[cpp-opensaml] branch master updated: CPPOST-112 - Clean up message correlation in relevant policy rules
Scott Cantor
cantor.2 at osu.edu
Tue Feb 11 12:59:08 EST 2020
This is an automated email from the git hooks/post-receive script.
scantor pushed a commit to branch master
in repository cpp-opensaml.
View the commit online:
http://git.shibboleth.net/view/?p=cpp-opensaml.git;a=commit;h=eae759ea5c32951115f4248f4bc6040d7e28635f
The following commit(s) were added to refs/heads/master by this push:
new eae759e CPPOST-112 - Clean up message correlation in relevant policy rules
eae759e is described below
commit eae759ea5c32951115f4248f4bc6040d7e28635f
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Tue Feb 11 12:57:50 2020 -0500
CPPOST-112 - Clean up message correlation in relevant policy rules
https://issues.shibboleth.net/jira/browse/CPPOST-112
Initial implementation of toggleable correlation support.
---
Projects/vc15/saml/saml.vcxproj | 4 +-
Projects/vc15/saml/saml.vcxproj.filters | 6 ++
saml/Makefile.am | 2 +
saml/binding/MessageDecoder.h | 33 ++++++++--
saml/binding/SecurityPolicy.h | 18 +++++-
saml/binding/impl/MessageDecoder.cpp | 21 ++++++
saml/binding/impl/MessageFlowRule.cpp | 21 ++++++
saml/binding/impl/SecurityPolicy.cpp | 12 ++++
saml/saml1/binding/impl/SAML1ArtifactDecoder.cpp | 2 +
saml/saml1/binding/impl/SAML1MessageDecoder.cpp | 2 +
saml/saml1/binding/impl/SAML1POSTDecoder.cpp | 2 +
saml/saml1/binding/impl/SAML1SOAPClient.cpp | 9 ++-
saml/saml1/binding/impl/SAML1SOAPDecoder.cpp | 2 +
saml/saml2/binding/SAML2MessageDecoder.h | 21 ++++++
...SAML2MessageDecoder.h => SAML2MessageEncoder.h} | 38 +++++++----
saml/saml2/binding/impl/SAML2ArtifactDecoder.cpp | 4 ++
saml/saml2/binding/impl/SAML2ArtifactEncoder.cpp | 13 ++--
saml/saml2/binding/impl/SAML2ECPDecoder.cpp | 35 ++++++----
saml/saml2/binding/impl/SAML2ECPEncoder.cpp | 11 ++--
saml/saml2/binding/impl/SAML2MessageDecoder.cpp | 39 ++++++++++++
saml/saml2/binding/impl/SAML2MessageEncoder.cpp | 74 ++++++++++++++++++++++
saml/saml2/binding/impl/SAML2POSTDecoder.cpp | 4 ++
saml/saml2/binding/impl/SAML2POSTEncoder.cpp | 11 ++--
saml/saml2/binding/impl/SAML2RedirectDecoder.cpp | 4 ++
saml/saml2/binding/impl/SAML2RedirectEncoder.cpp | 14 ++--
saml/saml2/binding/impl/SAML2SOAPClient.cpp | 6 +-
saml/saml2/binding/impl/SAML2SOAPDecoder.cpp | 2 +
saml/saml2/binding/impl/SAML2SOAPEncoder.cpp | 8 +--
saml/saml2/profile/impl/BearerConfirmationRule.cpp | 15 ++++-
samltest/saml1/binding/SAML1ArtifactTest.h | 2 +-
samltest/saml1/binding/SAML1POSTTest.h | 2 +-
samltest/saml2/binding/SAML2ArtifactTest.h | 2 +-
samltest/saml2/binding/SAML2POSTTest.h | 2 +-
samltest/saml2/binding/SAML2RedirectTest.h | 2 +-
34 files changed, 356 insertions(+), 87 deletions(-)
diff --git a/Projects/vc15/saml/saml.vcxproj b/Projects/vc15/saml/saml.vcxproj
index f3713a5..5b4cc9d 100644
--- a/Projects/vc15/saml/saml.vcxproj
+++ b/Projects/vc15/saml/saml.vcxproj
@@ -191,6 +191,7 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
+ <ClCompile Include="..\..\..\saml\saml2\binding\impl\SAML2MessageEncoder.cpp" />
<ClCompile Include="..\..\..\saml\saml2\metadata\impl\AbstractDynamicMetadataProvider.cpp" />
<ClCompile Include="..\..\..\saml\saml2\metadata\impl\DiscoverableMetadataProvider.cpp" />
<ClCompile Include="..\..\..\saml\saml2\metadata\impl\EntityAttributesEntityMatcher.cpp" />
@@ -297,6 +298,7 @@
<ClInclude Include="..\..\..\saml\exceptions.h" />
<ClInclude Include="..\..\..\saml\internal.h" />
<ClInclude Include="..\..\..\saml\RootObject.h" />
+ <ClInclude Include="..\..\..\saml\saml2\binding\SAML2MessageEncoder.h" />
<ClInclude Include="..\..\..\saml\saml2\metadata\AbstractDynamicMetadataProvider.h" />
<ClInclude Include="..\..\..\saml\saml2\metadata\DiscoverableMetadataProvider.h" />
<ClInclude Include="..\..\..\saml\saml2\metadata\EntityMatcher.h" />
@@ -346,4 +348,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
-</Project>
+</Project>
\ No newline at end of file
diff --git a/Projects/vc15/saml/saml.vcxproj.filters b/Projects/vc15/saml/saml.vcxproj.filters
index 4598f4b..bc13cb4 100644
--- a/Projects/vc15/saml/saml.vcxproj.filters
+++ b/Projects/vc15/saml/saml.vcxproj.filters
@@ -363,6 +363,9 @@
<ClCompile Include="..\..\..\saml\saml2\metadata\impl\LocalDynamicMetadataProvider.cpp">
<Filter>Source Files\saml2\metadata\impl</Filter>
</ClCompile>
+ <ClCompile Include="..\..\..\saml\saml2\binding\impl\SAML2MessageEncoder.cpp">
+ <Filter>Source Files\saml2\binding\impl</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\..\saml\Assertion.h">
@@ -497,6 +500,9 @@
<ClInclude Include="..\..\..\saml\saml2\metadata\AbstractDynamicMetadataProvider.h">
<Filter>Header Files\saml2\metadata</Filter>
</ClInclude>
+ <ClInclude Include="..\..\..\saml\saml2\binding\SAML2MessageEncoder.h">
+ <Filter>Header Files\saml2\binding</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\..\..\saml\saml.rc">
diff --git a/saml/Makefile.am b/saml/Makefile.am
index 251a314..48b003f 100644
--- a/saml/Makefile.am
+++ b/saml/Makefile.am
@@ -73,6 +73,7 @@ saml2bindinclude_HEADERS = \
saml2/binding/SAML2Artifact.h \
saml2/binding/SAML2ArtifactType0004.h \
saml2/binding/SAML2MessageDecoder.h \
+ saml2/binding/SAML2MessageEncoder.h \
saml2/binding/SAML2SOAPClient.h
saml2mdinclude_HEADERS = \
@@ -161,6 +162,7 @@ libsaml_la_SOURCES = \
saml2/binding/impl/SAML2ECPDecoder.cpp \
saml2/binding/impl/SAML2ECPEncoder.cpp \
saml2/binding/impl/SAML2MessageDecoder.cpp \
+ saml2/binding/impl/SAML2MessageEncoder.cpp \
saml2/binding/impl/SAML2POSTDecoder.cpp \
saml2/binding/impl/SAML2POSTEncoder.cpp \
saml2/binding/impl/SAML2RedirectDecoder.cpp \
diff --git a/saml/binding/MessageDecoder.h b/saml/binding/MessageDecoder.h
index d93c7c9..c7f5186 100644
--- a/saml/binding/MessageDecoder.h
+++ b/saml/binding/MessageDecoder.h
@@ -34,6 +34,7 @@
namespace xmltooling {
class XMLTOOL_API GenericRequest;
+ class XMLTOOL_API GenericResponse;
class XMLTOOL_API XMLObject;
};
@@ -150,13 +151,9 @@ namespace opensaml {
void setArtifactResolver(const ArtifactResolver* artifactResolver);
/**
- * Decodes a transport request into a SAML protocol message, and evaluates it
- * against a supplied SecurityPolicy. If the transport request does not contain
- * the information necessary to decode the request, nullptr will be returned.
- * Errors during the decoding process will be raised as exceptions.
+ * @Deprecated
*
- * <p>Artifact-based bindings require an ArtifactResolver be set to
- * turn an artifact into the corresponding message.
+ * The future version is the variant below that also takes a response object.
*
* @param relayState will be set to RelayState/TARGET value accompanying message
* @param genericRequest reference to interface for accessing transport request to decode
@@ -167,7 +164,29 @@ namespace opensaml {
std::string& relayState,
const xmltooling::GenericRequest& genericRequest,
SecurityPolicy& policy
- ) const=0;
+ ) const;
+
+ /**
+ * Decodes a transport request into a SAML protocol message, and evaluates it
+ * against a supplied SecurityPolicy. If the transport request does not contain
+ * the information necessary to decode the request, nullptr will be returned.
+ * Errors during the decoding process will be raised as exceptions.
+ *
+ * <p>Artifact-based bindings require an ArtifactResolver be set to
+ * turn an artifact into the corresponding message.</p>
+ *
+ * @param relayState will be set to RelayState/TARGET value accompanying message
+ * @param genericRequest reference to interface for accessing transport request to decode
+ * @param genericResponse optional interface for accessing transport response
+ * @param policy reference to policy containing rules, MetadataProvider, TrustEngine, etc.
+ * @return the decoded message, or nullptr if the decoder did not recognize the request content
+ */
+ virtual xmltooling::XMLObject* decode(
+ std::string& relayState,
+ const xmltooling::GenericRequest& genericRequest,
+ xmltooling::GenericResponse* genericResponse,
+ SecurityPolicy& policy
+ ) const;
protected:
MessageDecoder();
diff --git a/saml/binding/SecurityPolicy.h b/saml/binding/SecurityPolicy.h
index 47b29ec..b7ecc18 100644
--- a/saml/binding/SecurityPolicy.h
+++ b/saml/binding/SecurityPolicy.h
@@ -159,6 +159,14 @@ namespace opensaml {
const XMLCh* getCorrelationID() const;
/**
+ * Returns the message identifier to which the message being evaluated
+ * claims to be a response.
+ *
+ * @return correlatable message identifier
+ */
+ const XMLCh* getInResponseTo() const;
+
+ /**
* Gets a mutable array of installed policy rules.
*
* <p>If adding rules, their lifetime must be at least as long as the policy object.
@@ -234,6 +242,14 @@ namespace opensaml {
void setCorrelationID(const XMLCh* correlationID);
/**
+ * Sets the message identifier to which the message being evaluated
+ * was responding (i.e., the value to be compared to the correlation ID).
+ *
+ * @param id correlatable message identifier
+ */
+ void setInResponseTo(const XMLCh* id);
+
+ /**
* Evaluates the policy against the given request and message,
* possibly populating message information in the policy object.
*
@@ -418,7 +434,7 @@ namespace opensaml {
// contextual information
mutable time_t m_ts;
- xmltooling::xstring m_correlationID;
+ xmltooling::xstring m_correlationID, m_inResponseTo;
std::vector<xmltooling::xstring> m_audiences;
};
diff --git a/saml/binding/impl/MessageDecoder.cpp b/saml/binding/impl/MessageDecoder.cpp
index 6e4bcc8..d2d60d9 100644
--- a/saml/binding/impl/MessageDecoder.cpp
+++ b/saml/binding/impl/MessageDecoder.cpp
@@ -25,6 +25,7 @@
*/
#include "internal.h"
+#include "exceptions.h"
#include "binding/MessageDecoder.h"
#include "saml2/metadata/EndpointManager.h"
#include "saml2/metadata/Metadata.h"
@@ -115,3 +116,23 @@ bool MessageDecoder::ArtifactResolver::isSupported(const SSODescriptorType& ssoD
return false;
}
+
+XMLObject* MessageDecoder::decode(
+ std::string& relayState,
+ const xmltooling::GenericRequest& genericRequest,
+ SecurityPolicy& policy
+ ) const
+{
+ // Default just calls new version.
+ return decode(relayState, genericRequest, nullptr, policy);
+}
+
+XMLObject* MessageDecoder::decode(
+ std::string& relayState,
+ const xmltooling::GenericRequest& genericRequest,
+ xmltooling::GenericResponse* genericResponse,
+ SecurityPolicy& policy
+ ) const
+{
+ throw BindingException("Unimplemented decode method");
+}
diff --git a/saml/binding/impl/MessageFlowRule.cpp b/saml/binding/impl/MessageFlowRule.cpp
index d9a4b96..ac98e94 100644
--- a/saml/binding/impl/MessageFlowRule.cpp
+++ b/saml/binding/impl/MessageFlowRule.cpp
@@ -54,6 +54,7 @@ namespace opensaml {
private:
bool m_checkReplay;
+ bool m_correlation;
time_t m_expires;
};
@@ -64,10 +65,12 @@ namespace opensaml {
};
static const XMLCh checkReplay[] = UNICODE_LITERAL_11(c,h,e,c,k,R,e,p,l,a,y);
+static const XMLCh checkCorrelation[] = UNICODE_LITERAL_16(c,h,e,c,k,C,o,r,r,e,l,a,t,i,o,n);
static const XMLCh expires[] = UNICODE_LITERAL_7(e,x,p,i,r,e,s);
MessageFlowRule::MessageFlowRule(const DOMElement* e)
: m_checkReplay(XMLHelper::getAttrBool(e, true, checkReplay)),
+ m_correlation(XMLHelper::getAttrBool(e, false, checkCorrelation)),
m_expires(XMLHelper::getAttrInt(e, XMLToolingConfig::getConfig().clock_skew_secs, expires))
{
}
@@ -96,6 +99,24 @@ bool MessageFlowRule::evaluate(const XMLObject& message, const GenericRequest* r
}
}
+ if (m_correlation) {
+ if (policy.getCorrelationID() && *(policy.getCorrelationID())) {
+ if (!XMLString::equals(policy.getCorrelationID(), policy.getInResponseTo())) {
+ log.warn("Response correlation ID did not match request ID");
+ auto_ptr_char requestID(policy.getCorrelationID());
+ throw SecurityPolicyException("Rejecting non-correlated response to request ID ($1).",
+ params(1, requestID.get()));
+ }
+ }
+ else if (policy.getInResponseTo() && *(policy.getInResponseTo())) {
+ log.warn("Response correlation failed due to lack of request ID to compare against");
+ throw SecurityPolicyException("Response correlation failed with lack of correlation ID");
+ }
+ }
+ else {
+ log.debug("ignoring InResponseTo, correlation checking is disabled");
+ }
+
// Check replay.
if (m_checkReplay) {
const XMLCh* id = policy.getMessageID();
diff --git a/saml/binding/impl/SecurityPolicy.cpp b/saml/binding/impl/SecurityPolicy.cpp
index e772a62..0cb436f 100644
--- a/saml/binding/impl/SecurityPolicy.cpp
+++ b/saml/binding/impl/SecurityPolicy.cpp
@@ -163,6 +163,11 @@ const XMLCh* SecurityPolicy::getCorrelationID() const
return m_correlationID.c_str();
}
+const XMLCh* SecurityPolicy::getInResponseTo() const
+{
+ return m_inResponseTo.c_str();
+}
+
vector<const SecurityPolicyRule*>& SecurityPolicy::getRules()
{
return m_rules;
@@ -212,6 +217,13 @@ void SecurityPolicy::setCorrelationID(const XMLCh* correlationID)
m_correlationID = correlationID;
}
+void SecurityPolicy::setInResponseTo(const XMLCh* id)
+{
+ m_inResponseTo.erase();
+ if (id)
+ m_inResponseTo = id;
+}
+
void SecurityPolicy::evaluate(const XMLObject& message, const GenericRequest* request)
{
for_each(
diff --git a/saml/saml1/binding/impl/SAML1ArtifactDecoder.cpp b/saml/saml1/binding/impl/SAML1ArtifactDecoder.cpp
index bb2a579..d131668 100644
--- a/saml/saml1/binding/impl/SAML1ArtifactDecoder.cpp
+++ b/saml/saml1/binding/impl/SAML1ArtifactDecoder.cpp
@@ -59,6 +59,7 @@ namespace opensaml {
xmltooling::XMLObject* decode(
std::string& relayState,
const GenericRequest& genericRequest,
+ GenericResponse* genericResponse,
SecurityPolicy& policy
) const;
};
@@ -73,6 +74,7 @@ namespace opensaml {
XMLObject* SAML1ArtifactDecoder::decode(
string& relayState,
const GenericRequest& genericRequest,
+ GenericResponse* genericResponse,
SecurityPolicy& policy
) const
{
diff --git a/saml/saml1/binding/impl/SAML1MessageDecoder.cpp b/saml/saml1/binding/impl/SAML1MessageDecoder.cpp
index bf5c673..4a37db9 100644
--- a/saml/saml1/binding/impl/SAML1MessageDecoder.cpp
+++ b/saml/saml1/binding/impl/SAML1MessageDecoder.cpp
@@ -89,6 +89,8 @@ void SAML1MessageDecoder::extractMessageDetails(
return;
}
+ policy.setInResponseTo(response->getInResponseTo());
+
log.debug("extracting issuer from SAML 1.x Response");
const vector<saml1::Assertion*>& assertions = response->getAssertions();
if (assertions.empty()) {
diff --git a/saml/saml1/binding/impl/SAML1POSTDecoder.cpp b/saml/saml1/binding/impl/SAML1POSTDecoder.cpp
index d32a02d..83a17eb 100644
--- a/saml/saml1/binding/impl/SAML1POSTDecoder.cpp
+++ b/saml/saml1/binding/impl/SAML1POSTDecoder.cpp
@@ -62,6 +62,7 @@ namespace opensaml {
xmltooling::XMLObject* decode(
std::string& relayState,
const GenericRequest& genericRequest,
+ GenericResponse* genericResponse,
SecurityPolicy& policy
) const;
};
@@ -76,6 +77,7 @@ namespace opensaml {
XMLObject* SAML1POSTDecoder::decode(
string& relayState,
const GenericRequest& genericRequest,
+ GenericResponse* genericResponse,
SecurityPolicy& policy
) const
{
diff --git a/saml/saml1/binding/impl/SAML1SOAPClient.cpp b/saml/saml1/binding/impl/SAML1SOAPClient.cpp
index e436b47..d57fe00 100644
--- a/saml/saml1/binding/impl/SAML1SOAPClient.cpp
+++ b/saml/saml1/binding/impl/SAML1SOAPClient.cpp
@@ -74,10 +74,6 @@ Response* SAML1SOAPClient::receiveSAML()
Response* response = dynamic_cast<Response*>(body->getUnknownXMLObjects().front());
if (response) {
- // Check InResponseTo.
- if (m_correlate && response->getInResponseTo() && !XMLString::equals(m_correlate, response->getInResponseTo()))
- throw SecurityPolicyException("InResponseTo attribute did not correlate with the Request ID.");
-
m_soaper.getPolicy().reset(true);
// Extract Response details and run policy against it.
@@ -85,8 +81,11 @@ Response* SAML1SOAPClient::receiveSAML()
// alternate issuers at that layer.
m_soaper.getPolicy().setMessageID(response->getResponseID());
m_soaper.getPolicy().setIssueInstant(response->getIssueInstantEpoch());
+ m_soaper.getPolicy().setInResponseTo(response->getInResponseTo());
+ m_soaper.getPolicy().setCorrelationID(m_correlate);
+
m_soaper.getPolicy().evaluate(*response);
-
+
// Check Status.
Status* status = response->getStatus();
if (status) {
diff --git a/saml/saml1/binding/impl/SAML1SOAPDecoder.cpp b/saml/saml1/binding/impl/SAML1SOAPDecoder.cpp
index 2dbba34..8aaf548 100644
--- a/saml/saml1/binding/impl/SAML1SOAPDecoder.cpp
+++ b/saml/saml1/binding/impl/SAML1SOAPDecoder.cpp
@@ -60,6 +60,7 @@ namespace opensaml {
xmltooling::XMLObject* decode(
std::string& relayState,
const GenericRequest& genericRequest,
+ GenericResponse* genericResponse,
SecurityPolicy& policy
) const;
};
@@ -74,6 +75,7 @@ namespace opensaml {
XMLObject* SAML1SOAPDecoder::decode(
string& relayState,
const GenericRequest& genericRequest,
+ GenericResponse* genericResponse,
SecurityPolicy& policy
) const
{
diff --git a/saml/saml2/binding/SAML2MessageDecoder.h b/saml/saml2/binding/SAML2MessageDecoder.h
index 6248468..a659b15 100644
--- a/saml/saml2/binding/SAML2MessageDecoder.h
+++ b/saml/saml2/binding/SAML2MessageDecoder.h
@@ -29,6 +29,11 @@
#include <saml/binding/MessageDecoder.h>
+namespace xmltooling {
+ class HTTPRequest;
+ class HTTPResponse;
+}
+
namespace opensaml {
namespace saml2p {
@@ -41,6 +46,22 @@ namespace opensaml {
SAML2MessageDecoder();
virtual ~SAML2MessageDecoder();
+ /**
+ * If relay state is provided, the previous request ID is extracted from a correlation cookie
+ * and supplied to the policy.
+ *
+ * @param request HTTP request
+ * @param response optional HTTP response
+ * @param relayState the RelayState token
+ * @param policy the SecurityPolicy to attach the ID to
+ */
+ void extractCorrelationID(
+ const xmltooling::HTTPRequest& request,
+ xmltooling::HTTPResponse* response,
+ const std::string& relayState,
+ SecurityPolicy& policy
+ ) const;
+
public:
const XMLCh* getProtocolFamily() const;
void extractMessageDetails (
diff --git a/saml/saml2/binding/SAML2MessageDecoder.h b/saml/saml2/binding/SAML2MessageEncoder.h
similarity index 56%
copy from saml/saml2/binding/SAML2MessageDecoder.h
copy to saml/saml2/binding/SAML2MessageEncoder.h
index 6248468..8b153b5 100644
--- a/saml/saml2/binding/SAML2MessageDecoder.h
+++ b/saml/saml2/binding/SAML2MessageEncoder.h
@@ -24,33 +24,43 @@
* Base class for SAML 2.0 MessageDecoders.
*/
-#ifndef __saml2_msgdecoder_h__
-#define __saml2_msgdecoder_h__
+#ifndef __saml2_msgencoder_h__
+#define __saml2_msgencoder_h__
-#include <saml/binding/MessageDecoder.h>
+#include <saml/binding/MessageEncoder.h>
+#include <saml/saml2/core/Protocols.h>
+
+namespace xmltooling {
+ class HTTPResponse;
+}
namespace opensaml {
namespace saml2p {
/**
- * Base class for SAML 2.0 MessageDecoders.
+ * Base class for SAML 2.0 MessageEncoders.
*/
- class SAML_API SAML2MessageDecoder : public MessageDecoder
+ class SAML_API SAML2MessageEncoder : public MessageEncoder
{
protected:
- SAML2MessageDecoder();
- virtual ~SAML2MessageDecoder();
+ SAML2MessageEncoder();
+ virtual ~SAML2MessageEncoder();
+
+ /**
+ * If the message is a request and relay state is provided, the request ID is preserved in a correlation cookie.
+ *
+ * @param response HTTP response
+ * @param message the SAML message
+ * @param relayState the RelayState token
+ */
+ void preserveCorrelationID(
+ xmltooling::HTTPResponse& response, const RequestAbstractType& message, const char* relayState
+ ) const;
public:
const XMLCh* getProtocolFamily() const;
- void extractMessageDetails (
- const xmltooling::XMLObject& message,
- const xmltooling::GenericRequest& genericRequest,
- const XMLCh* protocol,
- SecurityPolicy& policy
- ) const;
};
};
};
-#endif /* __saml2_msgdecoder_h__ */
+#endif /* __saml2_msgencoder_h__ */
diff --git a/saml/saml2/binding/impl/SAML2ArtifactDecoder.cpp b/saml/saml2/binding/impl/SAML2ArtifactDecoder.cpp
index dd35c99..724c01e 100644
--- a/saml/saml2/binding/impl/SAML2ArtifactDecoder.cpp
+++ b/saml/saml2/binding/impl/SAML2ArtifactDecoder.cpp
@@ -37,6 +37,7 @@
#include <xmltooling/logging.h>
#include <xmltooling/XMLToolingConfig.h>
#include <xmltooling/io/HTTPRequest.h>
+#include <xmltooling/io/HTTPResponse.h>
#include <xmltooling/util/NDC.h>
#include <xmltooling/util/ReplayCache.h>
@@ -60,6 +61,7 @@ namespace opensaml {
xmltooling::XMLObject* decode(
std::string& relayState,
const GenericRequest& genericRequest,
+ GenericResponse* genericResponse,
SecurityPolicy& policy
) const;
};
@@ -74,6 +76,7 @@ namespace opensaml {
XMLObject* SAML2ArtifactDecoder::decode(
string& relayState,
const GenericRequest& genericRequest,
+ GenericResponse* genericResponse,
SecurityPolicy& policy
) const
{
@@ -169,6 +172,7 @@ XMLObject* SAML2ArtifactDecoder::decode(
throw BindingException("ArtifactResponse message did not contain a protocol message.");
}
extractMessageDetails(*payload, genericRequest, samlconstants::SAML20P_NS, policy);
+ extractCorrelationID(*httpRequest, dynamic_cast<HTTPResponse*>(genericResponse), relayState, policy);
policy.evaluate(*payload, &genericRequest);
// Return the payload only.
diff --git a/saml/saml2/binding/impl/SAML2ArtifactEncoder.cpp b/saml/saml2/binding/impl/SAML2ArtifactEncoder.cpp
index caa095d..4b26087 100644
--- a/saml/saml2/binding/impl/SAML2ArtifactEncoder.cpp
+++ b/saml/saml2/binding/impl/SAML2ArtifactEncoder.cpp
@@ -27,8 +27,8 @@
#include "internal.h"
#include "exceptions.h"
#include "binding/ArtifactMap.h"
-#include "binding/MessageEncoder.h"
#include "saml2/binding/SAML2Artifact.h"
+#include "saml2/binding/SAML2MessageEncoder.h"
#include "saml2/core/Protocols.h"
#include "saml2/metadata/Metadata.h"
#include "signature/ContentReference.h"
@@ -56,16 +56,12 @@ using boost::scoped_ptr;
namespace opensaml {
namespace saml2p {
- class SAML_DLLLOCAL SAML2ArtifactEncoder : public MessageEncoder
+ class SAML_DLLLOCAL SAML2ArtifactEncoder : public SAML2MessageEncoder
{
public:
SAML2ArtifactEncoder(const DOMElement* e);
virtual ~SAML2ArtifactEncoder() {}
- const XMLCh* getProtocolFamily() const {
- return samlconstants::SAML20P_NS;
- }
-
long encode(
GenericResponse& genericResponse,
XMLObject* xmlObject,
@@ -159,7 +155,10 @@ long SAML2ArtifactEncoder::encode(
StatusResponseType* response = nullptr;
RequestAbstractType* request = dynamic_cast<RequestAbstractType*>(xmlObject);
- if (!request) {
+ if (request) {
+ preserveCorrelationID(*httpResponse, *request, relayState);
+ }
+ else {
response = dynamic_cast<StatusResponseType*>(xmlObject);
if (!response)
throw BindingException("XML content for SAML 2.0 HTTP-Artifact Encoder must be a SAML 2.0 protocol message.");
diff --git a/saml/saml2/binding/impl/SAML2ECPDecoder.cpp b/saml/saml2/binding/impl/SAML2ECPDecoder.cpp
index f57e593..610ac2f 100644
--- a/saml/saml2/binding/impl/SAML2ECPDecoder.cpp
+++ b/saml/saml2/binding/impl/SAML2ECPDecoder.cpp
@@ -33,6 +33,7 @@
#include <xmltooling/logging.h>
#include <xmltooling/XMLToolingConfig.h>
#include <xmltooling/io/HTTPRequest.h>
+#include <xmltooling/io/HTTPResponse.h>
#include <xmltooling/soap/SOAP.h>
#include <xmltooling/util/NDC.h>
#include <xmltooling/util/ParserPool.h>
@@ -57,6 +58,7 @@ namespace opensaml {
xmltooling::XMLObject* decode(
std::string& relayState,
const GenericRequest& genericRequest,
+ GenericResponse* genericResponse,
SecurityPolicy& policy
) const;
};
@@ -71,6 +73,7 @@ namespace opensaml {
XMLObject* SAML2ECPDecoder::decode(
string& relayState,
const GenericRequest& genericRequest,
+ GenericResponse* genericResponse,
SecurityPolicy& policy
) const
{
@@ -112,11 +115,29 @@ XMLObject* SAML2ECPDecoder::decode(
if (body && body->hasChildren()) {
Response* response = dynamic_cast<Response*>(body->getUnknownXMLObjects().front());
if (response) {
+
+ // Check for RelayState header.
+ if (env->getHeader()) {
+ static const XMLCh RelayState[] = UNICODE_LITERAL_10(R,e,l,a,y,S,t,a,t,e);
+ const vector<XMLObject*>& blocks = const_cast<const Header*>(env->getHeader())->getUnknownXMLObjects();
+ vector<XMLObject*>::const_iterator h =
+ find_if(blocks.begin(), blocks.end(), hasQName(xmltooling::QName(samlconstants::SAML20ECP_NS, RelayState)));
+ const ElementProxy* ep = dynamic_cast<const ElementProxy*>(h != blocks.end() ? *h : nullptr);
+ if (ep) {
+ auto_ptr_char rs(ep->getTextContent());
+ if (rs.get())
+ relayState = rs.get();
+ }
+ }
+
// 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);
+ if (httpRequest) {
+ extractCorrelationID(*httpRequest, dynamic_cast<HTTPResponse*>(genericResponse), relayState, policy);
+ }
policy.evaluate(*response, &genericRequest);
// Check destination URL if this is HTTP.
@@ -133,20 +154,6 @@ XMLObject* SAML2ECPDecoder::decode(
throw BindingException("SAML message delivered with PAOS to incorrect server URL.");
}
}
-
- // Check for RelayState header.
- if (env->getHeader()) {
- static const XMLCh RelayState[] = UNICODE_LITERAL_10(R,e,l,a,y,S,t,a,t,e);
- const vector<XMLObject*>& blocks = const_cast<const Header*>(env->getHeader())->getUnknownXMLObjects();
- vector<XMLObject*>::const_iterator h =
- find_if(blocks.begin(), blocks.end(), hasQName(xmltooling::QName(samlconstants::SAML20ECP_NS, RelayState)));
- const ElementProxy* ep = dynamic_cast<const ElementProxy*>(h != blocks.end() ? *h : nullptr);
- if (ep) {
- auto_ptr_char rs(ep->getTextContent());
- if (rs.get())
- relayState = rs.get();
- }
- }
xmlObject.release();
body->detach(); // frees Envelope
diff --git a/saml/saml2/binding/impl/SAML2ECPEncoder.cpp b/saml/saml2/binding/impl/SAML2ECPEncoder.cpp
index 9842605..1f3741a 100644
--- a/saml/saml2/binding/impl/SAML2ECPEncoder.cpp
+++ b/saml/saml2/binding/impl/SAML2ECPEncoder.cpp
@@ -26,9 +26,9 @@
#include "internal.h"
#include "exceptions.h"
-#include "binding/MessageEncoder.h"
#include "signature/ContentReference.h"
#include "saml1/core/Protocols.h"
+#include "saml2/binding/SAML2MessageEncoder.h"
#include "saml2/core/Protocols.h"
#include <sstream>
@@ -57,16 +57,12 @@ namespace opensaml {
static const XMLCh ProviderName[] = UNICODE_LITERAL_12(P, r, o, v, i, d, e, r, N, a, m, e);
- class SAML_DLLLOCAL SAML2ECPEncoder : public MessageEncoder
+ class SAML_DLLLOCAL SAML2ECPEncoder : public SAML2MessageEncoder
{
public:
SAML2ECPEncoder(const DOMElement* e);
virtual ~SAML2ECPEncoder() {}
- const XMLCh* getProtocolFamily() const {
- return samlconstants::SAML20P_NS;
- }
-
long encode(
GenericResponse& genericResponse,
XMLObject* xmlObject,
@@ -154,6 +150,9 @@ long SAML2ECPEncoder::encode(
httpResponse->setResponseHeader("Expires", "01-Jan-1997 12:00:00 GMT");
httpResponse->setResponseHeader("Cache-Control", "no-cache, no-store, must-revalidate, private");
httpResponse->setResponseHeader("Pragma", "no-cache");
+ if (request) {
+ preserveCorrelationID(*httpResponse, *request, relayState);
+ }
}
// Wrap it in a SOAP envelope.
diff --git a/saml/saml2/binding/impl/SAML2MessageDecoder.cpp b/saml/saml2/binding/impl/SAML2MessageDecoder.cpp
index d2e0a82..18e25d9 100644
--- a/saml/saml2/binding/impl/SAML2MessageDecoder.cpp
+++ b/saml/saml2/binding/impl/SAML2MessageDecoder.cpp
@@ -33,6 +33,10 @@
#include "util/SAMLConstants.h"
#include <xmltooling/logging.h>
+#include <xmltooling/XMLToolingConfig.h>
+#include <xmltooling/io/HTTPRequest.h>
+#include <xmltooling/io/HTTPResponse.h>
+#include <xmltooling/util/URLEncoder.h>
using namespace opensaml::saml2md;
using namespace opensaml::saml2p;
@@ -55,6 +59,36 @@ const XMLCh* SAML2MessageDecoder::getProtocolFamily() const
return samlconstants::SAML20P_NS;
}
+void SAML2MessageDecoder::extractCorrelationID(
+ const HTTPRequest& request, HTTPResponse* response, const string& relayState, SecurityPolicy& policy
+ ) const
+{
+ Category& log = Category::getInstance(SAML_LOGCAT ".MessageDecoder.SAML2");
+
+ if (!relayState.empty()) {
+ string cookie_name = string("_opensaml_req_").append(
+ XMLToolingConfig::getConfig().getURLEncoder()->encode(relayState.c_str()));
+ const char* cookie = request.getCookie(cookie_name.c_str());
+ if (cookie && *cookie) {
+ log.debug("recovered request/response correlation value (%s)", cookie);
+ char* dup = strdup(cookie);
+ XMLToolingConfig::getConfig().getURLEncoder()->decode(dup);
+ auto_ptr_XMLCh corrID(dup);
+ free(dup);
+ policy.setCorrelationID(corrID.get());
+ if (response) {
+ response->setCookie(cookie_name.c_str(), nullptr, 0, HTTPResponse::SAMESITE_NONE);
+ }
+ }
+ else {
+ log.debug("no request/response correlation cookie found");
+ }
+ }
+ else {
+ log.debug("no RelayState, unable to search for request/response correlation cookie");
+ }
+}
+
void SAML2MessageDecoder::extractMessageDetails(
const XMLObject& message, const GenericRequest& request, const XMLCh* protocol, SecurityPolicy& policy
) const
@@ -71,6 +105,11 @@ void SAML2MessageDecoder::extractMessageDetails(
policy.setMessageID(samlRoot.getID());
policy.setIssueInstant(samlRoot.getIssueInstantEpoch());
+ const saml2p::StatusResponseType* statusResponse = dynamic_cast<const saml2p::StatusResponseType*>(&message);
+ if (statusResponse) {
+ policy.setInResponseTo(statusResponse->getInResponseTo());
+ }
+
log.debug("extracting issuer from SAML 2.0 protocol message");
const Issuer* issuer = samlRoot.getIssuer();
if (issuer) {
diff --git a/saml/saml2/binding/impl/SAML2MessageEncoder.cpp b/saml/saml2/binding/impl/SAML2MessageEncoder.cpp
new file mode 100644
index 0000000..673dff9
--- /dev/null
+++ b/saml/saml2/binding/impl/SAML2MessageEncoder.cpp
@@ -0,0 +1,74 @@
+/**
+ * Licensed to the University Corporation for Advanced Internet
+ * Development, Inc. (UCAID) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for
+ * additional information regarding copyright ownership.
+ *
+ * UCAID licenses this file to you 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.
+ */
+
+/**
+ * SAML2MessageEncoder.cpp
+ *
+ * Base class for SAML 2.0 MessageEncoders.
+ */
+
+#include "internal.h"
+#include "saml2/binding/SAML2MessageEncoder.h"
+#include "saml2/core/Protocols.h"
+#include "util/SAMLConstants.h"
+
+#include <xmltooling/logging.h>
+#include <xmltooling/XMLToolingConfig.h>
+#include <xmltooling/io/HTTPResponse.h>
+#include <xmltooling/util/URLEncoder.h>
+
+using namespace opensaml::saml2p;
+using namespace opensaml::saml2;
+using namespace opensaml;
+using namespace xmltooling::logging;
+using namespace xmltooling;
+using namespace std;
+
+SAML2MessageEncoder::SAML2MessageEncoder()
+{
+}
+
+SAML2MessageEncoder::~SAML2MessageEncoder()
+{
+}
+
+const XMLCh* SAML2MessageEncoder::getProtocolFamily() const
+{
+ return samlconstants::SAML20P_NS;
+}
+
+void SAML2MessageEncoder::preserveCorrelationID(HTTPResponse& response, const RequestAbstractType& message, const char* relayState) const
+{
+ Category& log = Category::getInstance(SAML_LOGCAT ".MessageEncoder.SAML2");
+
+ if (relayState && *relayState) {
+ string cookie_name = string("_opensaml_req_").append(
+ XMLToolingConfig::getConfig().getURLEncoder()->encode(relayState));
+ auto_ptr_char id(message.getID());
+ log.debug("tracking request (%s) against RelayState token (%s)", id.get(), relayState);
+ response.setCookie(cookie_name.c_str(),
+ XMLToolingConfig::getConfig().getURLEncoder()->encode(id.get()).c_str(),
+ 0,
+ HTTPResponse::SAMESITE_NONE);
+ }
+ else {
+ log.debug("no relay state, request/response correlation is disabled");
+ }
+}
diff --git a/saml/saml2/binding/impl/SAML2POSTDecoder.cpp b/saml/saml2/binding/impl/SAML2POSTDecoder.cpp
index 1b7900e..534b8ff 100644
--- a/saml/saml2/binding/impl/SAML2POSTDecoder.cpp
+++ b/saml/saml2/binding/impl/SAML2POSTDecoder.cpp
@@ -38,6 +38,7 @@
#include <xmltooling/logging.h>
#include <xmltooling/XMLToolingConfig.h>
#include <xmltooling/io/HTTPRequest.h>
+#include <xmltooling/io/HTTPResponse.h>
#include <xmltooling/util/NDC.h>
#include <xmltooling/util/ParserPool.h>
#include <xmltooling/validation/ValidatorSuite.h>
@@ -61,6 +62,7 @@ namespace opensaml {
xmltooling::XMLObject* decode(
std::string& relayState,
const GenericRequest& genericRequest,
+ GenericResponse* genericResponse,
SecurityPolicy& policy
) const;
};
@@ -75,6 +77,7 @@ namespace opensaml {
XMLObject* SAML2POSTDecoder::decode(
std::string& relayState,
const GenericRequest& genericRequest,
+ GenericResponse* genericResponse,
SecurityPolicy& policy
) const
{
@@ -133,6 +136,7 @@ XMLObject* SAML2POSTDecoder::decode(
// Run through the policy.
extractMessageDetails(*root, genericRequest, samlconstants::SAML20P_NS, policy);
+ extractCorrelationID(*httpRequest, dynamic_cast<HTTPResponse*>(genericResponse), relayState, policy);
policy.evaluate(*root, &genericRequest);
// Check destination URL.
diff --git a/saml/saml2/binding/impl/SAML2POSTEncoder.cpp b/saml/saml2/binding/impl/SAML2POSTEncoder.cpp
index 453865a..ed84214 100644
--- a/saml/saml2/binding/impl/SAML2POSTEncoder.cpp
+++ b/saml/saml2/binding/impl/SAML2POSTEncoder.cpp
@@ -26,8 +26,8 @@
#include "internal.h"
#include "exceptions.h"
-#include "binding/MessageEncoder.h"
#include "signature/ContentReference.h"
+#include "saml2/binding/SAML2MessageEncoder.h"
#include "saml2/core/Protocols.h"
#include <fstream>
@@ -56,16 +56,12 @@ using boost::scoped_ptr;
namespace opensaml {
namespace saml2p {
- class SAML_DLLLOCAL SAML2POSTEncoder : public MessageEncoder
+ class SAML_DLLLOCAL SAML2POSTEncoder : public SAML2MessageEncoder
{
public:
SAML2POSTEncoder(const DOMElement* e, bool simple=false);
virtual ~SAML2POSTEncoder() {}
- const XMLCh* getProtocolFamily() const {
- return samlconstants::SAML20P_NS;
- }
-
long encode(
GenericResponse& genericResponse,
XMLObject* xmlObject,
@@ -249,6 +245,9 @@ long SAML2POSTEncoder::encode(
httpResponse->setResponseHeader("Expires", "01-Jan-1997 12:00:00 GMT");
httpResponse->setResponseHeader("Cache-Control", "no-cache, no-store, must-revalidate, private");
httpResponse->setResponseHeader("Pragma", "no-cache");
+ if (request) {
+ preserveCorrelationID(*httpResponse, *request, relayState);
+ }
}
long ret = genericResponse.sendResponse(s);
diff --git a/saml/saml2/binding/impl/SAML2RedirectDecoder.cpp b/saml/saml2/binding/impl/SAML2RedirectDecoder.cpp
index f58c819..ca46e57 100644
--- a/saml/saml2/binding/impl/SAML2RedirectDecoder.cpp
+++ b/saml/saml2/binding/impl/SAML2RedirectDecoder.cpp
@@ -36,6 +36,7 @@
#include <xmltooling/logging.h>
#include <xmltooling/XMLToolingConfig.h>
#include <xmltooling/io/HTTPRequest.h>
+#include <xmltooling/io/HTTPResponse.h>
#include <xmltooling/util/NDC.h>
#include <xmltooling/util/ParserPool.h>
#include <xmltooling/util/XMLHelper.h>
@@ -61,6 +62,7 @@ namespace opensaml {
xmltooling::XMLObject* decode(
std::string& relayState,
const GenericRequest& genericRequest,
+ GenericResponse* genericResponse,
SecurityPolicy& policy
) const;
};
@@ -75,6 +77,7 @@ namespace opensaml {
XMLObject* SAML2RedirectDecoder::decode(
string& relayState,
const GenericRequest& genericRequest,
+ GenericResponse* genericResponse,
SecurityPolicy& policy
) const
{
@@ -144,6 +147,7 @@ XMLObject* SAML2RedirectDecoder::decode(
// Run through the policy.
extractMessageDetails(*root, genericRequest, samlconstants::SAML20P_NS, policy);
+ extractCorrelationID(*httpRequest, dynamic_cast<HTTPResponse*>(genericResponse), relayState, policy);
policy.evaluate(*root, &genericRequest);
// Check destination URL.
diff --git a/saml/saml2/binding/impl/SAML2RedirectEncoder.cpp b/saml/saml2/binding/impl/SAML2RedirectEncoder.cpp
index ea98c7b..2e867d3 100644
--- a/saml/saml2/binding/impl/SAML2RedirectEncoder.cpp
+++ b/saml/saml2/binding/impl/SAML2RedirectEncoder.cpp
@@ -26,8 +26,7 @@
#include "internal.h"
#include "exceptions.h"
-#include "binding/MessageEncoder.h"
-#include "saml2/core/Protocols.h"
+#include "saml2/binding/SAML2MessageEncoder.h"
#include <fstream>
#include <sstream>
@@ -52,7 +51,7 @@ using namespace std;
namespace opensaml {
namespace saml2p {
- class SAML_DLLLOCAL SAML2RedirectEncoder : public MessageEncoder
+ class SAML_DLLLOCAL SAML2RedirectEncoder : public SAML2MessageEncoder
{
public:
SAML2RedirectEncoder() {}
@@ -62,10 +61,6 @@ namespace opensaml {
return true;
}
- const XMLCh* getProtocolFamily() const {
- return samlconstants::SAML20P_NS;
- }
-
long encode(
GenericResponse& genericResponse,
XMLObject* xmlObject,
@@ -112,7 +107,10 @@ long SAML2RedirectEncoder::encode(
StatusResponseType* response = nullptr;
RequestAbstractType* request = dynamic_cast<RequestAbstractType*>(xmlObject);
- if (!request) {
+ if (request) {
+ preserveCorrelationID(*httpResponse, *request, relayState);
+ }
+ else {
response = dynamic_cast<StatusResponseType*>(xmlObject);
if (!response)
throw BindingException("XML content for SAML 2.0 HTTP-Redirect Encoder must be a SAML 2.0 protocol message.");
diff --git a/saml/saml2/binding/impl/SAML2SOAPClient.cpp b/saml/saml2/binding/impl/SAML2SOAPClient.cpp
index 36898c2..da45caf 100644
--- a/saml/saml2/binding/impl/SAML2SOAPClient.cpp
+++ b/saml/saml2/binding/impl/SAML2SOAPClient.cpp
@@ -76,16 +76,14 @@ StatusResponseType* SAML2SOAPClient::receiveSAML()
// Check for SAML Response.
StatusResponseType* response = dynamic_cast<StatusResponseType*>(body->getUnknownXMLObjects().front());
if (response) {
- // Check InResponseTo.
- if (m_correlate && response->getInResponseTo() && !XMLString::equals(m_correlate, response->getInResponseTo()))
- throw SecurityPolicyException("InResponseTo attribute did not correlate with the Request ID.");
-
SecurityPolicy& policy = m_soaper.getPolicy();
policy.reset(true);
// Extract Response details.
policy.setMessageID(response->getID());
policy.setIssueInstant(response->getIssueInstantEpoch());
+ policy.setInResponseTo(response->getInResponseTo());
+ policy.setCorrelationID(m_correlate);
// Extract and re-verify Issuer if present.
const Issuer* issuer = response->getIssuer();
diff --git a/saml/saml2/binding/impl/SAML2SOAPDecoder.cpp b/saml/saml2/binding/impl/SAML2SOAPDecoder.cpp
index b16744f..812342b 100644
--- a/saml/saml2/binding/impl/SAML2SOAPDecoder.cpp
+++ b/saml/saml2/binding/impl/SAML2SOAPDecoder.cpp
@@ -60,6 +60,7 @@ namespace opensaml {
xmltooling::XMLObject* decode(
std::string& relayState,
const GenericRequest& genericRequest,
+ GenericResponse* genericResponse,
SecurityPolicy& policy
) const;
};
@@ -74,6 +75,7 @@ namespace opensaml {
XMLObject* SAML2SOAPDecoder::decode(
string& relayState,
const GenericRequest& genericRequest,
+ GenericResponse* genericResponse,
SecurityPolicy& policy
) const
{
diff --git a/saml/saml2/binding/impl/SAML2SOAPEncoder.cpp b/saml/saml2/binding/impl/SAML2SOAPEncoder.cpp
index ac9f1e9..a8785b0 100644
--- a/saml/saml2/binding/impl/SAML2SOAPEncoder.cpp
+++ b/saml/saml2/binding/impl/SAML2SOAPEncoder.cpp
@@ -26,8 +26,8 @@
#include "internal.h"
#include "exceptions.h"
-#include "binding/MessageEncoder.h"
#include "signature/ContentReference.h"
+#include "saml2/binding/SAML2MessageEncoder.h"
#include "saml2/core/Protocols.h"
#include <sstream>
@@ -48,7 +48,7 @@ using namespace std;
namespace opensaml {
namespace saml2p {
- class SAML_DLLLOCAL SAML2SOAPEncoder : public MessageEncoder
+ class SAML_DLLLOCAL SAML2SOAPEncoder : public SAML2MessageEncoder
{
public:
SAML2SOAPEncoder() {}
@@ -58,10 +58,6 @@ namespace opensaml {
return false;
}
- const XMLCh* getProtocolFamily() const {
- return samlconstants::SAML20P_NS;
- }
-
long encode(
GenericResponse& genericResponse,
XMLObject* xmlObject,
diff --git a/saml/saml2/profile/impl/BearerConfirmationRule.cpp b/saml/saml2/profile/impl/BearerConfirmationRule.cpp
index 8406348..745fa0e 100644
--- a/saml/saml2/profile/impl/BearerConfirmationRule.cpp
+++ b/saml/saml2/profile/impl/BearerConfirmationRule.cpp
@@ -107,12 +107,21 @@ bool BearerConfirmationRule::evaluate(const XMLObject& message, const GenericReq
}
}
- if (m_correlation && policy.getCorrelationID() && *(policy.getCorrelationID())) {
- if (!XMLString::equals(policy.getCorrelationID(), data ? data->getInResponseTo() : nullptr)) {
- msg = "bearer confirmation failed with request correlation mismatch";
+ if (m_correlation) {
+ if (policy.getCorrelationID() && *(policy.getCorrelationID())) {
+ if (!XMLString::equals(policy.getCorrelationID(), data ? data->getInResponseTo() : nullptr)) {
+ msg = "bearer confirmation failed with request correlation mismatch";
+ continue;
+ }
+ }
+ else if (data && data->getInResponseTo() && *(data->getInResponseTo())) {
+ msg = "bearer confirmation issued in response to request failed with lack of correlation ID";
continue;
}
}
+ else {
+ log.debug("ignoring InResponseTo, correlation checking is disabled");
+ }
if (m_validity) {
if (!data || !data->getNotOnOrAfter()) {
diff --git a/samltest/saml1/binding/SAML1ArtifactTest.h b/samltest/saml1/binding/SAML1ArtifactTest.h
index 1a7dc54..1d4d09d 100644
--- a/samltest/saml1/binding/SAML1ArtifactTest.h
+++ b/samltest/saml1/binding/SAML1ArtifactTest.h
@@ -86,7 +86,7 @@ public:
SAMLConfig::getConfig().MessageDecoderManager.newPlugin(samlconstants::SAML1_PROFILE_BROWSER_ARTIFACT, nullptr, false)
);
decoder->setArtifactResolver(this);
- scoped_ptr<Response> response(dynamic_cast<Response*>(decoder->decode(relayState,*this,policy)));
+ scoped_ptr<Response> response(dynamic_cast<Response*>(decoder->decode(relayState, *this, this, policy)));
// Test the results.
TSM_ASSERT_EQUALS("TARGET was not the expected result.", relayState, "state");
diff --git a/samltest/saml1/binding/SAML1POSTTest.h b/samltest/saml1/binding/SAML1POSTTest.h
index 8747cda..b4ac07e 100644
--- a/samltest/saml1/binding/SAML1POSTTest.h
+++ b/samltest/saml1/binding/SAML1POSTTest.h
@@ -93,7 +93,7 @@ public:
scoped_ptr<MessageDecoder> decoder(
SAMLConfig::getConfig().MessageDecoderManager.newPlugin(samlconstants::SAML1_PROFILE_BROWSER_POST, nullptr, false)
);
- scoped_ptr<Response> response(dynamic_cast<Response*>(decoder->decode(relayState,*this,policy)));
+ scoped_ptr<Response> response(dynamic_cast<Response*>(decoder->decode(relayState, *this, this, policy)));
// Test the results.
TSM_ASSERT_EQUALS("TARGET was not the expected result.", relayState, "state");
diff --git a/samltest/saml2/binding/SAML2ArtifactTest.h b/samltest/saml2/binding/SAML2ArtifactTest.h
index 1c6cd72..f71bcfd 100644
--- a/samltest/saml2/binding/SAML2ArtifactTest.h
+++ b/samltest/saml2/binding/SAML2ArtifactTest.h
@@ -87,7 +87,7 @@ public:
SAMLConfig::getConfig().MessageDecoderManager.newPlugin(samlconstants::SAML20_BINDING_HTTP_ARTIFACT, nullptr, false)
);
decoder->setArtifactResolver(this);
- scoped_ptr<Response> response(dynamic_cast<Response*>(decoder->decode(relayState,*this,policy)));
+ scoped_ptr<Response> response(dynamic_cast<Response*>(decoder->decode(relayState, *this, this, policy)));
// Test the results.
TSM_ASSERT_EQUALS("RelayState was not the expected result.", relayState, "state");
diff --git a/samltest/saml2/binding/SAML2POSTTest.h b/samltest/saml2/binding/SAML2POSTTest.h
index e6780e0..332795b 100644
--- a/samltest/saml2/binding/SAML2POSTTest.h
+++ b/samltest/saml2/binding/SAML2POSTTest.h
@@ -92,7 +92,7 @@ public:
scoped_ptr<MessageDecoder> decoder(
SAMLConfig::getConfig().MessageDecoderManager.newPlugin(samlconstants::SAML20_BINDING_HTTP_POST, nullptr, false)
);
- scoped_ptr<Response> response(dynamic_cast<Response*>(decoder->decode(relayState,*this,policy)));
+ scoped_ptr<Response> response(dynamic_cast<Response*>(decoder->decode(relayState, *this, this, policy)));
// Test the results.
TSM_ASSERT_EQUALS("RelayState was not the expected result.", relayState, "state");
diff --git a/samltest/saml2/binding/SAML2RedirectTest.h b/samltest/saml2/binding/SAML2RedirectTest.h
index 85bad24..c7f9f80 100644
--- a/samltest/saml2/binding/SAML2RedirectTest.h
+++ b/samltest/saml2/binding/SAML2RedirectTest.h
@@ -82,7 +82,7 @@ public:
scoped_ptr<MessageDecoder> decoder(
SAMLConfig::getConfig().MessageDecoderManager.newPlugin(samlconstants::SAML20_BINDING_HTTP_REDIRECT, nullptr, false)
);
- scoped_ptr<Response> response(dynamic_cast<Response*>(decoder->decode(relayState,*this,policy)));
+ scoped_ptr<Response> response(dynamic_cast<Response*>(decoder->decode(relayState, *this, this, policy)));
// Test the results.
TSM_ASSERT_EQUALS("RelayState was not the expected result.", relayState, "state");
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list