X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=saml%2Fbinding%2Fimpl%2FSimpleSigningRule.cpp;h=7f1ea7f4c0a308c3ecea0d878e8d3519f2770973;hb=750aa26530f9e8993eae37cd9e68e25497be66b5;hp=3e7952dcd3e5a04f2e25adb137f256f87103b930;hpb=42c774ed39a783c3ba6b90c36ba87ce1bd874c09;p=shibboleth%2Fcpp-opensaml.git diff --git a/saml/binding/impl/SimpleSigningRule.cpp b/saml/binding/impl/SimpleSigningRule.cpp index 3e7952d..7f1ea7f 100644 --- a/saml/binding/impl/SimpleSigningRule.cpp +++ b/saml/binding/impl/SimpleSigningRule.cpp @@ -22,13 +22,11 @@ #include "internal.h" #include "exceptions.h" -#include "RootObject.h" #include "binding/HTTPRequest.h" #include "binding/SimpleSigningRule.h" #include "saml2/core/Protocols.h" #include "saml2/metadata/Metadata.h" #include "saml2/metadata/MetadataProvider.h" -#include "security/TrustEngine.h" #include #include @@ -69,12 +67,12 @@ namespace opensaml { }; -pair SimpleSigningRule::evaluate( - const GenericRequest& request, +pair SimpleSigningRule::evaluate( const XMLObject& message, + const GenericRequest* request, const MetadataProvider* metadataProvider, const QName* role, - const opensaml::TrustEngine* trustEngine + const TrustEngine* trustEngine ) const { Category& log=Category::getInstance(SAML_LOGCAT".SecurityPolicyRule.SimpleSigning"); @@ -82,18 +80,24 @@ pair SimpleSigningRule::evaluate( pair ret = pair(NULL,NULL); + const HTTPRequest* httpRequest = dynamic_cast(request); + if (!request || !httpRequest) { + log.debug("ignoring message, no HTTP protocol request available"); + return ret; + } + if (!metadataProvider || !role || !trustEngine) { log.debug("ignoring message, no metadata supplied"); return ret; } - const char* signature = request.getParameter("Signature"); + const char* signature = request->getParameter("Signature"); if (!signature) { log.debug("ignoring unsigned message"); return ret; } - const char* sigAlgorithm = request.getParameter("SigAlg"); + const char* sigAlgorithm = request->getParameter("SigAlg"); if (!sigAlgorithm) { log.error("SigAlg parameter not found, no way to verify the signature"); return ret; @@ -118,31 +122,47 @@ pair SimpleSigningRule::evaluate( return ret; } - log.debug("matched assertion issuer against metadata, searching for applicable role..."); + log.debug("matched message issuer against metadata, searching for applicable role..."); const RoleDescriptor* roledesc=entity->getRoleDescriptor(*role, issuerInfo.second); if (!roledesc) { log.warn("unable to find compatible role (%s) in metadata", role->toString().c_str()); return ret; } - // We have to construct a string containing the signature input by accessing the - // request directly. We can't use the decoded parameters because we need the raw - // data and URL-encoding isn't canonical. string input; - const HTTPRequest& httpRequest = dynamic_cast(request); - const char* raw = - (!strcmp(httpRequest.getMethod(), "GET")) ? httpRequest.getQueryString() : httpRequest.getRequestBody(); - if (!appendParameter(input, raw, "SAMLRequest=")) - appendParameter(input, raw, "SAMLResponse="); - appendParameter(input, raw, "RelayState="); - appendParameter(input, raw, "SigAlg="); + const char* pch; + if (!strcmp(httpRequest->getMethod(), "GET")) { + // We have to construct a string containing the signature input by accessing the + // request directly. We can't use the decoded parameters because we need the raw + // data and URL-encoding isn't canonical. + pch = httpRequest->getQueryString(); + if (!appendParameter(input, pch, "SAMLRequest=")) + appendParameter(input, pch, "SAMLResponse="); + appendParameter(input, pch, "RelayState="); + appendParameter(input, pch, "SigAlg="); + } + else { + // With POST, the input string is concatenated from the decoded form controls. + // GET should be this way too, but I messed up the spec, sorry. + pch = httpRequest->getParameter("SAMLRequest"); + if (pch) + input = string("SAMLRequest=") + pch; + else { + pch = httpRequest->getParameter("SAMLResponse"); + input = string("SAMLResponse=") + pch; + } + pch = httpRequest->getParameter("RelayState"); + if (pch) + input = input + "&RelayState=" + pch; + input = input + "&SigAlg=" + sigAlgorithm; + } // Check for KeyInfo, but defensively (we might be able to run without it). KeyInfo* keyInfo=NULL; - const char* k = request.getParameter("KeyInfo"); - if (k) { + pch = request->getParameter("KeyInfo"); + if (pch) { try { - istringstream kstrm(k); + istringstream kstrm(pch); DOMDocument* doc = XMLToolingConfig::getConfig().getParser().parse(kstrm); XercesJanitor janitor(doc); XMLObject* kxml = XMLObjectBuilder::buildOneFromElement(doc->getDocumentElement(), true); @@ -185,13 +205,12 @@ pair SimpleSigningRule::getIssuerAndProtocol(const // Shortcuts some of the casting. const XMLCh* ns = message.getElementQName().getNamespaceURI(); if (ns) { - if (XMLString::equals(ns, samlconstants::SAML20P_NS) || XMLString::equals(ns, samlconstants::SAML20_NS)) { + if (XMLString::equals(ns, samlconstants::SAML20P_NS)) { // 2.0 namespace should be castable to a specialized 2.0 root. const saml2::RootObject& root = dynamic_cast(message); saml2::Issuer* issuer = root.getIssuer(); - if (issuer && issuer->getName()) { + if (issuer && issuer->getName()) return make_pair(issuer->cloneIssuer(), samlconstants::SAML20P_NS); - } // No issuer in the message, so we have to try the Response approach. const vector& assertions = dynamic_cast(message).getAssertions();