[shibboleth-sp2] 45/89: SSPCPP-528 - AttributeQuery Handler
Ferenc Wágner
wferi at moszumanska.debian.org
Thu Sep 1 09:24:07 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 a65d5c54cd481f67d9d9a6df3739fb9dac125385
Author: Scott Cantor <cantor.2 at osu.edu>
Date: Mon Jun 6 16:50:54 2016 -0400
SSPCPP-528 - AttributeQuery Handler
https://issues.shibboleth.net/jira/browse/SSPCPP-528
---
Projects/vc10/plugins/plugins-lite.vcxproj | 6 +-
Projects/vc10/plugins/plugins.vcxproj | 6 +-
Projects/vc10/plugins/plugins.vcxproj.filters | 21 +-
Projects/vc14/plugins/plugins-lite.vcxproj | 1 +
Projects/vc14/plugins/plugins.vcxproj | 1 +
Projects/vc14/plugins/plugins.vcxproj.filters | 1 +
doc/CREDITS.txt | 2 +
doc/NOTICE.txt | 3 +-
plugins/AttributeResolverHandler.cpp | 518 ++++++++++++++++++++++++++
plugins/Makefile.am | 1 +
plugins/plugins.cpp | 3 +
11 files changed, 546 insertions(+), 17 deletions(-)
diff --git a/Projects/vc10/plugins/plugins-lite.vcxproj b/Projects/vc10/plugins/plugins-lite.vcxproj
index dece135..18cc3c5 100644
--- a/Projects/vc10/plugins/plugins-lite.vcxproj
+++ b/Projects/vc10/plugins/plugins-lite.vcxproj
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
@@ -70,7 +70,6 @@
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)\..\..\Build\VC10\$(Platform)\$(Configuration)\</OutDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)\..\..\Build\VC10\\$(Configuration)\</OutDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)\..\..\Build\VC10\\$(Configuration)\</OutDir>
-
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(Platform)\$(ProjectName)-$(Configuration)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</LinkIncremental>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
@@ -183,6 +182,7 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
+ <ClCompile Include="..\..\..\plugins\AttributeResolverHandler.cpp" />
<ClCompile Include="..\..\..\plugins\plugins.cpp" />
<ClCompile Include="..\..\..\plugins\TimeAccessControl.cpp" />
</ItemGroup>
@@ -205,4 +205,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
-</Project>
+</Project>
\ No newline at end of file
diff --git a/Projects/vc10/plugins/plugins.vcxproj b/Projects/vc10/plugins/plugins.vcxproj
index 80d23e1..76b5798 100644
--- a/Projects/vc10/plugins/plugins.vcxproj
+++ b/Projects/vc10/plugins/plugins.vcxproj
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
@@ -70,7 +70,6 @@
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)\..\..\Build\VC10\$(Platform)\$(Configuration)\</OutDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)\..\..\Build\VC10\\$(Configuration)\</OutDir>
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)\..\..\Build\VC10\\$(Configuration)\</OutDir>
-
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(Platform)\$(Configuration)\</IntDir>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</LinkIncremental>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
@@ -181,6 +180,7 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
+ <ClCompile Include="..\..\..\plugins\AttributeResolverHandler.cpp" />
<ClCompile Include="..\..\..\plugins\CaseFoldingAttributeResolver.cpp" />
<ClCompile Include="..\..\..\plugins\GSSAPIAttributeExtractor.cpp" />
<ClCompile Include="..\..\..\plugins\plugins.cpp" />
@@ -207,4 +207,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
-</Project>
+</Project>
\ No newline at end of file
diff --git a/Projects/vc10/plugins/plugins.vcxproj.filters b/Projects/vc10/plugins/plugins.vcxproj.filters
index 09299f3..bf5418c 100644
--- a/Projects/vc10/plugins/plugins.vcxproj.filters
+++ b/Projects/vc10/plugins/plugins.vcxproj.filters
@@ -1,21 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
- <ClCompile Include="GSSAPIAttributeExtractor.cpp" />
- <ClCompile Include="plugins.cpp" />
- <ClCompile Include="TransformAttributeResolver.cpp" />
- <ClCompile Include="TemplateAttributeResolver.cpp" />
- <ClCompile Include="CaseFoldingAttributeResolver.cpp" />
- <ClCompile Include="TimeAccessControl.cpp" />
+ <ClCompile Include="..\..\..\plugins\CaseFoldingAttributeResolver.cpp" />
+ <ClCompile Include="..\..\..\plugins\GSSAPIAttributeExtractor.cpp" />
+ <ClCompile Include="..\..\..\plugins\plugins.cpp" />
+ <ClCompile Include="..\..\..\plugins\TemplateAttributeResolver.cpp" />
+ <ClCompile Include="..\..\..\plugins\TimeAccessControl.cpp" />
+ <ClCompile Include="..\..\..\plugins\TransformAttributeResolver.cpp" />
+ <ClCompile Include="..\..\..\plugins\AttributeResolverHandler.cpp" />
</ItemGroup>
<ItemGroup>
- <ClInclude Include="internal.h" />
- <ClInclude Include="resource.h" />
+ <ClInclude Include="..\..\..\plugins\internal.h" />
+ <ClInclude Include="..\..\..\plugins\resource.h" />
</ItemGroup>
<ItemGroup>
- <None Include="Makefile.am" />
+ <None Include="..\..\..\plugins\Makefile.am" />
</ItemGroup>
<ItemGroup>
- <ResourceCompile Include="plugins.rc" />
+ <ResourceCompile Include="..\..\..\plugins\plugins.rc" />
</ItemGroup>
</Project>
\ No newline at end of file
diff --git a/Projects/vc14/plugins/plugins-lite.vcxproj b/Projects/vc14/plugins/plugins-lite.vcxproj
index e81749b..e16b35e 100644
--- a/Projects/vc14/plugins/plugins-lite.vcxproj
+++ b/Projects/vc14/plugins/plugins-lite.vcxproj
@@ -190,6 +190,7 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
+ <ClCompile Include="..\..\..\plugins\AttributeResolverHandler.cpp" />
<ClCompile Include="..\..\..\plugins\plugins.cpp" />
<ClCompile Include="..\..\..\plugins\TimeAccessControl.cpp" />
</ItemGroup>
diff --git a/Projects/vc14/plugins/plugins.vcxproj b/Projects/vc14/plugins/plugins.vcxproj
index 55cb877..0425444 100644
--- a/Projects/vc14/plugins/plugins.vcxproj
+++ b/Projects/vc14/plugins/plugins.vcxproj
@@ -188,6 +188,7 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
+ <ClCompile Include="..\..\..\plugins\AttributeResolverHandler.cpp" />
<ClCompile Include="..\..\..\plugins\CaseFoldingAttributeResolver.cpp" />
<ClCompile Include="..\..\..\plugins\GSSAPIAttributeExtractor.cpp" />
<ClCompile Include="..\..\..\plugins\plugins.cpp" />
diff --git a/Projects/vc14/plugins/plugins.vcxproj.filters b/Projects/vc14/plugins/plugins.vcxproj.filters
index 6f1c71d..bf5418c 100644
--- a/Projects/vc14/plugins/plugins.vcxproj.filters
+++ b/Projects/vc14/plugins/plugins.vcxproj.filters
@@ -7,6 +7,7 @@
<ClCompile Include="..\..\..\plugins\TemplateAttributeResolver.cpp" />
<ClCompile Include="..\..\..\plugins\TimeAccessControl.cpp" />
<ClCompile Include="..\..\..\plugins\TransformAttributeResolver.cpp" />
+ <ClCompile Include="..\..\..\plugins\AttributeResolverHandler.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\..\plugins\internal.h" />
diff --git a/doc/CREDITS.txt b/doc/CREDITS.txt
index 4574341..f54340d 100644
--- a/doc/CREDITS.txt
+++ b/doc/CREDITS.txt
@@ -61,6 +61,8 @@ Additional thanks to:
National Research Council of Canada
+ National Institute of Informatics in Japan
+
Barbara Jenson (CMU), Parviz Dousti (CMU), Tom Dopirak (CMU),
and Sridhar Muppidi (IBM/Tivoli); for helping to develop
the initial Shibboleth prototype
diff --git a/doc/NOTICE.txt b/doc/NOTICE.txt
index 0481820..6be96e4 100644
--- a/doc/NOTICE.txt
+++ b/doc/NOTICE.txt
@@ -10,8 +10,9 @@ for use in the OpenSSL Toolkit. (http://www.openssl.org/).
This project uses libraries covered by the Lesser GNU Public License.
Source code for these libraries is available on request.
-This product includes software developed, copyrighted, and contributed by:
+This product includes software developed, copyrighted, and/or contributed by:
The Ohio State University
The National Research Council of Canada
The Danish CLARIN Consortium
+National Institute of Informatics in Japan
\ No newline at end of file
diff --git a/plugins/AttributeResolverHandler.cpp b/plugins/AttributeResolverHandler.cpp
new file mode 100644
index 0000000..554b3a0
--- /dev/null
+++ b/plugins/AttributeResolverHandler.cpp
@@ -0,0 +1,518 @@
+/**
+ * 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.
+ */
+
+/**
+ * AttributeResolverHandler.cpp
+ *
+ * Handler that runs the attribute resolver machinery and outputs the results directly.
+ */
+
+#if defined (_MSC_VER) || defined(__BORLANDC__)
+# include "config_win32.h"
+#else
+# include "config.h"
+#endif
+
+#include "internal.h"
+
+#include <shibsp/Application.h>
+#include <shibsp/exceptions.h>
+#include <shibsp/ServiceProvider.h>
+#include <shibsp/SPConfig.h>
+#include <shibsp/SPRequest.h>
+#include <shibsp/handler/SecuredHandler.h>
+#include <shibsp/handler/RemotedHandler.h>
+
+#include <boost/scoped_ptr.hpp>
+
+#ifndef SHIBSP_LITE
+#include <shibsp/attribute/Attribute.h>
+#include <shibsp/attribute/filtering/AttributeFilter.h>
+#include <shibsp/attribute/filtering/BasicFilteringContext.h>
+#include <shibsp/attribute/resolver/AttributeExtractor.h>
+#include <shibsp/attribute/resolver/AttributeResolver.h>
+#include <shibsp/attribute/resolver/ResolutionContext.h>
+#include <shibsp/metadata/MetadataProviderCriteria.h>
+
+#include <saml/exceptions.h>
+#include <saml/saml1/core/Assertions.h>
+#include <saml/saml2/core/Assertions.h>
+#include <saml/saml2/metadata/Metadata.h>
+#include <saml/saml2/metadata/MetadataProvider.h>
+#include <xmltooling/XMLToolingConfig.h>
+#include <xmltooling/util/ParserPool.h>
+#include <xmltooling/util/XMLHelper.h>
+#include <xercesc/util/XMLUniDefs.hpp>
+#include <boost/iterator/indirect_iterator.hpp>
+#endif
+
+using namespace std;
+using namespace shibsp;
+using namespace xmltooling;
+using namespace xercesc;
+using namespace boost;
+
+#ifndef SHIBSP_LITE
+using namespace opensaml::saml2md;
+using namespace opensaml;
+#endif
+
+namespace shibsp {
+
+#if defined (_MSC_VER)
+ #pragma warning( push )
+ #pragma warning( disable : 4250 )
+#endif
+
+ class SHIBSP_DLLLOCAL AttributeResolverHandler : public SecuredHandler, public RemotedHandler
+ {
+ public:
+ AttributeResolverHandler(const DOMElement* e, const char* appId);
+ virtual ~AttributeResolverHandler() {}
+
+ pair<bool,long> run(SPRequest& request, bool isHandler=true) const;
+ void receive(DDF& in, ostream& out);
+
+ private:
+ pair<bool,long> processMessage(
+ const Application& application,
+ const HTTPRequest& httpRequest,
+ HTTPResponse& httpResponse
+ ) const;
+
+#ifndef SHIBSP_LITE
+ ResolutionContext* resolveAttributes(
+ const Application& application,
+ const GenericRequest* request,
+ const RoleDescriptor* issuer,
+ const XMLCh* protocol,
+ const saml1::NameIdentifier* v1nameid,
+ const saml2::NameID* nameid
+ ) const;
+
+ ostream& buildJSON(ostream& os, vector<shibsp::Attribute*>& attributes) const;
+
+ string m_encoding;
+#endif
+ };
+
+#if defined (_MSC_VER)
+ #pragma warning( pop )
+#endif
+
+ Handler* SHIBSP_DLLLOCAL AttributeResolverHandlerFactory(const pair<const DOMElement*,const char*>& p)
+ {
+ return new AttributeResolverHandler(p.first, p.second);
+ }
+
+};
+
+#ifndef SHIBSP_LITE
+
+namespace {
+ class SHIBSP_DLLLOCAL DummyContext : public shibsp::ResolutionContext
+ {
+ public:
+ DummyContext(const vector<Attribute*>& attributes) : m_attributes(attributes) {
+ }
+
+ virtual ~DummyContext() {
+ for_each(m_attributes.begin(), m_attributes.end(), xmltooling::cleanup<Attribute>());
+ }
+
+ vector<Attribute*>& getResolvedAttributes() {
+ return m_attributes;
+ }
+ vector<Assertion*>& getResolvedAssertions() {
+ return m_tokens;
+ }
+
+ private:
+ vector<Attribute*> m_attributes;
+ static vector<Assertion*> m_tokens; // never any tokens, so just share an empty vector
+ };
+
+ static ostream& json_safe(ostream& os, const char* buf)
+ {
+ os << '"';
+ for (; *buf; ++buf) {
+ switch (*buf) {
+ case '\\':
+ case '"':
+ os << '\\';
+ os << *buf;
+ break;
+ case '\b':
+ os << "\\b";
+ break;
+ case '\t':
+ os << "\\t";
+ break;
+ case '\n':
+ os << "\\n";
+ break;
+ case '\f':
+ os << "\\f";
+ break;
+ case '\r':
+ os << "\\r";
+ break;
+ default:
+ os << *buf;
+ }
+ }
+ os << '"';
+ return os;
+ }
+};
+
+vector<Assertion*> DummyContext::m_tokens;
+
+#endif
+
+AttributeResolverHandler::AttributeResolverHandler(const DOMElement* e, const char* appId)
+ : SecuredHandler(e, Category::getInstance(SHIBSP_LOGCAT".AttributeResolverHandler"), "acl", "127.0.0.1 ::1")
+{
+ pair<bool,const char*> prop = getString("Location");
+ if (!prop.first)
+ throw ConfigurationException("AttributeQuery handler requires Location property.");
+ string address(appId);
+ address += prop.second;
+ setAddress(address.c_str());
+
+#ifndef SHIBSP_LITE
+ pair<bool, const char*> encoding = getString("encoding");
+ m_encoding = encoding.first ? encoding.second : "";
+#endif
+}
+
+pair<bool,long> AttributeResolverHandler::run(SPRequest& request, bool isHandler) const
+{
+ // Check ACL in base class.
+ pair<bool,long> ret = SecuredHandler::run(request, isHandler);
+ if (ret.first)
+ return ret;
+
+ request.setResponseHeader("Expires","Wed, 01 Jan 1997 12:00:00 GMT");
+ request.setResponseHeader("Cache-Control","private,no-store,no-cache,max-age=0");
+ request.setContentType("application/json; charset=utf-8");
+ try {
+ if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess)) {
+ // When out of process, we run natively and directly process the message.
+ return processMessage(request.getApplication(), request, request);
+ }
+ else {
+ // When not out of process, we remote all the message processing.
+ DDF out,in = wrap(request);
+ DDFJanitor jin(in), jout(out);
+ out=request.getServiceProvider().getListenerService()->send(in);
+ return unwrap(request, out);
+ }
+ }
+ catch (std::exception& ex) {
+ m_log.error("error while processing request: %s", ex.what());
+ istringstream msg("{}");
+ return make_pair(true, request.sendError(msg));
+ }
+}
+
+void AttributeResolverHandler::receive(DDF& in, ostream& out)
+{
+ // Find application.
+ const char* aid = in["application_id"].string();
+ const Application* app = aid ? SPConfig::getConfig().getServiceProvider()->getApplication(aid) : nullptr;
+ if (!app) {
+ // Something's horribly wrong.
+ m_log.error("couldn't find application (%s) for AttributeQuery request", aid ? aid : "(missing)");
+ throw ConfigurationException("Unable to locate application for request, deleted?");
+ }
+
+ // Wrap a response shim.
+ DDF ret(nullptr);
+ DDFJanitor jout(ret);
+ scoped_ptr<HTTPRequest> req(getRequest(in));
+ scoped_ptr<HTTPResponse> resp(getResponse(ret));
+
+ // 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, *req, *resp);
+ }
+ catch (std::exception& ex) {
+ m_log.error("raising exception: %s", ex.what());
+ throw;
+ }
+ out << ret;
+}
+
+pair<bool,long> AttributeResolverHandler::processMessage(
+ const Application& application, const HTTPRequest& httpRequest, HTTPResponse& httpResponse
+ ) const
+{
+#ifndef SHIBSP_LITE
+ m_log.debug("processing status request");
+ m_log.debug("request URL: %s", httpRequest.getRequestURL());
+
+ const char* param_protocol = httpRequest.getParameter("protocol");
+ const char* param_issuer = httpRequest.getParameter("entityID");
+ const char* param_format = httpRequest.getParameter("format");
+ const char* param_nameid = httpRequest.getParameter("nameId");
+
+ m_log.debug("protocol = %s, entityID = %s, format = %s, name = %s",
+ param_protocol, param_issuer, param_format, param_nameid);
+
+ stringstream msg;
+
+ if (!param_nameid || !*param_nameid) {
+ m_log.error("AttributeQuery Handler requires nameId parameter");
+ msg << "{}";
+ return make_pair(true, httpResponse.sendResponse(msg, HTTPResponse::XMLTOOLING_HTTP_STATUS_BADREQUEST));
+ }
+
+ const auto_ptr_XMLCh issuer(param_issuer);
+ const auto_ptr_XMLCh nameid(param_nameid);
+ const auto_ptr_XMLCh format(param_format);
+
+ if (param_protocol) {
+ if (strcmp(param_protocol, "SAML2.0") == 0)
+ param_protocol = "urn:oasis:names:tc:SAML:2.0:protocol"; // samlconstants::SAML20P_NS;
+ else if (strcmp(param_protocol, "SAML1.1") == 0)
+ param_protocol = "urn:oasis:names:tc:SAML:1.1:protocol"; // samlconstants::SAML11_PROTOCOL_ENUM;
+ else if (strcmp(param_protocol, "SAML1.0") == 0)
+ param_protocol = "urn:oasis:names:tc:SAML:1.0:protocol"; // samlconstants::SAML10_PROTOCOL_ENUM;
+ }
+ else {
+ param_protocol = "urn:oasis:names:tc:SAML:2.0:protocol"; // samlconstants::SAML20P_NS;
+ }
+ const auto_ptr_XMLCh protocol(param_protocol);
+
+ try {
+ scoped_ptr<ResolutionContext> ctx;
+
+ MetadataProvider* m = application.getMetadataProvider();
+ Locker mlock(m);
+
+ MetadataProviderCriteria mc(application, param_issuer, &IDPSSODescriptor::ELEMENT_QNAME, protocol.get());
+ pair<const EntityDescriptor*,const RoleDescriptor*> site = m->getEntityDescriptor(mc);
+ if (!site.first)
+ m_log.info("Unable to locate metadata for IdP (%s).", param_issuer);
+
+ // Build NameID(s).
+ scoped_ptr<saml1::NameIdentifier> v1name;
+ scoped_ptr<saml2::NameID> v2name(saml2::NameIDBuilder::buildNameID());
+ v2name->setName(nameid.get());
+ v2name->setFormat(format.get());
+ v2name->setNameQualifier(issuer.get());
+ v2name->setSPNameQualifier(application.getRelyingParty(site.first)->getXMLString("entityID").second);
+ if (!XMLString::equals(protocol.get(), samlconstants::SAML20P_NS)) {
+ v1name.reset(saml1::NameIdentifierBuilder::buildNameIdentifier());
+ v1name->setName(nameid.get());
+ v1name->setFormat(format.get());
+ v1name->setNameQualifier(issuer.get());
+ }
+
+ ctx.reset(resolveAttributes(application, &httpRequest, site.second, protocol.get(), v1name.get(), v2name.get()));
+
+ buildJSON(msg, ctx->getResolvedAttributes());
+ }
+ catch (std::exception& ex) {
+ m_log.error("error while processing request: %s", ex.what());
+ msg << "{}";
+ return make_pair(true, httpResponse.sendError(msg));
+ }
+ return make_pair(true, httpResponse.sendResponse(msg));
+#else
+ return make_pair(false, 0L);
+#endif
+}
+
+#ifndef SHIBSP_LITE
+ResolutionContext* AttributeResolverHandler::resolveAttributes(
+ const Application& application,
+ const GenericRequest* request,
+ const RoleDescriptor* issuer,
+ const XMLCh* protocol,
+ const saml1::NameIdentifier* v1nameid,
+ const saml2::NameID* nameid
+ ) const
+{
+ // First we do the extraction of any pushed information, including from metadata.
+ vector<Attribute*> resolvedAttributes;
+ AttributeExtractor* extractor = application.getAttributeExtractor();
+ if (extractor) {
+ Locker extlocker(extractor);
+ if (issuer) {
+ pair<bool,const char*> mprefix = application.getString("metadataAttributePrefix");
+ if (mprefix.first) {
+ 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, request, 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();
+ for (vector<string>::iterator id = ids.begin(); id != ids.end(); ++id)
+ *id = mprefix.second + *id;
+ }
+ }
+ catch (std::exception& ex) {
+ m_log.error("caught exception extracting attributes: %s", ex.what());
+ }
+ }
+ }
+
+ m_log.debug("extracting attributes from NameID/NameIdentifier...");
+
+ if (v1nameid || nameid) {
+ try {
+ if (v1nameid)
+ extractor->extractAttributes(application, request, issuer, *v1nameid, resolvedAttributes);
+ else
+ extractor->extractAttributes(application, request, issuer, *nameid, resolvedAttributes);
+ }
+ catch (std::exception& ex) {
+ m_log.error("caught exception extracting attributes: %s", ex.what());
+ }
+ }
+
+ AttributeFilter* filter = application.getAttributeFilter();
+ if (filter && !resolvedAttributes.empty()) {
+ BasicFilteringContext fc(application, resolvedAttributes, issuer, nullptr, nullptr);
+ Locker filtlocker(filter);
+ try {
+ filter->filterAttributes(fc, resolvedAttributes);
+ }
+ catch (std::exception& ex) {
+ m_log.error("caught exception filtering attributes: %s", ex.what());
+ m_log.error("dumping extracted attributes due to filtering exception");
+ for_each(resolvedAttributes.begin(), resolvedAttributes.end(), xmltooling::cleanup<shibsp::Attribute>());
+ resolvedAttributes.clear();
+ }
+ }
+ }
+
+ try {
+ AttributeResolver* resolver = application.getAttributeResolver();
+ if (resolver) {
+ m_log.debug("resolving attributes...");
+
+ Locker locker(resolver);
+ auto_ptr<ResolutionContext> ctx(
+ resolver->createResolutionContext(
+ application,
+ request,
+ issuer ? dynamic_cast<const saml2md::EntityDescriptor*>(issuer->getParent()) : nullptr,
+ protocol,
+ nameid,
+ nullptr,
+ nullptr,
+ nullptr,
+ &resolvedAttributes
+ )
+ );
+ resolver->resolveAttributes(*ctx);
+ // Copy over any pushed attributes.
+ while (!resolvedAttributes.empty()) {
+ ctx->getResolvedAttributes().push_back(resolvedAttributes.back());
+ resolvedAttributes.pop_back();
+ }
+ return ctx.release();
+ }
+ }
+ catch (std::exception& ex) {
+ m_log.error("attribute resolution failed: %s", ex.what());
+ }
+
+ if (!resolvedAttributes.empty()) {
+ try {
+ return new DummyContext(resolvedAttributes);
+ }
+ catch (bad_alloc&) {
+ for_each(resolvedAttributes.begin(), resolvedAttributes.end(), xmltooling::cleanup<shibsp::Attribute>());
+ }
+ }
+ return nullptr;
+}
+
+ostream& AttributeResolverHandler::buildJSON(ostream& os, vector<shibsp::Attribute*>& attributes) const
+{
+ m_log.debug("building JSON from attributes..");
+
+ os << '{';
+
+ indirect_iterator<vector<Attribute*>::const_iterator> ahead = make_indirect_iterator(attributes.begin());
+ indirect_iterator<vector<Attribute*>::const_iterator> a = ahead;
+ for (; a != make_indirect_iterator(attributes.end()); ++a) {
+
+ if (a != ahead)
+ os << ',';
+
+ vector<string>::const_iterator shead = a->getAliases().begin();
+ for (vector<string>::const_iterator s = shead; s != a->getAliases().end(); ++s) {
+ if (s != shead)
+ os << ',';
+ os << endl << " ";
+ json_safe(os, s->c_str());
+ os << " : ";
+
+ if (m_encoding.empty() || m_encoding == "JSON") {
+ os << '[' << endl;
+ vector<string>::const_iterator vhead = a->getSerializedValues().begin();
+ for (vector<string>::const_iterator v = vhead; v != a->getSerializedValues().end(); ++v) {
+ if (v != vhead)
+ os << ',';
+ os << endl << " ";
+ json_safe(os, v->c_str());
+ }
+ os << endl << " ]";
+ }
+ else if (m_encoding == "JSON/CGI") {
+ string attrValues;
+ vector<string>::const_iterator vhead = a->getSerializedValues().begin();
+ for (vector<string>::const_iterator v = vhead; v != a->getSerializedValues().end(); ++v) {
+ if (v != vhead)
+ attrValues += ';';
+ string::size_type pos = v->find_first_of(';', string::size_type(0));
+ if (pos != string::npos) {
+ string value(*v);
+ for (; pos != string::npos; pos = value.find_first_of(';', pos)) {
+ value.insert(pos, "\\");
+ pos += 2;
+ }
+ attrValues += value;
+ }
+ else {
+ attrValues += *v;
+ }
+ }
+ json_safe(os, attrValues.c_str());
+ }
+
+ }
+ }
+ if (a != ahead)
+ os << endl;
+
+ os << '}';
+
+ return os;
+}
+#endif
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index 472088b..ee2dbec 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -8,6 +8,7 @@ noinst_HEADERS = \
common_sources = \
plugins.cpp \
+ AttributeResolverHandler.cpp \
TimeAccessControl.cpp
plugins_la_SOURCES = \
diff --git a/plugins/plugins.cpp b/plugins/plugins.cpp
index d23f127..b277f7f 100644
--- a/plugins/plugins.cpp
+++ b/plugins/plugins.cpp
@@ -42,6 +42,8 @@ using namespace std;
namespace shibsp {
PluginManager<AccessControl,string,const DOMElement*>::Factory TimeAccessControlFactory;
+ PluginManager<Handler,string,pair<const DOMElement*,const char*>>::Factory AttributeResolverHandlerFactory;
+
#ifndef SHIBSP_LITE
# ifdef HAVE_GSSAPI_NAMINGEXTS
PluginManager<AttributeExtractor,string,const DOMElement*>::Factory GSSAPIExtractorFactory;
@@ -57,6 +59,7 @@ extern "C" int PLUGINS_EXPORTS xmltooling_extension_init(void*)
{
SPConfig& conf = SPConfig::getConfig();
conf.AccessControlManager.registerFactory("Time", TimeAccessControlFactory);
+ conf.HandlerManager.registerFactory("AttributeResolver", AttributeResolverHandlerFactory);
#ifndef SHIBSP_LITE
# ifdef HAVE_GSSAPI_NAMINGEXTS
conf.AttributeExtractorManager.registerFactory("GSSAPI", GSSAPIExtractorFactory);
--
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