[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