[shibboleth-sp2] 47/89: SSPCPP-528 - AttributeQuery Handler

Ferenc Wágner wferi at moszumanska.debian.org
Thu Sep 1 09:24:08 UTC 2016


This is an automated email from the git hooks/post-receive script.

wferi pushed a commit to branch master
in repository shibboleth-sp2.

commit fe9e6e5ab7fa78b7416ac7a0d8df48abbece4f5b
Author: Scott Cantor <cantor.2 at osu.edu>
Date:   Tue Jun 7 16:09:12 2016 -0400

    SSPCPP-528 - AttributeQuery Handler
    
    https://issues.shibboleth.net/jira/browse/SSPCPP-528
    
    Revert the design a bit by enhancing the handler APIs.
    Add control of NameQualifiers and handle missing entityID.
---
 plugins/AttributeResolverHandler.cpp    | 152 +++++++++++++-------------------
 shibsp/handler/AbstractHandler.h        |   8 +-
 shibsp/handler/impl/AbstractHandler.cpp |  28 +++---
 3 files changed, 81 insertions(+), 107 deletions(-)

diff --git a/plugins/AttributeResolverHandler.cpp b/plugins/AttributeResolverHandler.cpp
index 3fdbc9d..c509fbe 100644
--- a/plugins/AttributeResolverHandler.cpp
+++ b/plugins/AttributeResolverHandler.cpp
@@ -87,17 +87,14 @@ namespace shibsp {
     private:
         pair<bool,long> processMessage(
             const Application& application,
-            const char* protocol,
-            const char* entityID,
-            const char* format,
-            const char* nameID,
-            const char* encoding,
+            const HTTPRequest& httpRequest,
             HTTPResponse& httpResponse
             ) const;
 
 #ifndef SHIBSP_LITE
         ResolutionContext* resolveAttributes(
             const Application& application,
+            const HTTPRequest& httpRequest,
             const RoleDescriptor* issuer,
             const XMLCh* protocol,
             const saml1::NameIdentifier* v1nameid,
@@ -204,44 +201,15 @@ pair<bool,long> AttributeResolverHandler::run(SPRequest& request, bool isHandler
     request.setResponseHeader("Cache-Control","private,no-store,no-cache,max-age=0");
     request.setContentType("application/json; charset=utf-8");
 
-    pair<bool,const char*> param_protocol = getString("protocol", request, HANDLER_PROPERTY_REQUEST|HANDLER_PROPERTY_FIXED);
-    pair<bool,const char*> param_issuer = getString("entityID", request, HANDLER_PROPERTY_REQUEST|HANDLER_PROPERTY_FIXED);
-    pair<bool,const char*> param_format = getString("format", request, HANDLER_PROPERTY_REQUEST|HANDLER_PROPERTY_FIXED);
-    pair<bool,const char*> param_nameid = getString("nameId", request, HANDLER_PROPERTY_REQUEST|HANDLER_PROPERTY_FIXED);
-    pair<bool,const char*> param_encoding = getString("encoding", request, HANDLER_PROPERTY_REQUEST|HANDLER_PROPERTY_FIXED);
-
-    if (!param_nameid.first) {
-        m_log.error("AttributResolver handler requires nameId parameter");
-        istringstream msg("{}");
-        return make_pair(true, request.sendResponse(msg, HTTPResponse::XMLTOOLING_HTTP_STATUS_BADREQUEST));
-    }
-
     try {
         if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess)) {
             // When out of process, we run natively and directly process the message.
-            return processMessage(
-                request.getApplication(),
-                param_protocol.second,
-                param_issuer.second,
-                param_format.second,
-                param_nameid.second,
-                param_encoding.second,
-                request);
+            return processMessage(request.getApplication(), request, request);
         }
         else {
             // When not out of process, we remote all the message processing.
-            DDF out,in = DDF(m_address.c_str()).structure();
+            DDF out, in = wrap(request);
             DDFJanitor jin(in), jout(out);
-            in.addmember("application_id").string(request.getApplication().getId());
-            if (param_protocol.first)
-                in.addmember("protocol").string(param_protocol.second);
-            if (param_issuer.first)
-                in.addmember("entityID").string(param_issuer.second);
-            if (param_format.first)
-                in.addmember("format").string(param_format.second);
-            in.addmember("nameID").string(param_nameid.second);
-            if (param_encoding.first)
-                in.addmember("encoding").string(param_encoding.second);
             out=request.getServiceProvider().getListenerService()->send(in);
             return unwrap(request, out);
         }
@@ -264,30 +232,17 @@ void AttributeResolverHandler::receive(DDF& in, ostream& out)
         throw ConfigurationException("Unable to locate application for request, deleted?");
     }
 
-    const char* nameID = in["nameID"].string();
-    if (!nameID) {
-        // Something's horribly wrong.
-        m_log.error("no nameId parameter supplied for request");
-        throw FatalProfileException("Required nameId parameter not found");
-    }
-
     // Wrap a response shim.
     DDF ret(nullptr);
     DDFJanitor jout(ret);
     scoped_ptr<HTTPResponse> resp(getResponse(ret));
+    scoped_ptr<HTTPRequest> req(getRequest(in));
 
     // Since we're remoted, the result should either be a throw, a false/0 return,
     // which we just return as an empty structure, or a response/redirect,
     // which we capture in the facade and send back.
     try {
-        processMessage(
-            *app,
-            in["protocol"].string(),
-            in["entityID"].string(),
-            in["format"].string(),
-            in["nameID"].string(),
-            in["encoding"].string(),
-            *resp);
+        processMessage(*app, *req, *resp);
     }
     catch (std::exception& ex) {
         m_log.error("raising exception: %s", ex.what());
@@ -297,63 +252,77 @@ void AttributeResolverHandler::receive(DDF& in, ostream& out)
 }
 
 pair<bool,long> AttributeResolverHandler::processMessage(
-    const Application& application,
-    const char* protocol,
-    const char* entityID,
-    const char* format,
-    const char* nameID,
-    const char* encoding,
-    HTTPResponse& httpResponse
+    const Application& application, const HTTPRequest& httpRequest, HTTPResponse& httpResponse
     ) const
 {
 #ifndef SHIBSP_LITE
     stringstream msg;
 
-    const auto_ptr_XMLCh w_entityID(entityID);
-    const auto_ptr_XMLCh w_nameID(nameID);
-    const auto_ptr_XMLCh w_format(format);
-
-    if (protocol) {
-        if (!strcmp(protocol, "SAML2.0"))
-            protocol = "urn:oasis:names:tc:SAML:2.0:protocol"; // samlconstants::SAML20P_NS;
-        else if (!strcmp(protocol, "SAML1.1"))
-            protocol = "urn:oasis:names:tc:SAML:1.1:protocol"; // samlconstants::SAML11_PROTOCOL_ENUM;
-        else if (!strcmp(protocol, "SAML1.0"))
-            protocol = "urn:oasis:names:tc:SAML:1.0:protocol"; // samlconstants::SAML10_PROTOCOL_ENUM;
+    pair<bool,const char*> param_protocol = getString("protocol", httpRequest, HANDLER_PROPERTY_REQUEST|HANDLER_PROPERTY_FIXED);
+    pair<bool,const char*> param_issuer = getString("entityID", httpRequest, HANDLER_PROPERTY_REQUEST|HANDLER_PROPERTY_FIXED);
+    pair<bool,const char*> param_format = getString("format", httpRequest, HANDLER_PROPERTY_REQUEST|HANDLER_PROPERTY_FIXED);
+    pair<bool,const char*> param_qual = getString("nameQualifier", httpRequest, HANDLER_PROPERTY_REQUEST|HANDLER_PROPERTY_FIXED);
+    pair<bool,const char*> param_spqual = getString("spNameQualifier", httpRequest, HANDLER_PROPERTY_REQUEST|HANDLER_PROPERTY_FIXED);
+    pair<bool,const char*> param_nameid = getString("nameId", httpRequest, HANDLER_PROPERTY_REQUEST|HANDLER_PROPERTY_FIXED);
+    pair<bool,const char*> param_encoding = getString("encoding", httpRequest, HANDLER_PROPERTY_REQUEST|HANDLER_PROPERTY_FIXED);
+
+    if (!param_nameid.first) {
+        // Something's horribly wrong.
+        m_log.error("no nameId parameter supplied for request");
+        throw FatalProfileException("Required nameId parameter not found");
+    }
+
+    auto_ptr_XMLCh entityID(param_issuer.second);
+    auto_ptr_XMLCh nameID(param_nameid.second);
+    auto_ptr_XMLCh format(param_format.second);
+
+    if (param_protocol.first) {
+        if (!strcmp(param_protocol.second, "SAML2.0"))
+            param_protocol.second = "urn:oasis:names:tc:SAML:2.0:protocol"; // samlconstants::SAML20P_NS;
+        else if (!strcmp(param_protocol.second, "SAML1.1"))
+            param_protocol.second = "urn:oasis:names:tc:SAML:1.1:protocol"; // samlconstants::SAML11_PROTOCOL_ENUM;
+        else if (!strcmp(param_protocol.second, "SAML1.0"))
+            param_protocol.second = "urn:oasis:names:tc:SAML:1.0:protocol"; // samlconstants::SAML10_PROTOCOL_ENUM;
     }
     else {
-        protocol = "urn:oasis:names:tc:SAML:2.0:protocol"; // samlconstants::SAML20P_NS;
+        param_protocol.second = "urn:oasis:names:tc:SAML:2.0:protocol"; // samlconstants::SAML20P_NS;
     }
-    const auto_ptr_XMLCh w_protocol(protocol);
+    auto_ptr_XMLCh protocol(param_protocol.second);
 
     try {
-        scoped_ptr<ResolutionContext> ctx;
-
         MetadataProvider* m = application.getMetadataProvider();
         Locker mlock(m);
 
-        MetadataProviderCriteria mc(application, entityID, &IDPSSODescriptor::ELEMENT_QNAME, w_protocol.get());
-        pair<const EntityDescriptor*,const RoleDescriptor*> site = m->getEntityDescriptor(mc);
-        if (!site.first)
-            m_log.info("Unable to locate metadata for IdP (%s).", entityID);
+        pair<const EntityDescriptor*,const RoleDescriptor*> site = make_pair(nullptr, nullptr);
+        if (entityID.get()) {
+            MetadataProviderCriteria mc(application, entityID.get(), &IDPSSODescriptor::ELEMENT_QNAME, protocol.get());
+            site = m->getEntityDescriptor(mc);
+            if (!site.first)
+                m_log.info("Unable to locate metadata for IdP (%s).", param_issuer.second);
+        }
+
+        auto_ptr_XMLCh nameQualifier(param_qual.first ? param_qual.second : param_issuer.second);
+        auto_ptr_XMLCh spNameQualifier(param_spqual.first ? param_spqual.second
+            : application.getRelyingParty(site.first)->getString("entityID").second);
 
         // Build NameID(s).
         scoped_ptr<saml1::NameIdentifier> v1name;
         scoped_ptr<saml2::NameID> v2name(saml2::NameIDBuilder::buildNameID());
-        v2name->setName(w_nameID.get());
-        v2name->setFormat(w_format.get());
-        v2name->setNameQualifier(w_entityID.get());
-        v2name->setSPNameQualifier(application.getRelyingParty(site.first)->getXMLString("entityID").second);
-        if (!XMLString::equals(w_protocol.get(), samlconstants::SAML20P_NS)) {
+        v2name->setName(nameID.get());
+        v2name->setFormat(format.get());
+        v2name->setNameQualifier(nameQualifier.get());
+        v2name->setSPNameQualifier(spNameQualifier.get());
+        if (!XMLString::equals(protocol.get(), samlconstants::SAML20P_NS)) {
             v1name.reset(saml1::NameIdentifierBuilder::buildNameIdentifier());
-            v1name->setName(w_nameID.get());
-            v1name->setFormat(w_format.get());
-            v1name->setNameQualifier(w_entityID.get());
+            v1name->setName(nameID.get());
+            v1name->setFormat(format.get());
+            v1name->setNameQualifier(nameQualifier.get());
         }
 
-        ctx.reset(resolveAttributes(application, site.second, w_protocol.get(), v1name.get(), v2name.get()));
+        scoped_ptr<ResolutionContext> ctx;
+        ctx.reset(resolveAttributes(application, httpRequest, site.second, protocol.get(), v1name.get(), v2name.get()));
 
-        buildJSON(msg, ctx->getResolvedAttributes(), encoding);
+        buildJSON(msg, ctx->getResolvedAttributes(), param_encoding.second);
     }
     catch (std::exception& ex) {
         m_log.error("error while processing request: %s", ex.what());
@@ -369,6 +338,7 @@ pair<bool,long> AttributeResolverHandler::processMessage(
 #ifndef SHIBSP_LITE
 ResolutionContext* AttributeResolverHandler::resolveAttributes(
     const Application& application,
+    const HTTPRequest& httpRequest,
     const RoleDescriptor* issuer,
     const XMLCh* protocol,
     const saml1::NameIdentifier* v1nameid,
@@ -386,7 +356,7 @@ ResolutionContext* AttributeResolverHandler::resolveAttributes(
                 m_log.debug("extracting metadata-derived attributes...");
                 try {
                     // We pass nullptr for "issuer" because the IdP isn't the one asserting metadata-based attributes.
-                    extractor->extractAttributes(application, nullptr, nullptr, *issuer, resolvedAttributes);
+                    extractor->extractAttributes(application, &httpRequest, nullptr, *issuer, resolvedAttributes);
                     for (indirect_iterator<vector<Attribute*>::iterator> a = make_indirect_iterator(resolvedAttributes.begin());
                             a != make_indirect_iterator(resolvedAttributes.end()); ++a) {
                         vector<string>& ids = a->getAliases();
@@ -405,9 +375,9 @@ ResolutionContext* AttributeResolverHandler::resolveAttributes(
         if (v1nameid || nameid) {
             try {
                 if (v1nameid)
-                    extractor->extractAttributes(application, nullptr, issuer, *v1nameid, resolvedAttributes);
+                    extractor->extractAttributes(application, &httpRequest, issuer, *v1nameid, resolvedAttributes);
                 else
-                    extractor->extractAttributes(application, nullptr, issuer, *nameid, resolvedAttributes);
+                    extractor->extractAttributes(application, &httpRequest, issuer, *nameid, resolvedAttributes);
             }
             catch (std::exception& ex) {
                 m_log.error("caught exception extracting attributes: %s", ex.what());
@@ -439,7 +409,7 @@ ResolutionContext* AttributeResolverHandler::resolveAttributes(
             auto_ptr<ResolutionContext> ctx(
                 resolver->createResolutionContext(
                     application,
-                    nullptr,
+                    &httpRequest,
                     issuer ? dynamic_cast<const saml2md::EntityDescriptor*>(issuer->getParent()) : nullptr,
                     protocol,
                     nameid,
diff --git a/shibsp/handler/AbstractHandler.h b/shibsp/handler/AbstractHandler.h
index 7c9726a..ee5fa95 100644
--- a/shibsp/handler/AbstractHandler.h
+++ b/shibsp/handler/AbstractHandler.h
@@ -236,7 +236,7 @@ namespace shibsp {
          * @param type      bitmask of property sources to use
          * @return a pair consisting of a nullptr indicator and the property value iff the indicator is true
          */
-        std::pair<bool,bool> getBool(const char* name, const SPRequest& request, unsigned int type=HANDLER_PROPERTY_ALL) const;
+        std::pair<bool,bool> getBool(const char* name, const xmltooling::HTTPRequest& request, unsigned int type=HANDLER_PROPERTY_ALL) const;
 
         /**
          * Returns a string-valued property.
@@ -246,7 +246,7 @@ namespace shibsp {
          * @param type      bitmask of property sources to use
          * @return a pair consisting of a nullptr indicator and the property value iff the indicator is true
          */
-        std::pair<bool,const char*> getString(const char* name, const SPRequest& request, unsigned int type=HANDLER_PROPERTY_ALL) const;
+        std::pair<bool,const char*> getString(const char* name, const xmltooling::HTTPRequest& request, unsigned int type=HANDLER_PROPERTY_ALL) const;
 
         /**
          * Returns an unsigned integer-valued property.
@@ -256,7 +256,7 @@ namespace shibsp {
          * @param type      bitmask of property sources to use
          * @return a pair consisting of a nullptr indicator and the property value iff the indicator is true
          */
-        std::pair<bool,unsigned int> getUnsignedInt(const char* name, const SPRequest& request, unsigned int type=HANDLER_PROPERTY_ALL) const;
+        std::pair<bool,unsigned int> getUnsignedInt(const char* name, const xmltooling::HTTPRequest& request, unsigned int type=HANDLER_PROPERTY_ALL) const;
 
         /**
          * Returns an integer-valued property.
@@ -266,7 +266,7 @@ namespace shibsp {
          * @param type      bitmask of property sources to use
          * @return a pair consisting of a nullptr indicator and the property value iff the indicator is true
          */
-        std::pair<bool,int> getInt(const char* name, const SPRequest& request, unsigned int type=HANDLER_PROPERTY_ALL) const;
+        std::pair<bool,int> getInt(const char* name, const xmltooling::HTTPRequest& request, unsigned int type=HANDLER_PROPERTY_ALL) const;
 
         /** Logging object. */
         xmltooling::logging::Category& m_log;
diff --git a/shibsp/handler/impl/AbstractHandler.cpp b/shibsp/handler/impl/AbstractHandler.cpp
index ecbd753..37c07bd 100644
--- a/shibsp/handler/impl/AbstractHandler.cpp
+++ b/shibsp/handler/impl/AbstractHandler.cpp
@@ -822,7 +822,7 @@ DDF AbstractHandler::getPostData(const Application& application, const HTTPReque
     return DDF();
 }
 
-pair<bool,bool> AbstractHandler::getBool(const char* name, const SPRequest& request, unsigned int type) const
+pair<bool,bool> AbstractHandler::getBool(const char* name, const HTTPRequest& request, unsigned int type) const
 {
     if (type & HANDLER_PROPERTY_REQUEST) {
         const char* param = request.getParameter(name);
@@ -830,8 +830,9 @@ pair<bool,bool> AbstractHandler::getBool(const char* name, const SPRequest& requ
             return make_pair(true, (*param=='t' || *param=='1'));
     }
     
-    if (type & HANDLER_PROPERTY_MAP) {
-        pair<bool,bool> ret = request.getRequestSettings().first->getBool(name);
+    const SPRequest* sprequest = dynamic_cast<const SPRequest*>(&request);
+    if (sprequest && (type & HANDLER_PROPERTY_MAP)) {
+        pair<bool,bool> ret = sprequest->getRequestSettings().first->getBool(name);
         if (ret.first)
             return ret;
     }
@@ -843,7 +844,7 @@ pair<bool,bool> AbstractHandler::getBool(const char* name, const SPRequest& requ
     return make_pair(false,false);
 }
 
-pair<bool,const char*> AbstractHandler::getString(const char* name, const SPRequest& request, unsigned int type) const
+pair<bool,const char*> AbstractHandler::getString(const char* name, const HTTPRequest& request, unsigned int type) const
 {
     if (type & HANDLER_PROPERTY_REQUEST) {
         const char* param = request.getParameter(name);
@@ -851,8 +852,9 @@ pair<bool,const char*> AbstractHandler::getString(const char* name, const SPRequ
             return make_pair(true, param);
     }
     
-    if (type & HANDLER_PROPERTY_MAP) {
-        pair<bool,const char*> ret = request.getRequestSettings().first->getString(name);
+    const SPRequest* sprequest = dynamic_cast<const SPRequest*>(&request);
+    if (sprequest && (type & HANDLER_PROPERTY_MAP)) {
+        pair<bool,const char*> ret = sprequest->getRequestSettings().first->getString(name);
         if (ret.first)
             return ret;
     }
@@ -864,7 +866,7 @@ pair<bool,const char*> AbstractHandler::getString(const char* name, const SPRequ
     return pair<bool,const char*>(false,nullptr);
 }
 
-pair<bool,unsigned int> AbstractHandler::getUnsignedInt(const char* name, const SPRequest& request, unsigned int type) const
+pair<bool,unsigned int> AbstractHandler::getUnsignedInt(const char* name, const HTTPRequest& request, unsigned int type) const
 {
     if (type & HANDLER_PROPERTY_REQUEST) {
         const char* param = request.getParameter(name);
@@ -878,8 +880,9 @@ pair<bool,unsigned int> AbstractHandler::getUnsignedInt(const char* name, const
         }
     }
     
-    if (type & HANDLER_PROPERTY_MAP) {
-        pair<bool,unsigned int> ret = request.getRequestSettings().first->getUnsignedInt(name);
+    const SPRequest* sprequest = dynamic_cast<const SPRequest*>(&request);
+    if (sprequest && (type & HANDLER_PROPERTY_MAP)) {
+        pair<bool,unsigned int> ret = sprequest->getRequestSettings().first->getUnsignedInt(name);
         if (ret.first)
             return ret;
     }
@@ -891,7 +894,7 @@ pair<bool,unsigned int> AbstractHandler::getUnsignedInt(const char* name, const
     return pair<bool,unsigned int>(false,0);
 }
 
-pair<bool,int> AbstractHandler::getInt(const char* name, const SPRequest& request, unsigned int type) const
+pair<bool,int> AbstractHandler::getInt(const char* name, const HTTPRequest& request, unsigned int type) const
 {
     if (type & HANDLER_PROPERTY_REQUEST) {
         const char* param = request.getParameter(name);
@@ -899,8 +902,9 @@ pair<bool,int> AbstractHandler::getInt(const char* name, const SPRequest& reques
             return pair<bool,int>(true, atoi(param));
     }
     
-    if (type & HANDLER_PROPERTY_MAP) {
-        pair<bool,int> ret = request.getRequestSettings().first->getInt(name);
+    const SPRequest* sprequest = dynamic_cast<const SPRequest*>(&request);
+    if (sprequest && (type & HANDLER_PROPERTY_MAP)) {
+        pair<bool,int> ret = sprequest->getRequestSettings().first->getInt(name);
         if (ret.first)
             return ret;
     }

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-shibboleth/shibboleth-sp2.git



More information about the Pkg-shibboleth-devel mailing list