#include "saml2/core/Protocols.h"
#include <xmltooling/logging.h>
+#include <xmltooling/io/HTTPRequest.h>
#include <xmltooling/soap/SOAP.h>
#include <xmltooling/util/NDC.h>
+#include <xmltooling/util/Predicates.h>
#include <xmltooling/validation/ValidatorSuite.h>
using namespace opensaml::saml2p;
Category& log = Category::getInstance(SAML_LOGCAT".MessageDecoder.SAML2ECP");
log.debug("validating input");
+ const HTTPRequest* httpRequest=dynamic_cast<const HTTPRequest*>(&genericRequest);
+ if (!httpRequest)
+ throw BindingException("Unable to cast request object to HTTPRequest type.");
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");
policy.reset(true);
extractMessageDetails(*response, genericRequest, samlconstants::SAML20P_NS, policy);
policy.evaluate(*response, &genericRequest);
-
+
+ // Check destination URL.
+ auto_ptr_char dest(response->getDestination());
+ const char* dest2 = httpRequest->getRequestURL();
+ const char* delim = strchr(dest2, '?');
+ if (response->getSignature() && (!dest.get() || !*(dest.get()))) {
+ log.error("signed SAML message missing Destination attribute");
+ throw BindingException("Signed SAML message missing Destination attribute identifying intended destination.");
+ }
+ else if (dest.get() && *dest.get() && ((delim && strncmp(dest.get(), dest2, delim - dest2)) || (!delim && strcmp(dest.get(),dest2)))) {
+ log.error("PAOS response targeted at (%s), but delivered to (%s)", dest.get(), dest2);
+ 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();
- for (vector<XMLObject*>::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<const ElementProxy*>(*h);
- if (ep) {
- auto_ptr_char rs(ep->getTextContent());
- if (rs.get()) {
- relayState = rs.get();
- break;
- }
- }
- }
+ vector<XMLObject*>::const_iterator h =
+ find_if(blocks.begin(), blocks.end(), hasQName(QName(samlconstants::SAML20ECP_NS, RelayState)));
+ const ElementProxy* ep = dynamic_cast<const ElementProxy*>(h != blocks.end() ? *h : NULL);
+ if (ep) {
+ auto_ptr_char rs(ep->getTextContent());
+ if (rs.get())
+ relayState = rs.get();
}
}