[cpp-sp] branch main updated: Remove AttrbuteResolver and extractor code.
Scott Cantor
cantor.2 at osu.edu
Wed Oct 30 21:24:45 UTC 2024
This is an automated email from the git hooks/post-receive script.
scantor pushed a commit to branch main
in repository cpp-sp.
View the commit online:
http://git.shibboleth.net/view/?p=cpp-sp.git;a=commit;h=6cdf44b27d81c7e40b99e86cf35b6786f62199af
The following commit(s) were added to refs/heads/main by this push:
new 6cdf44b2 Remove AttrbuteResolver and extractor code.
6cdf44b2 is described below
commit 6cdf44b27d81c7e40b99e86cf35b6786f62199af
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Wed Oct 30 17:24:40 2024 -0400
Remove AttrbuteResolver and extractor code.
---
shibsp/Makefile.am | 9 -
shibsp/attribute/resolver/AttributeExtractor.h | 124 ---
shibsp/attribute/resolver/AttributeResolver.h | 150 ---
shibsp/attribute/resolver/ResolutionContext.h | 77 --
.../resolver/impl/AssertionAttributeExtractor.cpp | 399 --------
.../resolver/impl/ChainingAttributeExtractor.cpp | 150 ---
.../resolver/impl/ChainingAttributeResolver.cpp | 242 -----
.../resolver/impl/DelegationAttributeExtractor.cpp | 202 ----
.../impl/KeyDescriptorAttributeExtractor.cpp | 192 ----
.../resolver/impl/MetadataAttributeExtractor.cpp | 406 --------
.../resolver/impl/QueryAttributeResolver.cpp | 764 --------------
.../impl/SimpleAggregationAttributeResolver.cpp | 765 --------------
.../resolver/impl/XMLAttributeExtractor.cpp | 1068 --------------------
13 files changed, 4548 deletions(-)
diff --git a/shibsp/Makefile.am b/shibsp/Makefile.am
index e4cd946b..ec2ae137 100644
--- a/shibsp/Makefile.am
+++ b/shibsp/Makefile.am
@@ -6,10 +6,6 @@ libshibspincludedir = $(includedir)/shibsp
attrincludedir = $(includedir)/shibsp/attribute
-attrresincludedir = $(includedir)/shibsp/attribute/resolver
-
-attrfiltincludedir = $(includedir)/shibsp/attribute/filtering
-
bindincludedir = $(includedir)/shibsp/binding
handincludedir = $(includedir)/shibsp/handler
@@ -51,11 +47,6 @@ attrinclude_HEADERS = \
attribute/SimpleAttribute.h \
attribute/XMLAttribute.h
-attrresinclude_HEADERS = \
- attribute/resolver/AttributeExtractor.h \
- attribute/resolver/AttributeResolver.h \
- attribute/resolver/ResolutionContext.h
-
bindinclude_HEADERS = \
binding/ArtifactResolver.h \
binding/ProtocolProvider.h \
diff --git a/shibsp/attribute/resolver/AttributeExtractor.h b/shibsp/attribute/resolver/AttributeExtractor.h
deleted file mode 100644
index fd0d30dc..00000000
--- a/shibsp/attribute/resolver/AttributeExtractor.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/**
- * 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.
- */
-
-/**
- * @file shibsp/attribute/resolver/AttributeExtractor.h
- *
- * A service that extracts and decodes attributes from XML objects.
- */
-
-#ifndef __shibsp_extractor_h__
-#define __shibsp_extractor_h__
-
-#include <shibsp/base.h>
-
-#include <string>
-#include <vector>
-#include <xmltooling/Lockable.h>
-
-namespace xmltooling {
- class XMLTOOL_API XMLObject;
-};
-
-namespace opensaml {
- namespace saml2md {
- class SAML_API RoleDescriptor;
- class SAML_API SPSSODescriptor;
- };
-};
-
-namespace shibsp {
-
- class SHIBSP_API Application;
- class SHIBSP_API Attribute;
-
- /**
- * A service that extracts and decodes attributes from XML objects.
- */
- class SHIBSP_API AttributeExtractor : public virtual xmltooling::Lockable
- {
- MAKE_NONCOPYABLE(AttributeExtractor);
- protected:
- AttributeExtractor();
- public:
- virtual ~AttributeExtractor();
-
- /**
- * Extracts the attributes found in an XMLObject.
- *
- * @param application Application performing the extraction
- * @param request request triggering the extraction, if any
- * @param issuer source of object, if known
- * @param xmlObject object to extract
- * @param attributes an array to populate with the extracted attributes
- *
- * @throws AttributeExtractionException thrown if there is a problem extracting attributes
- */
- virtual void extractAttributes(
- const Application& application,
- const xmltooling::GenericRequest* request,
- const opensaml::saml2md::RoleDescriptor* issuer,
- const xmltooling::XMLObject& xmlObject,
- std::vector<Attribute*>& attributes
- ) const=0;
-
- /**
- * Populates an array with the set of Attribute IDs that might be generated.
- *
- * @param attributes array to populate
- */
- virtual void getAttributeIds(std::vector<std::string>& attributes) const=0;
-
- /**
- * Generates and/or modifies metadata reflecting the extractor,
- * typically attribute-related requirements.
- *
- * <p>The default implementation does nothing.
- *
- * @param role metadata role to decorate
- */
- virtual void generateMetadata(opensaml::saml2md::SPSSODescriptor& role) const;
- };
-
- /**
- * Registers AttributeExtractor classes into the runtime.
- */
- void SHIBSP_API registerAttributeExtractors();
-
- /** AttributeExtractor based on an XML mapping schema. */
- #define XML_ATTRIBUTE_EXTRACTOR "XML"
-
- /** AttributeExtractor for SAML assertion information. */
- #define ASSERTION_ATTRIBUTE_EXTRACTOR "Assertion"
-
- /** AttributeExtractor for SAML metadata information. */
- #define METADATA_ATTRIBUTE_EXTRACTOR "Metadata"
-
- /** AttributeExtractor for DelegationRestriction information. */
- #define DELEGATION_ATTRIBUTE_EXTRACTOR "Delegation"
-
- /** AttributeExtractor for KeyInfo information. */
- #define KEYDESCRIPTOR_ATTRIBUTE_EXTRACTOR "KeyDescriptor"
-
- /** AttributeExtractor based on chaining together other extractors. */
- #define CHAINING_ATTRIBUTE_EXTRACTOR "Chaining"
-};
-
-#endif /* __shibsp_extractor_h__ */
diff --git a/shibsp/attribute/resolver/AttributeResolver.h b/shibsp/attribute/resolver/AttributeResolver.h
deleted file mode 100644
index 5c34b6ef..00000000
--- a/shibsp/attribute/resolver/AttributeResolver.h
+++ /dev/null
@@ -1,150 +0,0 @@
-/**
- * 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.
- */
-
-/**
- * @file shibsp/attribute/resolver/AttributeResolver.h
- *
- * A service that transforms or resolves additional attributes for a
- * particular subject.
- */
-
-#ifndef __shibsp_resolver_h__
-#define __shibsp_resolver_h__
-
-#include <shibsp/base.h>
-
-#include <string>
-#include <vector>
-#include <xercesc/util/XercesDefs.hpp>
-#include <xmltooling/Lockable.h>
-
-namespace xmltooling {
- class XMLTOOL_API GenericRequest;
-};
-
-namespace opensaml {
- class SAML_API Assertion;
- namespace saml2 {
- class SAML_API NameID;
- };
- namespace saml2md {
- class SAML_API EntityDescriptor;
- };
-};
-
-namespace shibsp {
-
- class SHIBSP_API Application;
- class SHIBSP_API Attribute;
- class SHIBSP_API Session;
- class SHIBSP_API ResolutionContext;
-
-#if defined (_MSC_VER)
- #pragma warning( push )
- #pragma warning( disable : 4250 4251 )
-#endif
-
- /**
- * The service that resolves the attributes for a particular subject.
- */
- class SHIBSP_API AttributeResolver : public virtual xmltooling::Lockable
- {
- MAKE_NONCOPYABLE(AttributeResolver);
- protected:
- AttributeResolver();
- public:
- virtual ~AttributeResolver();
-
- /**
- * Creates a ResolutionContext based on session bootstrap material.
- *
- * <p>This enables resolution to occur ahead of session creation so that
- * Attributes can be supplied while creating the session.
- *
- * @param application reference to Application that owns the eventual Session
- * @param request request triggering the resolution, if any
- * @param issuer issuing metadata of assertion issuer, if known
- * @param protocol protocol used to establish Session
- * @param nameid principal identifier, normalized to SAML 2, if any
- * @param authncontext_class method/category of authentication event, if known
- * @param authncontext_decl specifics of authentication event, if known
- * @param tokens assertions initiating the Session, if any
- * @param attributes array of previously resolved attributes, if any
- * @return newly created ResolutionContext, owned by caller
- */
- virtual ResolutionContext* createResolutionContext(
- const Application& application,
- const xmltooling::GenericRequest* request,
- const opensaml::saml2md::EntityDescriptor* issuer,
- const XMLCh* protocol,
- const opensaml::saml2::NameID* nameid=nullptr,
- const XMLCh* authncontext_class=nullptr,
- const XMLCh* authncontext_decl=nullptr,
- const std::vector<const opensaml::Assertion*>* tokens=nullptr,
- const std::vector<Attribute*>* attributes=nullptr
- ) const=0;
-
- /**
- * Creates a ResolutionContext for an existing Session.
- *
- * @param application reference to Application that owns the Session
- * @param session reference to Session
- * @return newly created ResolutionContext, owned by caller
- */
- virtual ResolutionContext* createResolutionContext(const Application& application, const Session& session) const=0;
-
-
- /**
- * Resolves attributes for a given subject and returns them in the supplied context.
- *
- * @param ctx resolution context to use to resolve attributes
- *
- * @throws AttributeResolutionException thrown if there is a problem resolving the attributes for the subject
- */
- virtual void resolveAttributes(ResolutionContext& ctx) const=0;
-
- /**
- * Populates an array with the set of Attribute IDs that might be generated.
- *
- * @param attributes array to populate
- */
- virtual void getAttributeIds(std::vector<std::string>& attributes) const=0;
- };
-
-#if defined (_MSC_VER)
- #pragma warning( pop )
-#endif
-
- /**
- * Registers AttributeResolver classes into the runtime.
- */
- void SHIBSP_API registerAttributeResolvers();
-
- /** AttributeResolver based on SAML queries to an IdP during SSO. */
- #define QUERY_ATTRIBUTE_RESOLVER "Query"
-
- /** AttributeResolver based on free-standing SAML queries to additional AAs. */
- #define SIMPLEAGGREGATION_ATTRIBUTE_RESOLVER "SimpleAggregation"
-
- /** AttributeResolver based on chaining together other resolvers. */
- #define CHAINING_ATTRIBUTE_RESOLVER "Chaining"
-};
-
-#endif /* __shibsp_resolver_h__ */
diff --git a/shibsp/attribute/resolver/ResolutionContext.h b/shibsp/attribute/resolver/ResolutionContext.h
deleted file mode 100644
index aedb5da4..00000000
--- a/shibsp/attribute/resolver/ResolutionContext.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/**
- * 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.
- */
-
-/**
- * @file shibsp/attribute/resolver/ResolutionContext.h
- *
- * A context for a resolution request.
- */
-
-#ifndef __shibsp_resctx_h__
-#define __shibsp_resctx_h__
-
-#include <shibsp/base.h>
-
-#include <vector>
-
-namespace opensaml {
- class SAML_API Assertion;
-};
-
-namespace shibsp {
-
- class SHIBSP_API Attribute;
-
- /**
- * A context for a resolution request.
- */
- class SHIBSP_API ResolutionContext
- {
- MAKE_NONCOPYABLE(ResolutionContext);
- protected:
- ResolutionContext();
- public:
- virtual ~ResolutionContext();
-
- /**
- * Returns the set of Attributes resolved and added to the context.
- *
- * <p>Any Attributes left in the returned container will be freed by the
- * context, so the caller should modify/clear the container after copying
- * objects for its own use.
- *
- * @return a mutable array of Attributes.
- */
- virtual std::vector<Attribute*>& getResolvedAttributes()=0;
-
- /**
- * Returns the set of assertions resolved and added to the context.
- *
- * <p>Any assertions left in the returned container will be freed by the
- * context, so the caller should modify/clear the container after copying
- * objects for its own use.
- *
- * @return a mutable array of Assertions
- */
- virtual std::vector<opensaml::Assertion*>& getResolvedAssertions()=0;
- };
-};
-
-#endif /* __shibsp_resctx_h__ */
diff --git a/shibsp/attribute/resolver/impl/AssertionAttributeExtractor.cpp b/shibsp/attribute/resolver/impl/AssertionAttributeExtractor.cpp
deleted file mode 100644
index 64d8136b..00000000
--- a/shibsp/attribute/resolver/impl/AssertionAttributeExtractor.cpp
+++ /dev/null
@@ -1,399 +0,0 @@
-/**
- * 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.
- */
-
-/**
- * AssertionAttributeExtractor.cpp
- *
- * AttributeExtractor for SAML assertion content.
- */
-
-#include "internal.h"
-#include "Application.h"
-#include "ServiceProvider.h"
-#include "attribute/SimpleAttribute.h"
-#include "attribute/resolver/AttributeExtractor.h"
-
-#include <saml/saml1/core/Assertions.h>
-#include <saml/saml2/core/Protocols.h>
-#include <saml/saml2/metadata/Metadata.h>
-#include <xmltooling/util/XMLHelper.h>
-#include <xercesc/util/XMLUniDefs.hpp>
-
-using namespace shibsp;
-using namespace opensaml::saml2;
-using namespace opensaml::saml2md;
-using namespace opensaml::saml1;
-using namespace opensaml;
-using namespace xmltooling;
-using namespace std;
-
-namespace shibsp {
-
-#if defined (_MSC_VER)
- #pragma warning( push )
- #pragma warning( disable : 4250 )
-#endif
-
- class AssertionExtractor : public AttributeExtractor
- {
- public:
- AssertionExtractor(const DOMElement* e);
- ~AssertionExtractor() {}
-
- Lockable* lock() {
- return this;
- }
-
- void unlock() {
- }
-
- void extractAttributes(
- const Application& application,
- const GenericRequest* request,
- const RoleDescriptor* issuer,
- const XMLObject& xmlObject,
- vector<shibsp::Attribute*>& attributes
- ) const;
- void getAttributeIds(vector<string>& attributes) const;
-
- private:
- string m_authnAuthority,
- m_authnClass,
- m_authnDecl,
- m_authnInstant,
- m_issuer,
- m_issuerFormat,
- m_notBefore,
- m_notOnOrAfter,
- m_sessionIndex,
- m_sessionNotOnOrAfter,
- m_subjectAddress,
- m_subjectDNS,
- m_consent;
- };
-
-#if defined (_MSC_VER)
- #pragma warning( pop )
-#endif
-
- AttributeExtractor* SHIBSP_DLLLOCAL AssertionAttributeExtractorFactory(const DOMElement* const & e, bool)
- {
- return new AssertionExtractor(e);
- }
-
- static const XMLCh IssuerFormat[] = UNICODE_LITERAL_12(I,s,s,u,e,r,F,o,r,m,a,t);
-};
-
-AssertionExtractor::AssertionExtractor(const DOMElement* e)
- : m_authnAuthority(XMLHelper::getAttrString(e, nullptr, AuthenticatingAuthority::LOCAL_NAME)),
- m_authnClass(XMLHelper::getAttrString(e, nullptr, AuthnContextClassRef::LOCAL_NAME)),
- m_authnDecl(XMLHelper::getAttrString(e, nullptr, AuthnContextDeclRef::LOCAL_NAME)),
- m_authnInstant(XMLHelper::getAttrString(e, nullptr, AuthnStatement::AUTHNINSTANT_ATTRIB_NAME)),
- m_issuer(XMLHelper::getAttrString(e, nullptr, Issuer::LOCAL_NAME)),
- m_issuerFormat(XMLHelper::getAttrString(e, nullptr, IssuerFormat)),
- m_notBefore(XMLHelper::getAttrString(e, nullptr, saml2::Conditions::NOTBEFORE_ATTRIB_NAME)),
- m_notOnOrAfter(XMLHelper::getAttrString(e, nullptr, saml2::Conditions::NOTONORAFTER_ATTRIB_NAME)),
- m_sessionIndex(XMLHelper::getAttrString(e, nullptr, AuthnStatement::SESSIONINDEX_ATTRIB_NAME)),
- m_sessionNotOnOrAfter(XMLHelper::getAttrString(e, nullptr, AuthnStatement::SESSIONNOTONORAFTER_ATTRIB_NAME)),
- m_subjectAddress(XMLHelper::getAttrString(e, nullptr, saml2::SubjectLocality::ADDRESS_ATTRIB_NAME)),
- m_subjectDNS(XMLHelper::getAttrString(e, nullptr, saml2::SubjectLocality::DNSNAME_ATTRIB_NAME)),
- m_consent(XMLHelper::getAttrString(e, nullptr, saml2p::StatusResponseType::CONSENT_ATTRIB_NAME))
-{
-}
-
-void AssertionExtractor::extractAttributes(
- const Application& application, const GenericRequest* request, const RoleDescriptor* issuer, const XMLObject& xmlObject, vector<shibsp::Attribute*>& attributes
- ) const
-{
- const saml2p::StatusResponseType* srt = dynamic_cast<const saml2p::StatusResponseType*>(&xmlObject);
- if (srt) {
- // Consent
- if (!m_consent.empty() && srt->getConsent()) {
- auto_ptr_char temp(srt->getConsent());
- if (temp.get() && *temp.get()) {
- auto_ptr<SimpleAttribute> consent(new SimpleAttribute(vector<string>(1, m_consent)));
- consent->getValues().push_back(temp.get());
- attributes.push_back(consent.get());
- consent.release();
- }
- }
- return;
- }
-
- const saml2::Assertion* saml2assertion = dynamic_cast<const saml2::Assertion*>(&xmlObject);
- if (saml2assertion) {
-
- if (saml2assertion->getIssuer()) {
- // Issuer
- if (!m_issuer.empty()) {
- auto_ptr_char temp(saml2assertion->getIssuer()->getName());
- if (temp.get() && *temp.get()) {
- auto_ptr<SimpleAttribute> issuer(new SimpleAttribute(vector<string>(1, m_issuer)));
- issuer->getValues().push_back(temp.get());
- attributes.push_back(issuer.get());
- issuer.release();
- }
- }
-
- // Format
- if (!m_issuerFormat.empty()) {
- auto_ptr_char temp(saml2assertion->getIssuer()->getFormat());
- if (temp.get()) {
- auto_ptr<SimpleAttribute> format(new SimpleAttribute(vector<string>(1, m_issuerFormat)));
- format->getValues().push_back(temp.get());
- attributes.push_back(format.get());
- format.release();
- }
- }
- }
-
- // NotBefore / NotOnOrAfter
- if (saml2assertion->getConditions()) {
- if (!m_notBefore.empty() && saml2assertion->getConditions()->getNotBefore()) {
- auto_ptr_char temp(saml2assertion->getConditions()->getNotBefore()->getRawData());
- if (temp.get()) {
- auto_ptr<SimpleAttribute> notbefore(new SimpleAttribute(vector<string>(1, m_notBefore)));
- notbefore->getValues().push_back(temp.get());
- attributes.push_back(notbefore.get());
- notbefore.release();
- }
- }
- if (!m_notOnOrAfter.empty() && saml2assertion->getConditions()->getNotOnOrAfter()) {
- auto_ptr_char temp(saml2assertion->getConditions()->getNotOnOrAfter()->getRawData());
- if (temp.get()) {
- auto_ptr<SimpleAttribute> notonorafter(new SimpleAttribute(vector<string>(1, m_notOnOrAfter)));
- notonorafter->getValues().push_back(temp.get());
- attributes.push_back(notonorafter.get());
- notonorafter.release();
- }
- }
- }
-
- return;
- }
-
- const AuthnStatement* saml2statement = dynamic_cast<const AuthnStatement*>(&xmlObject);
- if (saml2statement) {
- // AuthnInstant
- if (!m_authnInstant.empty() && saml2statement->getAuthnInstant()) {
- auto_ptr_char temp(saml2statement->getAuthnInstant()->getRawData());
- if (temp.get()) {
- auto_ptr<SimpleAttribute> authninstant(new SimpleAttribute(vector<string>(1, m_authnInstant)));
- authninstant->getValues().push_back(temp.get());
- attributes.push_back(authninstant.get());
- authninstant.release();
- }
- }
-
- // SessionIndex
- if (!m_sessionIndex.empty() && saml2statement->getSessionIndex() && *(saml2statement->getSessionIndex())) {
- auto_ptr_char temp(saml2statement->getSessionIndex());
- if (temp.get()) {
- auto_ptr<SimpleAttribute> sessionindex(new SimpleAttribute(vector<string>(1, m_sessionIndex)));
- sessionindex->getValues().push_back(temp.get());
- attributes.push_back(sessionindex.get());
- sessionindex.release();
- }
- }
-
- // SessionNotOnOrAfter
- if (!m_sessionNotOnOrAfter.empty() && saml2statement->getSessionNotOnOrAfter()) {
- auto_ptr_char temp(saml2statement->getSessionNotOnOrAfter()->getRawData());
- if (temp.get()) {
- auto_ptr<SimpleAttribute> sessionnotonorafter(new SimpleAttribute(vector<string>(1, m_sessionNotOnOrAfter)));
- sessionnotonorafter->getValues().push_back(temp.get());
- attributes.push_back(sessionnotonorafter.get());
- sessionnotonorafter.release();
- }
- }
-
- if (saml2statement->getSubjectLocality()) {
- const saml2::SubjectLocality* locality = saml2statement->getSubjectLocality();
- // Address
- if (!m_subjectAddress.empty() && locality->getAddress() && *(locality->getAddress())) {
- auto_ptr_char temp(locality->getAddress());
- if (temp.get()) {
- auto_ptr<SimpleAttribute> address(new SimpleAttribute(vector<string>(1, m_subjectAddress)));
- address->getValues().push_back(temp.get());
- attributes.push_back(address.get());
- address.release();
- }
- }
-
- // DNSName
- if (!m_subjectDNS.empty() && locality->getDNSName() && *(locality->getDNSName())) {
- auto_ptr_char temp(locality->getDNSName());
- if (temp.get()) {
- auto_ptr<SimpleAttribute> dns(new SimpleAttribute(vector<string>(1, m_subjectDNS)));
- dns->getValues().push_back(temp.get());
- attributes.push_back(dns.get());
- dns.release();
- }
- }
- }
-
- if (saml2statement->getAuthnContext()) {
- const AuthnContext* ac = saml2statement->getAuthnContext();
- // AuthnContextClassRef
- if (!m_authnClass.empty() && ac->getAuthnContextClassRef() && ac->getAuthnContextClassRef()->getReference()) {
- auto_ptr_char temp(ac->getAuthnContextClassRef()->getReference());
- if (temp.get()) {
- auto_ptr<SimpleAttribute> classref(new SimpleAttribute(vector<string>(1, m_authnClass)));
- classref->getValues().push_back(temp.get());
- attributes.push_back(classref.get());
- classref.release();
- }
- }
-
- // AuthnContextDeclRef
- if (!m_authnDecl.empty() && ac->getAuthnContextDeclRef() && ac->getAuthnContextDeclRef()->getReference()) {
- auto_ptr_char temp(ac->getAuthnContextDeclRef()->getReference());
- if (temp.get()) {
- auto_ptr<SimpleAttribute> declref(new SimpleAttribute(vector<string>(1, m_authnDecl)));
- declref->getValues().push_back(temp.get());
- attributes.push_back(declref.get());
- declref.release();
- }
- }
-
- // AuthenticatingAuthority
- if (!m_authnAuthority.empty() && !ac->getAuthenticatingAuthoritys().empty()) {
- auto_ptr<SimpleAttribute> attr(new SimpleAttribute(vector<string>(1, m_authnAuthority)));
- const vector<AuthenticatingAuthority*>& authorities = ac->getAuthenticatingAuthoritys();
- for (vector<AuthenticatingAuthority*>::const_iterator a = authorities.begin(); a != authorities.end(); ++a) {
- auto_ptr_char temp((*a)->getID());
- if (temp.get())
- attr->getValues().push_back(temp.get());
- }
- if (attr->valueCount() > 0) {
- attributes.push_back(attr.get());
- attr.release();
- }
- }
- }
-
- return;
- }
-
- const saml1::Assertion* saml1assertion = dynamic_cast<const saml1::Assertion*>(&xmlObject);
- if (saml1assertion) {
- // Issuer
- if (!m_issuer.empty()) {
- if (saml1assertion->getIssuer() && *(saml1assertion->getIssuer())) {
- auto_ptr_char temp(saml1assertion->getIssuer());
- if (temp.get()) {
- auto_ptr<SimpleAttribute> issuer(new SimpleAttribute(vector<string>(1, m_issuer)));
- issuer->getValues().push_back(temp.get());
- attributes.push_back(issuer.get());
- issuer.release();
- }
- }
- }
-
- // NotOnOrAfter
- if (!m_notOnOrAfter.empty() && saml1assertion->getConditions() && saml1assertion->getConditions()->getNotOnOrAfter()) {
- auto_ptr_char temp(saml1assertion->getConditions()->getNotOnOrAfter()->getRawData());
- if (temp.get()) {
- auto_ptr<SimpleAttribute> notonorafter(new SimpleAttribute(vector<string>(1, m_notOnOrAfter)));
- notonorafter->getValues().push_back(temp.get());
- attributes.push_back(notonorafter.get());
- notonorafter.release();
- }
- }
-
- return;
- }
-
- const AuthenticationStatement* saml1statement = dynamic_cast<const AuthenticationStatement*>(&xmlObject);
- if (saml1statement) {
- // AuthnInstant
- if (!m_authnInstant.empty() && saml1statement->getAuthenticationInstant()) {
- auto_ptr_char temp(saml1statement->getAuthenticationInstant()->getRawData());
- if (temp.get()) {
- auto_ptr<SimpleAttribute> authninstant(new SimpleAttribute(vector<string>(1, m_authnInstant)));
- authninstant->getValues().push_back(temp.get());
- attributes.push_back(authninstant.get());
- authninstant.release();
- }
- }
-
- // AuthenticationMethod
- if (!m_authnClass.empty() && saml1statement->getAuthenticationMethod() && *(saml1statement->getAuthenticationMethod())) {
- auto_ptr_char temp(saml1statement->getAuthenticationMethod());
- if (temp.get()) {
- auto_ptr<SimpleAttribute> authnmethod(new SimpleAttribute(vector<string>(1, m_authnClass)));
- authnmethod->getValues().push_back(temp.get());
- attributes.push_back(authnmethod.get());
- authnmethod.release();
- }
- }
-
- if (saml1statement->getSubjectLocality()) {
- const saml1::SubjectLocality* locality = saml1statement->getSubjectLocality();
- // IPAddress
- if (!m_subjectAddress.empty() && locality->getIPAddress() && *(locality->getIPAddress())) {
- auto_ptr_char temp(locality->getIPAddress());
- if (temp.get()) {
- auto_ptr<SimpleAttribute> address(new SimpleAttribute(vector<string>(1, m_subjectAddress)));
- address->getValues().push_back(temp.get());
- attributes.push_back(address.get());
- address.release();
- }
- }
-
- // DNSAddress
- if (!m_subjectDNS.empty() && locality->getDNSAddress() && *(locality->getDNSAddress())) {
- auto_ptr_char temp(locality->getDNSAddress());
- if (temp.get()) {
- auto_ptr<SimpleAttribute> dns(new SimpleAttribute(vector<string>(1, m_subjectDNS)));
- dns->getValues().push_back(temp.get());
- attributes.push_back(dns.get());
- dns.release();
- }
- }
- }
- }
-}
-
-void AssertionExtractor::getAttributeIds(vector<string>& attributes) const
-{
- if (!m_authnAuthority.empty())
- attributes.push_back(m_authnAuthority);
- if (!m_authnClass.empty())
- attributes.push_back(m_authnClass);
- if (!m_authnDecl.empty())
- attributes.push_back(m_authnDecl);
- if (!m_authnInstant.empty())
- attributes.push_back(m_authnInstant);
- if (!m_issuer.empty())
- attributes.push_back(m_issuer);
- if (!m_notOnOrAfter.empty())
- attributes.push_back(m_notOnOrAfter);
- if (!m_sessionIndex.empty())
- attributes.push_back(m_sessionIndex);
- if (!m_sessionNotOnOrAfter.empty())
- attributes.push_back(m_sessionNotOnOrAfter);
- if (!m_subjectAddress.empty())
- attributes.push_back(m_subjectAddress);
- if (!m_subjectDNS.empty())
- attributes.push_back(m_subjectDNS);
- if (!m_consent.empty())
- attributes.push_back(m_consent);
-}
diff --git a/shibsp/attribute/resolver/impl/ChainingAttributeExtractor.cpp b/shibsp/attribute/resolver/impl/ChainingAttributeExtractor.cpp
deleted file mode 100644
index 07a7d4ff..00000000
--- a/shibsp/attribute/resolver/impl/ChainingAttributeExtractor.cpp
+++ /dev/null
@@ -1,150 +0,0 @@
-/**
- * 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.
- */
-
-/**
- * ChainingAttributeExtractor.cpp
- *
- * Chains together multiple AttributeExtractor plugins.
- */
-
-#include "internal.h"
-#include "Application.h"
-#include "ServiceProvider.h"
-#include "attribute/Attribute.h"
-#include "attribute/resolver/AttributeExtractor.h"
-
-#include <boost/ptr_container/ptr_vector.hpp>
-#include <xercesc/util/XMLUniDefs.hpp>
-#include <xmltooling/util/XMLHelper.h>
-
-using namespace shibsp;
-using namespace opensaml::saml2md;
-using namespace xmltooling;
-using namespace boost;
-using namespace std;
-
-namespace shibsp {
-
- class SHIBSP_DLLLOCAL ChainingAttributeExtractor : public AttributeExtractor
- {
- public:
- ChainingAttributeExtractor(const DOMElement* e, bool deprecationSupport=true);
- virtual ~ChainingAttributeExtractor() {}
-
- Lockable* lock() {
- return this;
- }
- void unlock() {
- }
-
- void extractAttributes(
- const Application& application,
- const GenericRequest* request,
- const RoleDescriptor* issuer,
- const XMLObject& xmlObject,
- vector<Attribute*>& attributes
- ) const {
- for (ptr_vector<AttributeExtractor>::iterator i = m_extractors.begin(); i != m_extractors.end(); ++i) {
- Locker locker(&(*i));
- i->extractAttributes(application, request, issuer, xmlObject, attributes);
- }
- }
-
- void getAttributeIds(vector<string>& attributes) const {
- for (ptr_vector<AttributeExtractor>::iterator i = m_extractors.begin(); i != m_extractors.end(); ++i) {
- Locker locker(&(*i));
- i->getAttributeIds(attributes);
- }
- }
-
- void generateMetadata(SPSSODescriptor& role) const {
- for (ptr_vector<AttributeExtractor>::iterator i = m_extractors.begin(); i != m_extractors.end(); ++i) {
- Locker locker(&(*i));
- i->generateMetadata(role);
- }
- }
-
- private:
- mutable ptr_vector<AttributeExtractor> m_extractors;
- };
-
- static const XMLCh _AttributeExtractor[] = UNICODE_LITERAL_18(A,t,t,r,i,b,u,t,e,E,x,t,r,a,c,t,o,r);
- static const XMLCh _type[] = UNICODE_LITERAL_4(t,y,p,e);
-
- SHIBSP_DLLLOCAL PluginManager<AttributeExtractor,string,const DOMElement*>::Factory AssertionAttributeExtractorFactory;
- SHIBSP_DLLLOCAL PluginManager<AttributeExtractor,string,const DOMElement*>::Factory MetadataAttributeExtractorFactory;
- SHIBSP_DLLLOCAL PluginManager<AttributeExtractor,string,const DOMElement*>::Factory DelegationAttributeExtractorFactory;
- SHIBSP_DLLLOCAL PluginManager<AttributeExtractor,string,const DOMElement*>::Factory KeyDescriptorAttributeExtractorFactory;
- SHIBSP_DLLLOCAL PluginManager<AttributeExtractor,string,const DOMElement*>::Factory XMLAttributeExtractorFactory;
-
- AttributeExtractor* SHIBSP_DLLLOCAL ChainingExtractorFactory(const DOMElement* const & e, bool deprecationSupport)
- {
- return new ChainingAttributeExtractor(e, deprecationSupport);
- }
-};
-
-void SHIBSP_API shibsp::registerAttributeExtractors()
-{
- SPConfig::getConfig().AttributeExtractorManager.registerFactory(ASSERTION_ATTRIBUTE_EXTRACTOR, AssertionAttributeExtractorFactory);
- SPConfig::getConfig().AttributeExtractorManager.registerFactory(METADATA_ATTRIBUTE_EXTRACTOR, MetadataAttributeExtractorFactory);
- SPConfig::getConfig().AttributeExtractorManager.registerFactory(DELEGATION_ATTRIBUTE_EXTRACTOR, DelegationAttributeExtractorFactory);
- SPConfig::getConfig().AttributeExtractorManager.registerFactory(KEYDESCRIPTOR_ATTRIBUTE_EXTRACTOR, KeyDescriptorAttributeExtractorFactory);
- SPConfig::getConfig().AttributeExtractorManager.registerFactory(XML_ATTRIBUTE_EXTRACTOR, XMLAttributeExtractorFactory);
- SPConfig::getConfig().AttributeExtractorManager.registerFactory(CHAINING_ATTRIBUTE_EXTRACTOR, ChainingExtractorFactory);
-}
-
-AttributeExtractor::AttributeExtractor()
-{
-}
-
-AttributeExtractor::~AttributeExtractor()
-{
-}
-
-void AttributeExtractor::generateMetadata(SPSSODescriptor& role) const
-{
-}
-
-ChainingAttributeExtractor::ChainingAttributeExtractor(const DOMElement* e, bool deprecationSupport)
-{
- SPConfig& conf = SPConfig::getConfig();
-
- // Load up the chain of handlers.
- e = XMLHelper::getFirstChildElement(e, _AttributeExtractor);
- while (e) {
- string t(XMLHelper::getAttrString(e, nullptr, _type));
- if (!t.empty()) {
- try {
- Category::getInstance(SHIBSP_LOGCAT ".AttributeExtractor.Chaining").info(
- "building AttributeExtractor of type (%s)...", t.c_str()
- );
- auto_ptr<AttributeExtractor> np(conf.AttributeExtractorManager.newPlugin(t.c_str(), e, deprecationSupport));
- m_extractors.push_back(np.get());
- np.release();
- }
- catch (const exception& ex) {
- Category::getInstance(SHIBSP_LOGCAT ".AttributeExtractor.Chaining").error(
- "caught exception processing embedded AttributeExtractor element: %s", ex.what()
- );
- }
- }
- e = XMLHelper::getNextSiblingElement(e, _AttributeExtractor);
- }
-}
diff --git a/shibsp/attribute/resolver/impl/ChainingAttributeResolver.cpp b/shibsp/attribute/resolver/impl/ChainingAttributeResolver.cpp
deleted file mode 100644
index c9b5b78a..00000000
--- a/shibsp/attribute/resolver/impl/ChainingAttributeResolver.cpp
+++ /dev/null
@@ -1,242 +0,0 @@
-/**
- * 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.
- */
-
-/**
- * ChainingAttributeResolver.cpp
- *
- * Chains together multiple AttributeResolver plugins.
- */
-
-#include "internal.h"
-#include "exceptions.h"
-#include "Application.h"
-#include "ServiceProvider.h"
-#include "attribute/Attribute.h"
-#include "attribute/resolver/AttributeResolver.h"
-#include "attribute/resolver/ResolutionContext.h"
-
-#include <boost/ptr_container/ptr_vector.hpp>
-#include <xercesc/util/XMLUniDefs.hpp>
-#include <saml/Assertion.h>
-#include <xmltooling/util/XMLHelper.h>
-
-using namespace shibsp;
-using namespace opensaml::saml2;
-using namespace opensaml::saml2md;
-using namespace xmltooling;
-using namespace boost;
-using namespace std;
-
-namespace shibsp {
-
- struct SHIBSP_DLLLOCAL ChainingContext : public ResolutionContext
- {
- ChainingContext(
- const Application& application,
- const GenericRequest* request,
- const EntityDescriptor* issuer,
- const XMLCh* protocol,
- const NameID* nameid,
- const XMLCh* authncontext_class,
- const XMLCh* authncontext_decl,
- const vector<const opensaml::Assertion*>* tokens,
- const vector<shibsp::Attribute*>* attributes
- ) : m_app(application), m_request(request), m_issuer(issuer), m_protocol(protocol), m_nameid(nameid),
- m_authclass(authncontext_class), m_authdecl(authncontext_decl), m_session(nullptr) {
- if (tokens)
- m_tokens.assign(tokens->begin(), tokens->end());
- if (attributes)
- m_attributes.assign(attributes->begin(), attributes->end());
- }
-
- ChainingContext(const Application& application, const Session& session)
- : m_app(application), m_request(nullptr), m_issuer(nullptr), m_protocol(nullptr), m_nameid(nullptr),
- m_authclass(nullptr), m_authdecl(nullptr), m_session(&session) {
- }
-
- ~ChainingContext() {
- for_each(m_ownedAttributes.begin(), m_ownedAttributes.end(), xmltooling::cleanup<shibsp::Attribute>());
- for_each(m_ownedAssertions.begin(), m_ownedAssertions.end(), xmltooling::cleanup<opensaml::Assertion>());
- }
-
- vector<shibsp::Attribute*>& getResolvedAttributes() {
- return m_ownedAttributes;
- }
- vector<opensaml::Assertion*>& getResolvedAssertions() {
- return m_ownedAssertions;
- }
-
- vector<shibsp::Attribute*> m_ownedAttributes;
- vector<opensaml::Assertion*> m_ownedAssertions;
-
- const Application& m_app;
- const GenericRequest* m_request;
- const EntityDescriptor* m_issuer;
- const XMLCh* m_protocol;
- const NameID* m_nameid;
- const XMLCh* m_authclass;
- const XMLCh* m_authdecl;
- vector<const opensaml::Assertion*> m_tokens;
- vector<shibsp::Attribute*> m_attributes;
-
- const Session* m_session;
- };
-
- class SHIBSP_DLLLOCAL ChainingAttributeResolver : public AttributeResolver
- {
- public:
- ChainingAttributeResolver(const DOMElement* e, bool deprecationSupport=true);
- virtual ~ChainingAttributeResolver() {}
-
- Lockable* lock() {
- return this;
- }
- void unlock() {
- }
-
- ResolutionContext* createResolutionContext(
- const Application& application,
- const GenericRequest* request,
- const EntityDescriptor* issuer,
- const XMLCh* protocol,
- const NameID* nameid=nullptr,
- const XMLCh* authncontext_class=nullptr,
- const XMLCh* authncontext_decl=nullptr,
- const vector<const opensaml::Assertion*>* tokens=nullptr,
- const vector<shibsp::Attribute*>* attributes=nullptr
- ) const {
- return new ChainingContext(application, request, issuer, protocol, nameid, authncontext_class, authncontext_decl, tokens, attributes);
- }
-
- ResolutionContext* createResolutionContext(const Application& application, const Session& session) const {
- return new ChainingContext(application, session);
- }
-
- void resolveAttributes(ResolutionContext& ctx) const;
-
- void getAttributeIds(vector<string>& attributes) const {
- for (ptr_vector<AttributeResolver>::iterator i = m_resolvers.begin(); i != m_resolvers.end(); ++i) {
- Locker locker(&(*i));
- i->getAttributeIds(attributes);
- }
- }
-
- private:
- mutable ptr_vector<AttributeResolver> m_resolvers;
- bool m_failFast;
- };
-
- static const XMLCh _AttributeResolver[] = UNICODE_LITERAL_17(A,t,t,r,i,b,u,t,e,R,e,s,o,l,v,e,r);
- static const XMLCh failFast[] = UNICODE_LITERAL_8(f,a,i,l,F,a,s,t);
- static const XMLCh _type[] = UNICODE_LITERAL_4(t,y,p,e);
-
- SHIBSP_DLLLOCAL PluginManager<AttributeResolver,string,const DOMElement*>::Factory QueryResolverFactory;
- SHIBSP_DLLLOCAL PluginManager<AttributeResolver,string,const DOMElement*>::Factory SimpleAggregationResolverFactory;
-
- AttributeResolver* SHIBSP_DLLLOCAL ChainingResolverFactory(const DOMElement* const & e, bool deprecationSupport)
- {
- return new ChainingAttributeResolver(e, deprecationSupport);
- }
-};
-
-void SHIBSP_API shibsp::registerAttributeResolvers()
-{
- SPConfig::getConfig().AttributeResolverManager.registerFactory(QUERY_ATTRIBUTE_RESOLVER, QueryResolverFactory);
- SPConfig::getConfig().AttributeResolverManager.registerFactory(SIMPLEAGGREGATION_ATTRIBUTE_RESOLVER, SimpleAggregationResolverFactory);
- SPConfig::getConfig().AttributeResolverManager.registerFactory(CHAINING_ATTRIBUTE_RESOLVER, ChainingResolverFactory);
-}
-
-ResolutionContext::ResolutionContext()
-{
-}
-
-ResolutionContext::~ResolutionContext()
-{
-}
-
-AttributeResolver::AttributeResolver()
-{
-}
-
-AttributeResolver::~AttributeResolver()
-{
-}
-
-ChainingAttributeResolver::ChainingAttributeResolver(const DOMElement* e, bool deprecationSupport)
- : m_failFast(XMLHelper::getAttrBool(e, false, failFast))
-{
- SPConfig& conf = SPConfig::getConfig();
-
- // Load up the chain of handlers.
- e = XMLHelper::getFirstChildElement(e, _AttributeResolver);
- while (e) {
- string t(XMLHelper::getAttrString(e, nullptr, _type));
- if (!t.empty()) {
- try {
- Category::getInstance(SHIBSP_LOGCAT ".AttributeResolver." CHAINING_ATTRIBUTE_RESOLVER).info(
- "building AttributeResolver of type (%s)...", t.c_str()
- );
- auto_ptr<AttributeResolver> np(conf.AttributeResolverManager.newPlugin(t.c_str(), e, deprecationSupport));
- m_resolvers.push_back(np.get());
- np.release();
- }
- catch (const exception& ex) {
- Category::getInstance(SHIBSP_LOGCAT ".AttributeResolver." CHAINING_ATTRIBUTE_RESOLVER).error(
- "caught exception processing embedded AttributeResolver element: %s", ex.what()
- );
- }
- }
- e = XMLHelper::getNextSiblingElement(e, _AttributeResolver);
- }
-}
-
-void ChainingAttributeResolver::resolveAttributes(ResolutionContext& ctx) const
-{
- ChainingContext& chain = dynamic_cast<ChainingContext&>(ctx);
- for (ptr_vector<AttributeResolver>::iterator i = m_resolvers.begin(); i != m_resolvers.end(); ++i) {
- try {
- Locker locker(&(*i));
- scoped_ptr<ResolutionContext> context(
- chain.m_session ?
- i->createResolutionContext(chain.m_app, *chain.m_session) :
- i->createResolutionContext(
- chain.m_app, chain.m_request, chain.m_issuer, chain.m_protocol, chain.m_nameid, chain.m_authclass, chain.m_authdecl, &chain.m_tokens, &chain.m_attributes
- )
- );
-
- i->resolveAttributes(*context);
-
- chain.m_attributes.insert(chain.m_attributes.end(), context->getResolvedAttributes().begin(), context->getResolvedAttributes().end());
- chain.m_ownedAttributes.insert(chain.m_ownedAttributes.end(), context->getResolvedAttributes().begin(), context->getResolvedAttributes().end());
- context->getResolvedAttributes().clear();
-
- chain.m_tokens.insert(chain.m_tokens.end(), context->getResolvedAssertions().begin(), context->getResolvedAssertions().end());
- chain.m_ownedAssertions.insert(chain.m_ownedAssertions.end(), context->getResolvedAssertions().begin(), context->getResolvedAssertions().end());
- context->getResolvedAssertions().clear();
- }
- catch (const exception& ex) {
- Category::getInstance(SHIBSP_LOGCAT ".AttributeResolver." CHAINING_ATTRIBUTE_RESOLVER).error(
- "caught exception applying AttributeResolver in chain: %s", ex.what()
- );
- if (failFast)
- throw;
- }
- }
-}
diff --git a/shibsp/attribute/resolver/impl/DelegationAttributeExtractor.cpp b/shibsp/attribute/resolver/impl/DelegationAttributeExtractor.cpp
deleted file mode 100644
index 2b9d8413..00000000
--- a/shibsp/attribute/resolver/impl/DelegationAttributeExtractor.cpp
+++ /dev/null
@@ -1,202 +0,0 @@
-/**
- * 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.
- */
-
-/**
- * DelegationAttributeExtractor.cpp
- *
- * AttributeExtractor for DelegationRestriction information.
- */
-
-#include "internal.h"
-#include "Application.h"
-#include "ServiceProvider.h"
-#include "attribute/ExtensibleAttribute.h"
-#include "attribute/resolver/AttributeExtractor.h"
-#include "util/SPConstants.h"
-
-#include <boost/shared_ptr.hpp>
-#include <boost/iterator/indirect_iterator.hpp>
-#include <saml/saml2/core/Assertions.h>
-#include <saml/saml2/metadata/Metadata.h>
-#include <saml/saml2/metadata/MetadataCredentialCriteria.h>
-#include <xmltooling/security/CredentialResolver.h>
-#include <xmltooling/util/XMLHelper.h>
-#include <xercesc/util/XMLUniDefs.hpp>
-
-using namespace shibsp;
-using namespace opensaml::saml2md;
-using namespace opensaml;
-using namespace xmltooling;
-using namespace boost;
-using namespace std;
-
-namespace shibsp {
-
-#if defined (_MSC_VER)
- #pragma warning( push )
- #pragma warning( disable : 4250 )
-#endif
-
- class DelegationExtractor : public AttributeExtractor
- {
- public:
- DelegationExtractor(const DOMElement* e);
- ~DelegationExtractor() {}
-
- Lockable* lock() {
- return this;
- }
-
- void unlock() {
- }
-
- void extractAttributes(
- const Application& application, const GenericRequest* request, const RoleDescriptor* issuer, const XMLObject& xmlObject, vector<Attribute*>& attributes
- ) const;
-
- void getAttributeIds(std::vector<std::string>& attributes) const {
- attributes.push_back(m_attributeId);
- }
-
- private:
- string m_attributeId,m_formatter;
- };
-
-#if defined (_MSC_VER)
- #pragma warning( pop )
-#endif
-
- AttributeExtractor* SHIBSP_DLLLOCAL DelegationAttributeExtractorFactory(const DOMElement* const & e, bool)
- {
- return new DelegationExtractor(e);
- }
-
- static const XMLCh attributeId[] = UNICODE_LITERAL_11(a,t,t,r,i,b,u,t,e,I,d);
- static const XMLCh formatter[] = UNICODE_LITERAL_9(f,o,r,m,a,t,t,e,r);
-};
-
-DelegationExtractor::DelegationExtractor(const DOMElement* e)
- : m_attributeId(XMLHelper::getAttrString(e, "delegate", attributeId)),
- m_formatter(XMLHelper::getAttrString(e, "$Name", formatter))
-{
-}
-
-void DelegationExtractor::extractAttributes(
- const Application& application, const GenericRequest* request, const RoleDescriptor* issuer, const XMLObject& xmlObject, vector<Attribute*>& attributes
- ) const
-{
- const saml2::Assertion* assertion = dynamic_cast<const saml2::Assertion*>(&xmlObject);
- if (!assertion || !assertion->getConditions())
- return;
-
- Category& log = Category::getInstance(SHIBSP_LOGCAT ".AttributeExtractor.Delegation");
-
- const vector<saml2::Condition*>& conditions = const_cast<const saml2::Conditions*>(assertion->getConditions())->getConditions();
- for (vector<saml2::Condition*>::const_iterator c = conditions.begin(); c != conditions.end(); ++c) {
- const saml2::DelegationRestrictionType* drt = dynamic_cast<const saml2::DelegationRestrictionType*>(*c);
- if (drt) {
- auto_ptr<ExtensibleAttribute> attr(new ExtensibleAttribute(vector<string>(1,m_attributeId), m_formatter.c_str()));
-
- const vector<saml2::Delegate*>& dels = drt->getDelegates();
- for (indirect_iterator<vector<saml2::Delegate*>::const_iterator> d = make_indirect_iterator(dels.begin());
- d != make_indirect_iterator(dels.end()); ++d) {
- if (d->getBaseID()) {
- log.error("delegate identified by saml:BaseID cannot be processed into an attribute value");
- continue;
- }
-
- saml2::NameID* n = nullptr;
- boost::shared_ptr<saml2::NameID> namewrapper;
- if (d->getEncryptedID()) {
- CredentialResolver* cr = application.getCredentialResolver();
- if (!cr) {
- log.warn("found encrypted Delegate, but no CredentialResolver was available");
- }
-
- try {
- const XMLCh* recipient = application.getRelyingParty(
- issuer ? dynamic_cast<EntityDescriptor*>(issuer->getParent()) : nullptr
- )->getXMLString("entityID").second;
- Locker credlocker(cr);
- if (issuer) {
- MetadataCredentialCriteria mcc(*issuer);
- boost::shared_ptr<XMLObject> decrypted(d->getEncryptedID()->decrypt(*cr, recipient, &mcc));
- namewrapper = dynamic_pointer_cast<saml2::NameID>(decrypted);
- n = namewrapper.get();
- }
- else {
- boost::shared_ptr<XMLObject> decrypted(d->getEncryptedID()->decrypt(*cr, recipient));
- namewrapper = dynamic_pointer_cast<saml2::NameID>(decrypted);
- n = namewrapper.get();
- }
- if (n && log.isDebugEnabled())
- log.debugStream() << "decrypted Delegate: " << *n << logging::eol;
- }
- catch (std::exception& ex) {
- log.error("caught exception decrypting Delegate: %s", ex.what());
- }
- }
- else {
- n = d->getNameID();
- }
-
- if (n) {
- DDF val = DDF(nullptr).structure();
- if (d->getConfirmationMethod()) {
- auto_ptr_char temp(d->getConfirmationMethod());
- val.addmember("ConfirmationMethod").string(temp.get());
- }
- if (d->getDelegationInstant()) {
- auto_ptr_char temp(d->getDelegationInstant()->getRawData());
- val.addmember("DelegationInstant").string(temp.get());
- }
-
- auto_arrayptr<char> name(toUTF8(n->getName()));
- if (name.get() && *name.get()) {
- val.addmember("Name").string(name.get());
- auto_arrayptr<char> format(toUTF8(n->getFormat()));
- if (format.get())
- val.addmember("Format").string(format.get());
-
- auto_arrayptr<char> nq(toUTF8(n->getNameQualifier()));
- if (nq.get())
- val.addmember("NameQualifier").string(nq.get());
-
- auto_arrayptr<char> spnq(toUTF8(n->getSPNameQualifier()));
- if (spnq.get())
- val.addmember("SPNameQualifier").string(spnq.get());
-
- auto_arrayptr<char> sppid(toUTF8(n->getSPProvidedID()));
- if (sppid.get())
- val.addmember("SPProvidedID").string(sppid.get());
- }
-
- if (val.integer())
- attr->getValues().add(val);
- else
- val.destroy();
- }
- }
-
- attributes.push_back(attr.get());
- attr.release();
- }
- }
-}
diff --git a/shibsp/attribute/resolver/impl/KeyDescriptorAttributeExtractor.cpp b/shibsp/attribute/resolver/impl/KeyDescriptorAttributeExtractor.cpp
deleted file mode 100644
index 370321d2..00000000
--- a/shibsp/attribute/resolver/impl/KeyDescriptorAttributeExtractor.cpp
+++ /dev/null
@@ -1,192 +0,0 @@
-/**
- * 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.
- */
-
-/**
- * KeyDescriptorAttributeExtractor.cpp
- *
- * AttributeExtractor for KeyDescriptor information.
- */
-
-#include "internal.h"
-#include "exceptions.h"
-#include "Application.h"
-#include "attribute/AttributeDecoder.h"
-#include "attribute/SimpleAttribute.h"
-#include "attribute/resolver/AttributeExtractor.h"
-
-#include <boost/iterator/indirect_iterator.hpp>
-#include <saml/saml2/metadata/Metadata.h>
-#include <saml/saml2/metadata/MetadataCredentialCriteria.h>
-#include <saml/saml2/metadata/MetadataProvider.h>
-#include <xmltooling/security/Credential.h>
-#include <xmltooling/security/SecurityHelper.h>
-#include <xmltooling/util/XMLHelper.h>
-#include <xercesc/util/XMLUniDefs.hpp>
-
-using namespace shibsp;
-using namespace opensaml::saml2md;
-using namespace opensaml;
-using namespace xmltooling;
-using namespace boost;
-using namespace std;
-
-namespace shibsp {
-
-#if defined (_MSC_VER)
- #pragma warning( push )
- #pragma warning( disable : 4250 )
-#endif
-
- class KeyDescriptorExtractor : public AttributeExtractor
- {
- public:
- KeyDescriptorExtractor(const DOMElement* e);
- ~KeyDescriptorExtractor() {}
-
- Lockable* lock() {
- return this;
- }
-
- void unlock() {
- }
-
- void extractAttributes(
- const Application& application, const GenericRequest* request, const RoleDescriptor* issuer, const XMLObject& xmlObject, vector<Attribute*>& attributes
- ) const;
-
- void getAttributeIds(std::vector<std::string>& attributes) const {
- if (!m_hashId.empty())
- attributes.push_back(m_hashId.front());
- if (!m_signingId.empty())
- attributes.push_back(m_signingId.front());
- if (!m_encryptionId.empty())
- attributes.push_back(m_encryptionId.front());
- }
-
- private:
- string m_hashAlg;
- vector<string> m_hashId;
- vector<string> m_signingId;
- vector<string> m_encryptionId;
- };
-
-#if defined (_MSC_VER)
- #pragma warning( pop )
-#endif
-
- AttributeExtractor* SHIBSP_DLLLOCAL KeyDescriptorAttributeExtractorFactory(const DOMElement* const & e, bool)
- {
- return new KeyDescriptorExtractor(e);
- }
-
- static const XMLCh encryptionId[] = UNICODE_LITERAL_12(e,n,c,r,y,p,t,i,o,n,I,d);
- static const XMLCh hashId[] = UNICODE_LITERAL_6(h,a,s,h,I,d);
- static const XMLCh hashAlg[] = UNICODE_LITERAL_7(h,a,s,h,A,l,g);
- static const XMLCh signingId[] = UNICODE_LITERAL_9(s,i,g,n,i,n,g,I,d);
-};
-
-KeyDescriptorExtractor::KeyDescriptorExtractor(const DOMElement* e) : m_hashAlg(XMLHelper::getAttrString(e, "SHA1", hashAlg))
-{
- SPConfig::getConfig().deprecation().warn(KEYDESCRIPTOR_ATTRIBUTE_EXTRACTOR" AttributeExtractor");
- if (e) {
- string a(XMLHelper::getAttrString(e, nullptr, hashId));
- if (!a.empty())
- m_hashId.push_back(a);
- a = XMLHelper::getAttrString(e, nullptr, signingId);
- if (!a.empty())
- m_signingId.push_back(a);
- a = XMLHelper::getAttrString(e, nullptr, encryptionId);
- if (!a.empty())
- m_encryptionId.push_back(a);
- }
- if (m_hashId.empty() && m_signingId.empty() && m_encryptionId.empty())
- throw ConfigurationException("KeyDescriptor AttributeExtractor requires hashId, signingId, or encryptionId property.");
-}
-
-void KeyDescriptorExtractor::extractAttributes(
- const Application& application, const GenericRequest* request, const RoleDescriptor* issuer, const XMLObject& xmlObject, vector<Attribute*>& attributes
- ) const
-{
- const RoleDescriptor* role = dynamic_cast<const RoleDescriptor*>(&xmlObject);
- if (!role)
- return;
-
- vector<const Credential*> creds;
- MetadataCredentialCriteria mcc(*role);
-
- if (!m_signingId.empty() || !m_hashId.empty()) {
- mcc.setUsage(Credential::SIGNING_CREDENTIAL);
- if (application.getMetadataProvider()->resolve(creds, &mcc)) {
- if (!m_hashId.empty()) {
- auto_ptr<SimpleAttribute> attr(new SimpleAttribute(m_hashId));
- vector<string>& vals = attr->getValues();
- for (indirect_iterator<vector<const Credential*>::const_iterator> c = make_indirect_iterator(creds.begin());
- c != make_indirect_iterator(creds.end()); ++c) {
- if (vals.empty() || !vals.back().empty())
- vals.push_back(string());
- vals.back() = SecurityHelper::getDEREncoding(*c, m_hashAlg.c_str());
- }
- if (vals.back().empty())
- vals.pop_back();
- if (!vals.empty()) {
- attributes.push_back(attr.get());
- attr.release();
- }
- }
- if (!m_signingId.empty()) {
- auto_ptr<SimpleAttribute> attr(new SimpleAttribute(m_signingId));
- vector<string>& vals = attr->getValues();
- for (indirect_iterator<vector<const Credential*>::const_iterator> c = make_indirect_iterator(creds.begin());
- c != make_indirect_iterator(creds.end()); ++c) {
- if (vals.empty() || !vals.back().empty())
- vals.push_back(string());
- vals.back() = SecurityHelper::getDEREncoding(*c);
- }
- if (vals.back().empty())
- vals.pop_back();
- if (!vals.empty()) {
- attributes.push_back(attr.get());
- attr.release();
- }
- }
- creds.clear();
- }
- }
-
- if (!m_encryptionId.empty()) {
- mcc.setUsage(Credential::ENCRYPTION_CREDENTIAL);
- if (application.getMetadataProvider()->resolve(creds, &mcc)) {
- auto_ptr<SimpleAttribute> attr(new SimpleAttribute(m_encryptionId));
- vector<string>& vals = attr->getValues();
- for (indirect_iterator<vector<const Credential*>::const_iterator> c = make_indirect_iterator(creds.begin());
- c != make_indirect_iterator(creds.end()); ++c) {
- if (vals.empty() || !vals.back().empty())
- vals.push_back(string());
- vals.back() = SecurityHelper::getDEREncoding(*c);
- }
- if (vals.back().empty())
- vals.pop_back();
- if (!vals.empty()) {
- attributes.push_back(attr.get());
- attr.release();
- }
- }
- }
-}
diff --git a/shibsp/attribute/resolver/impl/MetadataAttributeExtractor.cpp b/shibsp/attribute/resolver/impl/MetadataAttributeExtractor.cpp
deleted file mode 100644
index 600de29a..00000000
--- a/shibsp/attribute/resolver/impl/MetadataAttributeExtractor.cpp
+++ /dev/null
@@ -1,406 +0,0 @@
-/**
- * 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.
- */
-
-/**
- * MetadataAttributeExtractor.cpp
- *
- * AttributeExtractor for SAML metadata content.
- */
-
-#include "internal.h"
-#include "Application.h"
-#include "ServiceProvider.h"
-#include "attribute/SimpleAttribute.h"
-#include "attribute/AttributeDecoder.h"
-#include "attribute/resolver/AttributeExtractor.h"
-
-#define BOOST_BIND_GLOBAL_PLACEHOLDERS
-#include <boost/bind.hpp>
-#include <boost/shared_ptr.hpp>
-#include <boost/iterator/indirect_iterator.hpp>
-#include <boost/tuple/tuple.hpp>
-#include <saml/saml2/metadata/Metadata.h>
-#include <xmltooling/util/XMLHelper.h>
-#include <xercesc/util/XMLStringTokenizer.hpp>
-#include <xercesc/util/XMLUniDefs.hpp>
-
-using namespace shibsp;
-using namespace opensaml::saml2md;
-using namespace opensaml;
-using namespace xmltooling;
-using namespace boost;
-using namespace std;
-
-namespace shibsp {
-
-#if defined (_MSC_VER)
- #pragma warning( push )
- #pragma warning( disable : 4250 )
-#endif
-
- class MetadataExtractor : public AttributeExtractor
- {
- public:
- MetadataExtractor(const DOMElement* e, bool deprecationSupport=true);
- ~MetadataExtractor() {}
-
- Lockable* lock() {
- return this;
- }
-
- void unlock() {
- }
-
- void extractAttributes(
- const Application& application,
- const GenericRequest* request,
- const RoleDescriptor* issuer,
- const XMLObject& xmlObject,
- vector<shibsp::Attribute*>& attributes
- ) const;
- void getAttributeIds(vector<string>& attributes) const;
-
- private:
- string m_attributeProfiles,
- m_errorURL,
- m_displayName,
- m_description,
- m_informationURL,
- m_privacyURL,
- m_orgName,
- m_orgDisplayName,
- m_orgURL,
- m_registrationAuthority;
- typedef boost::tuple< string,xstring,boost::shared_ptr<AttributeDecoder> > contact_tuple_t;
- typedef boost::tuple< string,int,int,boost::shared_ptr<AttributeDecoder> > logo_tuple_t;
- vector<contact_tuple_t> m_contacts; // tuple is attributeID, contact type, decoder
- vector<logo_tuple_t> m_logos; // tuple is attributeID, height, width, decoder
-
- template <class T> void doLangSensitive(const GenericRequest*, const vector<T*>&, const string&, vector<shibsp::Attribute*>&) const;
- void doContactPerson(const GenericRequest* request, const RoleDescriptor*, const contact_tuple_t&, vector<shibsp::Attribute*>&) const;
- void doLogo(const GenericRequest*, const vector<Logo*>&,const logo_tuple_t&, vector<shibsp::Attribute*>&) const;
- };
-
-#if defined (_MSC_VER)
- #pragma warning( pop )
-#endif
-
- AttributeExtractor* SHIBSP_DLLLOCAL MetadataAttributeExtractorFactory(const DOMElement* const & e, bool deprecationSupport)
- {
- return new MetadataExtractor(e, deprecationSupport);
- }
-
- static const XMLCh _id[] = UNICODE_LITERAL_2(i,d);
- static const XMLCh _formatter[] = UNICODE_LITERAL_9(f,o,r,m,a,t,t,e,r);
-};
-
-MetadataExtractor::MetadataExtractor(const DOMElement* e, bool deprecationSupport)
- : m_attributeProfiles(XMLHelper::getAttrString(e, nullptr, AttributeProfile::LOCAL_NAME)),
- m_errorURL(XMLHelper::getAttrString(e, nullptr, RoleDescriptor::ERRORURL_ATTRIB_NAME)),
- m_displayName(XMLHelper::getAttrString(e, nullptr, DisplayName::LOCAL_NAME)),
- m_description(XMLHelper::getAttrString(e, nullptr, Description::LOCAL_NAME)),
- m_informationURL(XMLHelper::getAttrString(e, nullptr, InformationURL::LOCAL_NAME)),
- m_privacyURL(XMLHelper::getAttrString(e, nullptr, PrivacyStatementURL::LOCAL_NAME)),
- m_orgName(XMLHelper::getAttrString(e, nullptr, OrganizationName::LOCAL_NAME)),
- m_orgDisplayName(XMLHelper::getAttrString(e, nullptr, OrganizationDisplayName::LOCAL_NAME)),
- m_orgURL(XMLHelper::getAttrString(e, nullptr, OrganizationURL::LOCAL_NAME)),
- m_registrationAuthority(XMLHelper::getAttrString(e, nullptr, RegistrationInfo::REGAUTHORITY_ATTRIB_NAME))
-{
- const DOMElement* child = e ? XMLHelper::getFirstChildElement(e) : nullptr;
- while (child) {
- if (XMLHelper::isNodeNamed(child, e->getNamespaceURI(), ContactPerson::LOCAL_NAME)) {
- string id(XMLHelper::getAttrString(child, nullptr, _id));
- const XMLCh* type = child->getAttributeNS(nullptr, ContactPerson::CONTACTTYPE_ATTRIB_NAME);
- if (!id.empty() && type && *type) {
- boost::shared_ptr<AttributeDecoder> decoder(SPConfig::getConfig().AttributeDecoderManager.newPlugin(DOMAttributeDecoderType, child, deprecationSupport));
- m_contacts.push_back(contact_tuple_t(id, type, decoder));
- }
- }
- else if (XMLHelper::isNodeNamed(child, e->getNamespaceURI(), Logo::LOCAL_NAME)) {
- string id(XMLHelper::getAttrString(child, nullptr, _id));
- int h(XMLHelper::getAttrInt(child, 0, Logo::HEIGHT_ATTRIB_NAME));
- int w(XMLHelper::getAttrInt(child, 0, Logo::WIDTH_ATTRIB_NAME));
- if (!id.empty()) {
- boost::shared_ptr<AttributeDecoder> decoder(SPConfig::getConfig().AttributeDecoderManager.newPlugin(DOMAttributeDecoderType, child, deprecationSupport));
- m_logos.push_back(logo_tuple_t(id, h, w, decoder));
- }
- }
- child = XMLHelper::getNextSiblingElement(child);
- }
-}
-
-void MetadataExtractor::getAttributeIds(vector<string>& attributes) const
-{
- if (!m_attributeProfiles.empty())
- attributes.push_back(m_attributeProfiles);
- if (!m_errorURL.empty())
- attributes.push_back(m_errorURL);
- if (!m_displayName.empty())
- attributes.push_back(m_displayName);
- if (!m_description.empty())
- attributes.push_back(m_description);
- if (!m_informationURL.empty())
- attributes.push_back(m_informationURL);
- if (!m_privacyURL.empty())
- attributes.push_back(m_privacyURL);
- if (!m_orgName.empty())
- attributes.push_back(m_orgName);
- if (!m_orgDisplayName.empty())
- attributes.push_back(m_orgDisplayName);
- if (!m_orgURL.empty())
- attributes.push_back(m_orgURL);
- if (!m_registrationAuthority.empty())
- attributes.push_back(m_registrationAuthority);
- for (vector<contact_tuple_t>::const_iterator c = m_contacts.begin(); c != m_contacts.end(); ++c)
- attributes.push_back(c->get<0>());
- for (vector<logo_tuple_t>::const_iterator l = m_logos.begin(); l != m_logos.end(); ++l)
- attributes.push_back(l->get<0>());
-}
-
-void MetadataExtractor::extractAttributes(
- const Application& application,
- const GenericRequest* request,
- const RoleDescriptor* issuer,
- const XMLObject& xmlObject,
- vector<shibsp::Attribute*>& attributes
- ) const
-{
- const RoleDescriptor* roleToExtract = dynamic_cast<const RoleDescriptor*>(&xmlObject);
- if (!roleToExtract)
- return;
-
- if (!m_attributeProfiles.empty()) {
- const vector<AttributeProfile*>* profiles = nullptr;
- const IDPSSODescriptor* idpRole = dynamic_cast<const IDPSSODescriptor*>(roleToExtract);
- if (idpRole) {
- profiles = &(idpRole->getAttributeProfiles());
- }
- else {
- const AttributeAuthorityDescriptor* aaRole = dynamic_cast<const AttributeAuthorityDescriptor*>(roleToExtract);
- if (aaRole) {
- profiles = &(aaRole->getAttributeProfiles());
- }
- }
- if (profiles && !profiles->empty()) {
- auto_ptr<SimpleAttribute> attr(new SimpleAttribute(vector<string>(1, m_attributeProfiles)));
- for (indirect_iterator<vector<AttributeProfile*>::const_iterator> i = make_indirect_iterator(profiles->begin());
- i != make_indirect_iterator(profiles->end()); ++i) {
- auto_ptr_char temp(i->getProfileURI());
- if (temp.get())
- attr->getValues().push_back(temp.get());
- }
- if (attr->valueCount() > 0) {
- attributes.push_back(attr.get());
- attr.release();
- }
- }
- }
-
- if (!m_errorURL.empty() && roleToExtract->getErrorURL()) {
- auto_ptr_char temp(roleToExtract->getErrorURL());
- if (temp.get() && *temp.get()) {
- auto_ptr<SimpleAttribute> attr(new SimpleAttribute(vector<string>(1, m_errorURL)));
- attr->getValues().push_back(temp.get());
- attributes.push_back(attr.get());
- attr.release();
- }
- }
-
- if (!m_displayName.empty() || !m_description.empty() || !m_informationURL.empty() || !m_privacyURL.empty()) {
- const Extensions* exts = roleToExtract->getExtensions();
- if (exts) {
- const UIInfo* ui;
- for (vector<XMLObject*>::const_iterator ext = exts->getUnknownXMLObjects().begin(); ext != exts->getUnknownXMLObjects().end(); ++ext) {
- ui = dynamic_cast<const UIInfo*>(*ext);
- if (ui) {
- doLangSensitive(request, ui->getDisplayNames(), m_displayName, attributes);
- doLangSensitive(request, ui->getDescriptions(), m_description, attributes);
- doLangSensitive(request, ui->getInformationURLs(), m_informationURL, attributes);
- doLangSensitive(request, ui->getPrivacyStatementURLs(), m_privacyURL, attributes);
- const vector<Logo*>& logos = ui->getLogos();
- if (!logos.empty()) {
- for_each(
- m_logos.begin(), m_logos.end(),
- boost::bind(&MetadataExtractor::doLogo, this, request, boost::ref(logos), _1, boost::ref(attributes))
- );
- }
- break;
- }
- }
- }
- }
-
- if (!m_orgName.empty() || !m_orgDisplayName.empty() || !m_orgURL.empty()) {
- const Organization* org = roleToExtract->getOrganization();
- if (!org)
- org = dynamic_cast<EntityDescriptor*>(roleToExtract->getParent())->getOrganization();
- if (org) {
- doLangSensitive(request, org->getOrganizationNames(), m_orgName, attributes);
- doLangSensitive(request, org->getOrganizationDisplayNames(), m_orgDisplayName, attributes);
- doLangSensitive(request, org->getOrganizationURLs(), m_orgURL, attributes);
- }
- }
-
- for_each(
- m_contacts.begin(), m_contacts.end(),
- boost::bind(&MetadataExtractor::doContactPerson, this, request, roleToExtract, _1, boost::ref(attributes))
- );
-
- if (!m_registrationAuthority.empty()) {
- const Extensions* exts = dynamic_cast<EntityDescriptor*>(roleToExtract->getParent())->getExtensions();
- if (exts) {
- const RegistrationInfo* reginfo;
- for (vector<XMLObject*>::const_iterator ext = exts->getUnknownXMLObjects().begin(); ext != exts->getUnknownXMLObjects().end(); ++ext) {
- reginfo = dynamic_cast<const RegistrationInfo*>(*ext);
- if (reginfo) {
- auto_ptr_char temp(reginfo->getRegistrationAuthority());
- if (temp.get()) {
- auto_ptr<SimpleAttribute> attr(new SimpleAttribute(vector<string>(1, m_registrationAuthority)));
- attr->getValues().push_back(temp.get());
- attributes.push_back(attr.get());
- attr.release();
- }
- }
- }
- }
- }
-}
-
-template <class T> void MetadataExtractor::doLangSensitive(
- const GenericRequest* request, const vector<T*>& objects, const string& id, vector<shibsp::Attribute*>& attributes
- ) const
-{
- if (objects.empty() || id.empty())
- return;
-
- T* match = nullptr;
- if (request && request->startLangMatching()) {
- do {
- for (typename vector<T*>::const_iterator i = objects.begin(); !match && i != objects.end(); ++i) {
- if (request->matchLang((*i)->getLang()))
- match = *i;
- }
- } while (!match && request->continueLangMatching());
- }
- if (!match)
- match = objects.front();
-
- auto_arrayptr<char> temp(toUTF8(match->getTextContent()));
- if (temp.get() && *temp.get()) {
- auto_ptr<SimpleAttribute> attr(new SimpleAttribute(vector<string>(1, id)));
- attr->getValues().push_back(temp.get());
- attributes.push_back(attr.get());
- attr.release();
- }
-}
-
-void MetadataExtractor::doLogo(
- const GenericRequest* request, const vector<Logo*>& logos, const logo_tuple_t& params, vector<shibsp::Attribute*>& attributes
- ) const
-{
- if (logos.empty())
- return;
-
- pair<bool,int> dim;
- Logo* match = nullptr;
- int h = params.get<1>(), w = params.get<2>(), sizediff, bestdiff = INT_MAX;
- if (request && request->startLangMatching()) {
- do {
- for (vector<Logo*>::const_iterator i = logos.begin(); i != logos.end(); ++i) {
- if (!(*i)->getLang() || request->matchLang((*i)->getLang())) {
- sizediff = 0;
- if (h > 0) {
- dim = (*i)->getHeight();
- sizediff += abs(h - dim.second);
- }
- if (w > 0) {
- dim = (*i)->getWidth();
- sizediff += abs(w - dim.second);
- }
- if (sizediff < bestdiff) {
- match = *i;
- bestdiff = sizediff;
- }
- }
- if (match && bestdiff == 0)
- break;
- }
- if (match && bestdiff == 0)
- break;
- } while (request->continueLangMatching());
- }
- else if (h > 0 || w > 0) {
- for (vector<Logo*>::const_iterator i = logos.begin(); i != logos.end(); ++i) {
- sizediff = 0;
- if (h > 0) {
- dim = (*i)->getHeight();
- sizediff += abs(h - dim.second);
- }
- if (w > 0) {
- dim = (*i)->getWidth();
- sizediff += abs(w - dim.second);
- }
- if (sizediff < bestdiff) {
- match = *i;
- bestdiff = sizediff;
- }
- if (match && bestdiff == 0)
- break;
- }
- }
-
- if (!match)
- match = logos.front();
-
- if (!match->getDOM()) {
- match->marshall();
- }
- vector<string> ids(1, params.get<0>());
- auto_ptr<Attribute> attr(params.get<3>()->decode(request, ids, match));
- if (attr.get()) {
- attributes.push_back(attr.get());
- attr.release();
- }
-}
-
-void MetadataExtractor::doContactPerson(
- const GenericRequest* request, const RoleDescriptor* role, const contact_tuple_t& params, vector<shibsp::Attribute*>& attributes
- ) const
-{
- const XMLCh* ctype = params.get<1>().c_str();
- static bool (*eq)(const XMLCh*, const XMLCh*) = &XMLString::equals;
- const ContactPerson* cp = find_if(role->getContactPersons(),boost::bind(eq, ctype, boost::bind(&ContactPerson::getContactType, _1)));
- if (!cp) {
- cp = find_if(dynamic_cast<EntityDescriptor*>(role->getParent())->getContactPersons(),
- boost::bind(eq, ctype, boost::bind(&ContactPerson::getContactType, _1)));
- }
-
- if (cp) {
- if (!cp->getDOM()) {
- cp->marshall();
- }
- vector<string> ids(1, params.get<0>());
- auto_ptr<Attribute> attr(params.get<2>()->decode(request, ids, cp));
- if (attr.get()) {
- attributes.push_back(attr.get());
- attr.release();
- }
- }
-}
diff --git a/shibsp/attribute/resolver/impl/QueryAttributeResolver.cpp b/shibsp/attribute/resolver/impl/QueryAttributeResolver.cpp
deleted file mode 100644
index 9b6b7a94..00000000
--- a/shibsp/attribute/resolver/impl/QueryAttributeResolver.cpp
+++ /dev/null
@@ -1,764 +0,0 @@
-/**
- * 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.
- */
-
-/**
- * QueryAttributeResolver.cpp
- *
- * AttributeResolver based on SAML queries.
- */
-
-#include "internal.h"
-#include "Application.h"
-#include "ServiceProvider.h"
-#include "SessionCache.h"
-#include "attribute/SimpleAttribute.h"
-#include "attribute/filtering/AttributeFilter.h"
-#include "attribute/filtering/BasicFilteringContext.h"
-#include "attribute/resolver/AttributeExtractor.h"
-#include "attribute/resolver/AttributeResolver.h"
-#include "attribute/resolver/ResolutionContext.h"
-#include "binding/SOAPClient.h"
-#include "metadata/MetadataProviderCriteria.h"
-#include "security/SecurityPolicy.h"
-#include "security/SecurityPolicyProvider.h"
-#include "util/SPConstants.h"
-
-#include <boost/iterator/indirect_iterator.hpp>
-#include <boost/ptr_container/ptr_vector.hpp>
-#include <saml/exceptions.h>
-#include <saml/saml1/binding/SAML1SOAPClient.h>
-#include <saml/saml1/core/Assertions.h>
-#include <saml/saml1/core/Protocols.h>
-#include <saml/saml2/binding/SAML2SOAPClient.h>
-#include <saml/saml2/core/Protocols.h>
-#include <saml/saml2/metadata/Metadata.h>
-#include <saml/saml2/metadata/MetadataCredentialCriteria.h>
-#include <saml/saml2/metadata/MetadataProvider.h>
-#include <xmltooling/XMLToolingConfig.h>
-#include <xmltooling/util/NDC.h>
-#include <xmltooling/util/URLEncoder.h>
-#include <xmltooling/util/XMLHelper.h>
-#include <xercesc/util/XMLUniDefs.hpp>
-
-using namespace shibsp;
-using namespace opensaml::saml1;
-using namespace opensaml::saml1p;
-using namespace opensaml::saml2;
-using namespace opensaml::saml2p;
-using namespace opensaml::saml2md;
-using namespace opensaml;
-using namespace xmltooling;
-using namespace boost;
-using namespace std;
-
-namespace shibsp {
-
- class SHIBSP_DLLLOCAL QueryContext : public ResolutionContext
- {
- public:
- QueryContext(const Application& application, const Session& session)
- : m_query(true), m_app(application), m_request(nullptr), m_session(&session), m_metadata(nullptr), m_entity(nullptr), m_nameid(nullptr) {
- m_protocol = XMLString::transcode(session.getProtocol());
- m_class = XMLString::transcode(session.getAuthnContextClassRef());
- m_decl = XMLString::transcode(session.getAuthnContextDeclRef());
- }
-
- QueryContext(
- const Application& application,
- const GenericRequest* request,
- const EntityDescriptor* issuer,
- const XMLCh* protocol,
- const NameID* nameid=nullptr,
- const XMLCh* authncontext_class=nullptr,
- const XMLCh* authncontext_decl=nullptr,
- const vector<const opensaml::Assertion*>* tokens=nullptr
- ) : m_query(true), m_app(application), m_request(request), m_session(nullptr), m_metadata(nullptr), m_entity(issuer),
- m_protocol(protocol), m_nameid(nameid), m_class(authncontext_class), m_decl(authncontext_decl) {
-
- if (tokens) {
- for (vector<const opensaml::Assertion*>::const_iterator t = tokens->begin(); t!=tokens->end(); ++t) {
- const saml2::Assertion* token2 = dynamic_cast<const saml2::Assertion*>(*t);
- if (token2 && !token2->getAttributeStatements().empty()) {
- m_query = false;
- }
- else {
- const saml1::Assertion* token1 = dynamic_cast<const saml1::Assertion*>(*t);
- if (token1 && !token1->getAttributeStatements().empty()) {
- m_query = false;
- }
- }
- }
- }
- }
-
- ~QueryContext() {
- if (m_session) {
- XMLString::release((XMLCh**)&m_protocol);
- XMLString::release((XMLCh**)&m_class);
- XMLString::release((XMLCh**)&m_decl);
- }
- if (m_metadata)
- m_metadata->unlock();
- for_each(m_attributes.begin(), m_attributes.end(), xmltooling::cleanup<shibsp::Attribute>());
- for_each(m_assertions.begin(), m_assertions.end(), xmltooling::cleanup<opensaml::Assertion>());
- }
-
- bool doQuery() const {
- return m_query;
- }
-
- const Application& getApplication() const {
- return m_app;
- }
- const GenericRequest* getRequest() const {
- return m_request;
- }
- const EntityDescriptor* getEntityDescriptor() const {
- if (m_entity)
- return m_entity;
- if (m_session && m_session->getEntityID()) {
- m_metadata = m_app.getMetadataProvider(false);
- if (m_metadata) {
- m_metadata->lock();
- return m_entity = m_metadata->getEntityDescriptor(MetadataProviderCriteria(m_app, m_session->getEntityID())).first;
- }
- }
- return nullptr;
- }
- const XMLCh* getProtocol() const {
- return m_protocol;
- }
- const NameID* getNameID() const {
- return m_session ? m_session->getNameID() : m_nameid;
- }
- const XMLCh* getClassRef() const {
- return m_class;
- }
- const XMLCh* getDeclRef() const {
- return m_decl;
- }
- const Session* getSession() const {
- return m_session;
- }
- vector<shibsp::Attribute*>& getResolvedAttributes() {
- return m_attributes;
- }
- vector<opensaml::Assertion*>& getResolvedAssertions() {
- return m_assertions;
- }
-
- private:
- bool m_query;
- const Application& m_app;
- const GenericRequest* m_request;
- const Session* m_session;
- mutable MetadataProvider* m_metadata;
- mutable const EntityDescriptor* m_entity;
- const XMLCh* m_protocol;
- const NameID* m_nameid;
- const XMLCh* m_class;
- const XMLCh* m_decl;
- vector<shibsp::Attribute*> m_attributes;
- vector<opensaml::Assertion*> m_assertions;
- };
-
- class SHIBSP_DLLLOCAL QueryResolver : public AttributeResolver
- {
- public:
- QueryResolver(const DOMElement* e);
- ~QueryResolver() {}
-
- Lockable* lock() {return this;}
- void unlock() {}
-
- ResolutionContext* createResolutionContext(
- const Application& application,
- const GenericRequest* request,
- const EntityDescriptor* issuer,
- const XMLCh* protocol,
- const NameID* nameid=nullptr,
- const XMLCh* authncontext_class=nullptr,
- const XMLCh* authncontext_decl=nullptr,
- const vector<const opensaml::Assertion*>* tokens=nullptr,
- const vector<shibsp::Attribute*>* attributes=nullptr
- ) const {
- return new QueryContext(application, request, issuer, protocol, nameid, authncontext_class, authncontext_decl, tokens);
- }
-
- ResolutionContext* createResolutionContext(const Application& application, const Session& session) const {
- return new QueryContext(application,session);
- }
-
- void resolveAttributes(ResolutionContext& ctx) const;
-
- void getAttributeIds(vector<string>& attributes) const {
- if (!m_exceptionId.empty())
- attributes.push_back(m_exceptionId.front());
- }
-
- private:
- void SAML1Query(QueryContext& ctx, vector<string>& statusCodes) const;
- void SAML2Query(QueryContext& ctx, vector<string>& statusCodes) const;
-
- Category& m_log;
- string m_policyId;
- bool m_subjectMatch;
- ptr_vector<AttributeDesignator> m_SAML1Designators;
- ptr_vector<saml2::Attribute> m_SAML2Designators;
- vector<string> m_exceptionId;
- vector<string> m_statusId;
- };
-
- AttributeResolver* SHIBSP_DLLLOCAL QueryResolverFactory(const DOMElement* const & e, bool)
- {
- return new QueryResolver(e);
- }
-
- static const XMLCh exceptionId[] = UNICODE_LITERAL_11(e,x,c,e,p,t,i,o,n,I,d);
- static const XMLCh policyId[] = UNICODE_LITERAL_8(p,o,l,i,c,y,I,d);
- static const XMLCh statusId[] = UNICODE_LITERAL_8(s,t,a,t,u,s,I,d);
- static const XMLCh subjectMatch[] = UNICODE_LITERAL_12(s,u,b,j,e,c,t,M,a,t,c,h);
-};
-
-QueryResolver::QueryResolver(const DOMElement* e)
- : m_log(Category::getInstance(SHIBSP_LOGCAT ".AttributeResolver.Query")),
- m_policyId(XMLHelper::getAttrString(e, nullptr, policyId)),
- m_subjectMatch(XMLHelper::getAttrBool(e, false, subjectMatch))
-{
-#ifdef _DEBUG
- xmltooling::NDC ndc("QueryResolver");
-#endif
-
- DOMElement* child = XMLHelper::getFirstChildElement(e);
- while (child) {
- try {
- if (XMLHelper::isNodeNamed(child, samlconstants::SAML20_NS, saml2::Attribute::LOCAL_NAME)) {
- auto_ptr<XMLObject> obj(saml2::AttributeBuilder::buildOneFromElement(child));
- saml2::Attribute* down = dynamic_cast<saml2::Attribute*>(obj.get());
- if (down) {
- m_SAML2Designators.push_back(down);
- obj.release();
- }
- }
- else if (XMLHelper::isNodeNamed(child, samlconstants::SAML1_NS, AttributeDesignator::LOCAL_NAME)) {
- auto_ptr<XMLObject> obj(AttributeDesignatorBuilder::buildOneFromElement(child));
- AttributeDesignator* down = dynamic_cast<AttributeDesignator*>(obj.get());
- if (down) {
- m_SAML1Designators.push_back(down);
- obj.release();
- }
- }
- }
- catch (const exception& ex) {
- m_log.error("exception loading attribute designator: %s", ex.what());
- }
- child = XMLHelper::getNextSiblingElement(child);
- }
-
- string exid(XMLHelper::getAttrString(e, nullptr, exceptionId));
- if (!exid.empty())
- m_exceptionId.push_back(exid);
-
- string stid(XMLHelper::getAttrString(e, nullptr, statusId));
- if (!stid.empty())
- m_statusId.push_back(stid);
-}
-
-void QueryResolver::SAML1Query(QueryContext& ctx, vector<string>& statusCodes) const
-{
-#ifdef _DEBUG
- xmltooling::NDC ndc("query");
-#endif
-
- int version = XMLString::equals(ctx.getProtocol(), samlconstants::SAML11_PROTOCOL_ENUM) ? 1 : 0;
- const AttributeAuthorityDescriptor* AA =
- find_if(ctx.getEntityDescriptor()->getAttributeAuthorityDescriptors(), isValidForProtocol(ctx.getProtocol()));
- if (!AA) {
- m_log.warn("no SAML 1.%d AttributeAuthority role found in metadata", version);
- throw MetadataException("Unable to locate SAML 1 AttributeAuthority role.");
- }
-
- const Application& application = ctx.getApplication();
- const PropertySet* relyingParty = application.getRelyingParty(ctx.getEntityDescriptor());
-
- // Locate policy key.
- const char* policyId = m_policyId.empty() ? application.getString("policyId").second : m_policyId.c_str();
-
- // Set up policy and SOAP client.
- scoped_ptr<SecurityPolicy> policy(
- application.getServiceProvider().getSecurityPolicyProvider()->createSecurityPolicy(
- samlconstants::SAML1_BINDING_SOAP, application, nullptr, policyId
- )
- );
- policy->getAudiences().push_back(relyingParty->getXMLString("entityID").second);
- MetadataCredentialCriteria mcc(*AA);
- shibsp::SOAPClient soaper(*policy);
-
- auto_ptr_XMLCh binding(samlconstants::SAML1_BINDING_SOAP);
- auto_ptr<saml1p::Response> response;
- const vector<AttributeService*>& endpoints=AA->getAttributeServices();
- for (indirect_iterator<vector<AttributeService*>::const_iterator> ep = make_indirect_iterator(endpoints.begin());
- !response.get() && ep != make_indirect_iterator(endpoints.end()); ++ep) {
- if (!XMLString::equals(ep->getBinding(), binding.get()) || !ep->getLocation())
- continue;
- auto_ptr_char loc(ep->getLocation());
- try {
- NameIdentifier* nameid = NameIdentifierBuilder::buildNameIdentifier();
- nameid->setName(ctx.getNameID()->getName());
- nameid->setFormat(ctx.getNameID()->getFormat());
- nameid->setNameQualifier(ctx.getNameID()->getNameQualifier());
- saml1::Subject* subject = saml1::SubjectBuilder::buildSubject();
- subject->setNameIdentifier(nameid);
- saml1p::AttributeQuery* query = saml1p::AttributeQueryBuilder::buildAttributeQuery();
- query->setSubject(subject);
- query->setResource(relyingParty->getXMLString("entityID").second);
- for (ptr_vector<AttributeDesignator>::const_iterator ad = m_SAML1Designators.begin(); ad != m_SAML1Designators.end(); ++ad) {
- auto_ptr<AttributeDesignator> adwrapper(ad->cloneAttributeDesignator());
- query->getAttributeDesignators().push_back(adwrapper.get());
- adwrapper.release();
- }
- Request* request = RequestBuilder::buildRequest();
- request->setAttributeQuery(query);
- request->setMinorVersion(version);
-
- SAML1SOAPClient client(soaper, false);
- client.sendSAML(request, application.getId(), mcc, loc.get());
- response.reset(client.receiveSAML());
- }
- catch (const exception& ex) {
- m_log.error("exception during SAML query to %s: %s", loc.get(), ex.what());
- soaper.reset();
- }
- }
-
- if (!response.get()) {
- m_log.error("unable to obtain a SAML response from attribute authority");
- throw BindingException("Unable to obtain a SAML response from attribute authority.");
- }
- else if (!response->getStatus() || !response->getStatus()->getStatusCode() || response->getStatus()->getStatusCode()->getValue()==nullptr ||
- *(response->getStatus()->getStatusCode()->getValue()) != saml1p::StatusCode::SUCCESS) {
- m_log.error("attribute authority returned a SAML error");
- const saml1p::StatusCode* statusCode = response->getStatus() ? response->getStatus()->getStatusCode() : nullptr;
- while (statusCode && statusCode->getValue() && statusCode->getValue()->hasLocalPart()) {
- auto_ptr_char code(statusCode->getValue()->getLocalPart());
- if (code.get())
- statusCodes.push_back(code.get());
- statusCode = statusCode->getStatusCode();
- }
- throw FatalProfileException("Attribute authority returned a SAML error.");
- }
-
- const vector<saml1::Assertion*>& assertions = const_cast<const saml1p::Response*>(response.get())->getAssertions();
- if (assertions.empty()) {
- m_log.warn("response from attribute authority was empty");
- return;
- }
- else if (assertions.size() > 1) {
- m_log.warn("simple resolver only supports one assertion in the query response");
- }
-
- saml1::Assertion* newtoken = assertions.front();
-
- pair<bool,bool> signedAssertions = relyingParty->getBool("requireSignedAssertions");
- if (!newtoken->getSignature() && signedAssertions.first && signedAssertions.second) {
- m_log.error("assertion unsigned, rejecting it based on signedAssertions policy");
- throw SecurityPolicyException("Rejected unsigned assertion based on local policy.");
- }
-
- try {
- // We're going to insist that the assertion issuer is the same as the peer.
- // Reset the policy's message bits and extract them from the assertion.
- policy->reset(true);
- policy->setMessageID(newtoken->getAssertionID());
- policy->setIssueInstant(newtoken->getIssueInstantEpoch());
- policy->setIssuer(newtoken->getIssuer());
- policy->evaluate(*newtoken);
-
- // Now we can check the security status of the policy.
- if (!policy->isAuthenticated())
- throw SecurityPolicyException("Security of SAML 1.x query result not established.");
- }
- catch (const exception& ex) {
- m_log.error("assertion failed policy validation: %s", ex.what());
- throw;
- }
-
- newtoken->detach();
- response.release(); // detach blows away the Response
- ctx.getResolvedAssertions().push_back(newtoken);
-
- // Finally, extract and filter the result.
- try {
- AttributeExtractor* extractor = application.getAttributeExtractor();
- if (extractor) {
- Locker extlocker(extractor);
- const vector<saml1::AttributeStatement*>& statements = const_cast<const saml1::Assertion*>(newtoken)->getAttributeStatements();
- for (indirect_iterator<vector<saml1::AttributeStatement*>::const_iterator> s = make_indirect_iterator(statements.begin());
- s != make_indirect_iterator(statements.end()); ++s) {
- if (m_subjectMatch) {
- // Check for subject match.
- const NameIdentifier* respName = s->getSubject() ? s->getSubject()->getNameIdentifier() : nullptr;
- if (!respName || !XMLString::equals(respName->getName(), ctx.getNameID()->getName()) ||
- !XMLString::equals(respName->getFormat(), ctx.getNameID()->getFormat()) ||
- !XMLString::equals(respName->getNameQualifier(), ctx.getNameID()->getNameQualifier())) {
- if (respName)
- m_log.warnStream() << "ignoring AttributeStatement without strongly matching NameIdentifier in Subject: " <<
- *respName << logging::eol;
- else
- m_log.warn("ignoring AttributeStatement without NameIdentifier in Subject");
- continue;
- }
- }
- extractor->extractAttributes(application, ctx.getRequest(), AA, *s, ctx.getResolvedAttributes());
- }
- }
-
- AttributeFilter* filter = application.getAttributeFilter();
- if (filter) {
- BasicFilteringContext fc(application, ctx.getResolvedAttributes(), AA, ctx.getClassRef(), ctx.getDeclRef());
- Locker filtlocker(filter);
- filter->filterAttributes(fc, ctx.getResolvedAttributes());
- }
- }
- catch (const exception& ex) {
- m_log.error("caught exception extracting/filtering attributes from query result: %s", ex.what());
- for_each(ctx.getResolvedAttributes().begin(), ctx.getResolvedAttributes().end(), xmltooling::cleanup<shibsp::Attribute>());
- ctx.getResolvedAttributes().clear();
- throw;
- }
-}
-
-void QueryResolver::SAML2Query(QueryContext& ctx, vector<string>& statusCodes) const
-{
-#ifdef _DEBUG
- xmltooling::NDC ndc("query");
-#endif
-
- const AttributeAuthorityDescriptor* AA =
- find_if(ctx.getEntityDescriptor()->getAttributeAuthorityDescriptors(), isValidForProtocol(samlconstants::SAML20P_NS));
- if (!AA) {
- m_log.warn("no SAML 2 AttributeAuthority role found in metadata");
- throw MetadataException("Unable to locate SAML 2.0 AttributeAuthority role.");
- }
-
- const Application& application = ctx.getApplication();
- const PropertySet* relyingParty = application.getRelyingParty(ctx.getEntityDescriptor());
- pair<bool,bool> signedAssertions = relyingParty->getBool("requireSignedAssertions");
- pair<bool,const char*> encryption = relyingParty->getString("encryption");
-
- // Locate policy key.
- const char* policyId = m_policyId.empty() ? application.getString("policyId").second : m_policyId.c_str();
-
- // Set up policy and SOAP client.
- scoped_ptr<SecurityPolicy> policy(
- application.getServiceProvider().getSecurityPolicyProvider()->createSecurityPolicy(
- samlconstants::SAML20_PROFILE_QUERY, application, nullptr, policyId
- )
- );
- policy->getAudiences().push_back(relyingParty->getXMLString("entityID").second);
- MetadataCredentialCriteria mcc(*AA);
- shibsp::SOAPClient soaper(*policy);
-
- auto_ptr_XMLCh binding(samlconstants::SAML20_BINDING_SOAP);
- auto_ptr<saml2p::StatusResponseType> srt;
- const vector<AttributeService*>& endpoints=AA->getAttributeServices();
- for (indirect_iterator<vector<AttributeService*>::const_iterator> ep = make_indirect_iterator(endpoints.begin());
- !srt.get() && ep != make_indirect_iterator(endpoints.end()); ++ep) {
- if (!XMLString::equals(ep->getBinding(), binding.get()) || !ep->getLocation())
- continue;
- auto_ptr_char loc(ep->getLocation());
- try {
- auto_ptr<saml2::Subject> subject(saml2::SubjectBuilder::buildSubject());
-
- // Encrypt the NameID?
- if (SPConfig::shouldSignOrEncrypt(encryption.first ? encryption.second : "conditional", loc.get(), false)) {
- try {
- auto_ptr<EncryptedID> encrypted(EncryptedIDBuilder::buildEncryptedID());
- encrypted->encrypt(
- *ctx.getNameID(),
- *(application.getMetadataProvider()),
- mcc,
- false,
- relyingParty->getXMLString("encryptionAlg").second
- );
- subject->setEncryptedID(encrypted.get());
- encrypted.release();
- }
- catch (const std::exception& ex) {
- // If we're encrypting deliberately, failure should be fatal.
- if (encryption.first && strcmp(encryption.second, "conditional")) {
- throw;
- }
- // If opportunistically, just log and move on.
- m_log.info("Conditional encryption of NameID in AttributeQuery failed: %s", ex.what());
- auto_ptr<NameID> namewrapper(ctx.getNameID()->cloneNameID());
- subject->setNameID(namewrapper.get());
- namewrapper.release();
- }
- }
- else {
- auto_ptr<NameID> namewrapper(ctx.getNameID()->cloneNameID());
- subject->setNameID(namewrapper.get());
- namewrapper.release();
- }
-
- saml2p::AttributeQuery* query = saml2p::AttributeQueryBuilder::buildAttributeQuery();
- query->setSubject(subject.release());
- Issuer* iss = IssuerBuilder::buildIssuer();
- iss->setName(relyingParty->getXMLString("entityID").second);
- query->setIssuer(iss);
- for (ptr_vector<saml2::Attribute>::const_iterator ad = m_SAML2Designators.begin(); ad != m_SAML2Designators.end(); ++ad) {
- auto_ptr<saml2::Attribute> adwrapper(ad->cloneAttribute());
- query->getAttributes().push_back(adwrapper.get());
- adwrapper.release();
- }
-
- SAML2SOAPClient client(soaper, false);
- client.sendSAML(query, application.getId(), mcc, loc.get());
- srt.reset(client.receiveSAML());
- }
- catch (const exception& ex) {
- m_log.error("exception during SAML query to %s: %s", loc.get(), ex.what());
- soaper.reset();
- }
- }
-
- if (!srt.get()) {
- m_log.error("unable to obtain a SAML response from attribute authority");
- throw BindingException("Unable to obtain a SAML response from attribute authority.");
- }
-
- saml2p::Response* response = dynamic_cast<saml2p::Response*>(srt.get());
- if (!response) {
- m_log.error("message was not a samlp:Response");
- throw FatalProfileException("Attribute authority returned an unrecognized message.");
- }
- else if (!response->getStatus() || !response->getStatus()->getStatusCode() ||
- !XMLString::equals(response->getStatus()->getStatusCode()->getValue(), saml2p::StatusCode::SUCCESS)) {
- m_log.error("attribute authority returned a SAML error");
- const saml2p::StatusCode* statusCode = response->getStatus() ? response->getStatus()->getStatusCode() : nullptr;
- while (statusCode) {
- auto_ptr_char code(statusCode->getValue());
- if (code.get())
- statusCodes.push_back(code.get());
- statusCode = statusCode->getStatusCode();
- }
- throw FatalProfileException("Attribute authority returned a SAML error.");
- }
-
- saml2::Assertion* newtoken = nullptr;
- auto_ptr<saml2::Assertion> newtokenwrapper;
- const vector<saml2::Assertion*>& assertions = const_cast<const saml2p::Response*>(response)->getAssertions();
- if (assertions.empty()) {
- // Check for encryption.
- const vector<saml2::EncryptedAssertion*>& encassertions = const_cast<const saml2p::Response*>(response)->getEncryptedAssertions();
- if (encassertions.empty()) {
- m_log.warn("response from attribute authority was empty");
- return;
- }
- else if (encassertions.size() > 1) {
- m_log.warn("simple resolver only supports one assertion in the query response");
- }
-
- CredentialResolver* cr = application.getCredentialResolver();
- if (!cr) {
- m_log.warn("found encrypted assertion, but no CredentialResolver was available");
- throw FatalProfileException("Assertion was encrypted, but no decryption credentials are available.");
- }
-
- // With this flag on, we block unauthenticated ciphertext when decrypting,
- // unless the protocol was authenticated.
- pair<bool,bool> authenticatedCipher = application.getBool("requireAuthenticatedEncryption");
- if (policy->isAuthenticated())
- authenticatedCipher.second = false;
-
- // Attempt to decrypt it.
- try {
- Locker credlocker(cr);
- auto_ptr<XMLObject> tokenwrapper(
- encassertions.front()->decrypt(
- *cr, relyingParty->getXMLString("entityID").second, &mcc, authenticatedCipher.first && authenticatedCipher.second
- )
- );
- newtoken = dynamic_cast<saml2::Assertion*>(tokenwrapper.get());
- if (newtoken) {
- tokenwrapper.release();
- newtokenwrapper.reset(newtoken);
- if (m_log.isDebugEnabled())
- m_log.debugStream() << "decrypted assertion: " << *newtoken << logging::eol;
- }
- }
- catch (const exception& ex) {
- m_log.error("failed to decrypt assertion: %s", ex.what());
- throw;
- }
- }
- else {
- if (assertions.size() > 1)
- m_log.warn("simple resolver only supports one assertion in the query response");
- newtoken = assertions.front();
- }
-
- if (!newtoken->getSignature() && signedAssertions.first && signedAssertions.second) {
- m_log.error("assertion unsigned, rejecting it based on signedAssertions policy");
- throw SecurityPolicyException("Rejected unsigned assertion based on local policy.");
- }
-
- try {
- // We're going to insist that the assertion issuer is the same as the peer.
- // Reset the policy's message bits and extract them from the assertion.
- policy->reset(true);
- policy->setMessageID(newtoken->getID());
- policy->setIssueInstant(newtoken->getIssueInstantEpoch());
- policy->setIssuer(newtoken->getIssuer());
- policy->evaluate(*newtoken);
-
- // Now we can check the security status of the policy.
- if (!policy->isAuthenticated())
- throw SecurityPolicyException("Security of SAML 2.0 query result not established.");
-
- if (m_subjectMatch) {
- // Check for subject match.
- auto_ptr<NameID> nameIDwrapper;
- NameID* respName = newtoken->getSubject() ? newtoken->getSubject()->getNameID() : nullptr;
- if (!respName) {
- // Check for encryption.
- EncryptedID* encname = newtoken->getSubject() ? newtoken->getSubject()->getEncryptedID() : nullptr;
- if (encname) {
- CredentialResolver* cr=application.getCredentialResolver();
- if (!cr)
- m_log.warn("found EncryptedID, but no CredentialResolver was available");
- else {
- Locker credlocker(cr);
- auto_ptr<XMLObject> decryptedID(encname->decrypt(*cr, relyingParty->getXMLString("entityID").second, &mcc));
- respName = dynamic_cast<NameID*>(decryptedID.get());
- if (respName) {
- decryptedID.release();
- nameIDwrapper.reset(respName);
- if (m_log.isDebugEnabled())
- m_log.debugStream() << "decrypted NameID: " << *respName << logging::eol;
- }
- }
- }
- }
-
- if (!respName || !XMLString::equals(respName->getName(), ctx.getNameID()->getName()) ||
- !XMLString::equals(respName->getFormat(), ctx.getNameID()->getFormat()) ||
- !XMLString::equals(respName->getNameQualifier(), ctx.getNameID()->getNameQualifier()) ||
- !XMLString::equals(respName->getSPNameQualifier(), ctx.getNameID()->getSPNameQualifier())) {
- if (respName)
- m_log.warnStream() << "ignoring Assertion without strongly matching NameID in Subject: " <<
- *respName << logging::eol;
- else
- m_log.warn("ignoring Assertion without NameID in Subject");
- return;
- }
- }
- }
- catch (const exception& ex) {
- m_log.error("assertion failed policy validation: %s", ex.what());
- throw;
- }
-
- // If the token's embedded, detach it.
- if (!newtokenwrapper.get()) {
- newtoken->detach();
- srt.release(); // detach blows away the Response, so avoid a double free
- newtokenwrapper.reset(newtoken);
- }
- ctx.getResolvedAssertions().push_back(newtoken);
- newtokenwrapper.release();
-
- // Finally, extract and filter the result.
- try {
- AttributeExtractor* extractor = application.getAttributeExtractor();
- if (extractor) {
- Locker extlocker(extractor);
- extractor->extractAttributes(application, ctx.getRequest(), AA, *newtoken, ctx.getResolvedAttributes());
- }
-
- AttributeFilter* filter = application.getAttributeFilter();
- if (filter) {
- BasicFilteringContext fc(application, ctx.getResolvedAttributes(), AA, ctx.getClassRef(), ctx.getDeclRef());
- Locker filtlocker(filter);
- filter->filterAttributes(fc, ctx.getResolvedAttributes());
- }
- }
- catch (const exception& ex) {
- m_log.error("caught exception extracting/filtering attributes from query result: %s", ex.what());
- for_each(ctx.getResolvedAttributes().begin(), ctx.getResolvedAttributes().end(), xmltooling::cleanup<shibsp::Attribute>());
- ctx.getResolvedAttributes().clear();
- throw;
- }
-}
-
-void QueryResolver::resolveAttributes(ResolutionContext& ctx) const
-{
-#ifdef _DEBUG
- xmltooling::NDC ndc("resolveAttributes");
-#endif
-
- QueryContext& qctx = dynamic_cast<QueryContext&>(ctx);
- if (!qctx.doQuery()) {
- m_log.debug("found AttributeStatement in input to new session, skipping query");
- return;
- }
-
- vector<string> statusCodes;
-
- try {
- if (qctx.getNameID() && qctx.getEntityDescriptor()) {
- if (XMLString::equals(qctx.getProtocol(), samlconstants::SAML20P_NS)) {
- m_log.debug("attempting SAML 2.0 attribute query");
- SAML2Query(qctx, statusCodes);
- }
- else if (XMLString::equals(qctx.getProtocol(), samlconstants::SAML11_PROTOCOL_ENUM) ||
- XMLString::equals(qctx.getProtocol(), samlconstants::SAML10_PROTOCOL_ENUM)) {
- m_log.debug("attempting SAML 1.x attribute query");
- SAML1Query(qctx, statusCodes);
- }
- else {
- m_log.info("SSO protocol does not allow for attribute query");
- }
- }
- else {
- m_log.warn("can't attempt attribute query, either no NameID or no metadata to use");
- }
- }
- catch (const exception& ex) {
- // Already logged.
- if (!m_exceptionId.empty()) {
- auto_ptr<SimpleAttribute> attr(new SimpleAttribute(m_exceptionId));
- attr->getValues().push_back(XMLToolingConfig::getConfig().getURLEncoder()->encode(ex.what()));
- qctx.getResolvedAttributes().push_back(attr.get());
- attr.release();
-
- if (!m_statusId.empty() && !statusCodes.empty()) {
- auto_ptr<SimpleAttribute> attr(new SimpleAttribute(m_statusId));
- attr->getValues().assign(statusCodes.begin(), statusCodes.end());
- qctx.getResolvedAttributes().push_back(attr.get());
- attr.release();
- }
- }
- else {
- throw; // not exposing the exception as an attribute, so just surface to caller
- }
- }
-}
diff --git a/shibsp/attribute/resolver/impl/SimpleAggregationAttributeResolver.cpp b/shibsp/attribute/resolver/impl/SimpleAggregationAttributeResolver.cpp
deleted file mode 100644
index 6d0b12d3..00000000
--- a/shibsp/attribute/resolver/impl/SimpleAggregationAttributeResolver.cpp
+++ /dev/null
@@ -1,765 +0,0 @@
-/**
- * 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.
- */
-
-/**
- * SimpleAggregationAttributeResolver.cpp
- *
- * AttributeResolver based on SAML queries to third-party AA sources.
- */
-
-#include "internal.h"
-#include "exceptions.h"
-#include "Application.h"
-#include "ServiceProvider.h"
-#include "SessionCache.h"
-#include "attribute/NameIDAttribute.h"
-#include "attribute/SimpleAttribute.h"
-#include "attribute/filtering/AttributeFilter.h"
-#include "attribute/filtering/BasicFilteringContext.h"
-#include "attribute/resolver/AttributeExtractor.h"
-#include "attribute/resolver/AttributeResolver.h"
-#include "attribute/resolver/ResolutionContext.h"
-#include "binding/SOAPClient.h"
-#include "metadata/MetadataProviderCriteria.h"
-#include "security/SecurityPolicy.h"
-#include "security/SecurityPolicyProvider.h"
-#include "util/SPConstants.h"
-
-#include <boost/algorithm/string.hpp>
-#include <boost/iterator/indirect_iterator.hpp>
-#include <boost/ptr_container/ptr_vector.hpp>
-#include <saml/exceptions.h>
-#include <saml/SAMLConfig.h>
-#include <saml/saml2/binding/SAML2SOAPClient.h>
-#include <saml/saml2/core/Protocols.h>
-#include <saml/saml2/metadata/Metadata.h>
-#include <saml/saml2/metadata/MetadataCredentialCriteria.h>
-#include <saml/saml2/metadata/MetadataProvider.h>
-#include <xmltooling/XMLToolingConfig.h>
-#include <xmltooling/security/TrustEngine.h>
-#include <xmltooling/util/NDC.h>
-#include <xmltooling/util/URLEncoder.h>
-#include <xmltooling/util/XMLHelper.h>
-#include <xercesc/util/XMLUniDefs.hpp>
-
-using namespace shibsp;
-using namespace opensaml::saml2;
-using namespace opensaml::saml2p;
-using namespace opensaml::saml2md;
-using namespace opensaml;
-using namespace xmltooling;
-using namespace boost;
-using namespace std;
-
-namespace shibsp {
-
- class SHIBSP_DLLLOCAL SimpleAggregationContext : public ResolutionContext
- {
- public:
- SimpleAggregationContext(const Application& application, const Session& session)
- : m_app(application),
- m_request(nullptr),
- m_session(&session),
- m_nameid(nullptr),
- m_class(session.getAuthnContextClassRef()),
- m_decl(session.getAuthnContextDeclRef()),
- m_inputTokens(nullptr),
- m_inputAttributes(nullptr) {
- }
-
- SimpleAggregationContext(
- const Application& application,
- const GenericRequest* request=nullptr,
- const NameID* nameid=nullptr,
- const XMLCh* entityID=nullptr,
- const XMLCh* authncontext_class=nullptr,
- const XMLCh* authncontext_decl=nullptr,
- const vector<const opensaml::Assertion*>* tokens=nullptr,
- const vector<shibsp::Attribute*>* attributes=nullptr
- ) : m_app(application),
- m_request(request),
- m_session(nullptr),
- m_nameid(nameid),
- m_entityid(entityID),
- m_class(authncontext_class),
- m_decl(authncontext_decl),
- m_inputTokens(tokens),
- m_inputAttributes(attributes) {
- }
-
- ~SimpleAggregationContext() {
- for_each(m_attributes.begin(), m_attributes.end(), xmltooling::cleanup<shibsp::Attribute>());
- for_each(m_assertions.begin(), m_assertions.end(), xmltooling::cleanup<opensaml::Assertion>());
- }
-
- const Application& getApplication() const {
- return m_app;
- }
- const GenericRequest* getRequest() const {
- return m_request;
- }
- const char* getEntityID() const {
- return m_session ? m_session->getEntityID() : m_entityid.get();
- }
- const NameID* getNameID() const {
- return m_session ? m_session->getNameID() : m_nameid;
- }
- const XMLCh* getClassRef() const {
- return m_class.get();
- }
- const XMLCh* getDeclRef() const {
- return m_decl.get();
- }
- const Session* getSession() const {
- return m_session;
- }
- const vector<shibsp::Attribute*>* getInputAttributes() const {
- return m_inputAttributes;
- }
- const vector<const opensaml::Assertion*>* getInputTokens() const {
- return m_inputTokens;
- }
- vector<shibsp::Attribute*>& getResolvedAttributes() {
- return m_attributes;
- }
- vector<opensaml::Assertion*>& getResolvedAssertions() {
- return m_assertions;
- }
-
- private:
- const Application& m_app;
- const GenericRequest* m_request;
- const Session* m_session;
- const NameID* m_nameid;
- auto_ptr_char m_entityid;
- auto_ptr_XMLCh m_class;
- auto_ptr_XMLCh m_decl;
- const vector<const opensaml::Assertion*>* m_inputTokens;
- const vector<shibsp::Attribute*>* m_inputAttributes;
- vector<shibsp::Attribute*> m_attributes;
- vector<opensaml::Assertion*> m_assertions;
- };
-
- class SHIBSP_DLLLOCAL SimpleAggregationResolver : public AttributeResolver
- {
- public:
- SimpleAggregationResolver(const DOMElement* e, bool deprecationSupport=true);
- ~SimpleAggregationResolver() {}
-
- Lockable* lock() {return this;}
- void unlock() {}
-
- ResolutionContext* createResolutionContext(
- const Application& application,
- const GenericRequest* request,
- const EntityDescriptor* issuer,
- const XMLCh* protocol,
- const NameID* nameid=nullptr,
- const XMLCh* authncontext_class=nullptr,
- const XMLCh* authncontext_decl=nullptr,
- const vector<const opensaml::Assertion*>* tokens=nullptr,
- const vector<shibsp::Attribute*>* attributes=nullptr
- ) const {
- return new SimpleAggregationContext(
- application, request, nameid, (issuer ? issuer->getEntityID() : nullptr), authncontext_class, authncontext_decl, tokens, attributes
- );
- }
-
- ResolutionContext* createResolutionContext(const Application& application, const Session& session) const {
- return new SimpleAggregationContext(application,session);
- }
-
- void resolveAttributes(ResolutionContext& ctx) const;
-
- void getAttributeIds(vector<string>& attributes) const {
- if (m_extractor)
- m_extractor->getAttributeIds(attributes);
- if (!m_exceptionId.empty())
- attributes.push_back(m_exceptionId.front());
- }
-
- private:
- void doQuery(SimpleAggregationContext& ctx, const char* entityID, const NameID* name) const;
-
- Category& m_log;
- string m_policyId;
- bool m_subjectMatch;
- vector<string> m_attributeIds;
- xstring m_format;
- scoped_ptr<MetadataProvider> m_metadata;
- scoped_ptr<TrustEngine> m_trust;
- scoped_ptr<AttributeExtractor> m_extractor;
- scoped_ptr<AttributeFilter> m_filter;
- ptr_vector<saml2::Attribute> m_designators;
- vector< pair<string,bool> > m_sources;
- vector<string> m_exceptionId;
- };
-
- AttributeResolver* SHIBSP_DLLLOCAL SimpleAggregationResolverFactory(const DOMElement* const & e, bool deprecationSupport)
- {
- return new SimpleAggregationResolver(e, deprecationSupport);
- }
-
- static const XMLCh _AttributeExtractor[] = UNICODE_LITERAL_18(A,t,t,r,i,b,u,t,e,E,x,t,r,a,c,t,o,r);
- static const XMLCh _AttributeFilter[] = UNICODE_LITERAL_15(A,t,t,r,i,b,u,t,e,F,i,l,t,e,r);
- static const XMLCh attributeId[] = UNICODE_LITERAL_11(a,t,t,r,i,b,u,t,e,I,d);
- static const XMLCh Entity[] = UNICODE_LITERAL_6(E,n,t,i,t,y);
- static const XMLCh EntityReference[] = UNICODE_LITERAL_15(E,n,t,i,t,y,R,e,f,e,r,e,n,c,e);
- static const XMLCh exceptionId[] = UNICODE_LITERAL_11(e,x,c,e,p,t,i,o,n,I,d);
- static const XMLCh format[] = UNICODE_LITERAL_6(f,o,r,m,a,t);
- static const XMLCh _MetadataProvider[] = UNICODE_LITERAL_16(M,e,t,a,d,a,t,a,P,r,o,v,i,d,e,r);
- static const XMLCh policyId[] = UNICODE_LITERAL_8(p,o,l,i,c,y,I,d);
- static const XMLCh subjectMatch[] = UNICODE_LITERAL_12(s,u,b,j,e,c,t,M,a,t,c,h);
- static const XMLCh _TrustEngine[] = UNICODE_LITERAL_11(T,r,u,s,t,E,n,g,i,n,e);
- static const XMLCh _type[] = UNICODE_LITERAL_4(t,y,p,e);
-};
-
-SimpleAggregationResolver::SimpleAggregationResolver(const DOMElement* e, bool deprecationSupport)
- : m_log(Category::getInstance(SHIBSP_LOGCAT ".AttributeResolver.SimpleAggregation")),
- m_policyId(XMLHelper::getAttrString(e, nullptr, policyId)),
- m_subjectMatch(XMLHelper::getAttrBool(e, false, subjectMatch))
-{
-#ifdef _DEBUG
- xmltooling::NDC ndc("SimpleAggregationResolver");
-#endif
-
- const XMLCh* aid = e ? e->getAttributeNS(nullptr, attributeId) : nullptr;
- if (aid && *aid) {
- auto_ptr_char dup(aid);
- string sdup(dup.get());
- trim(sdup);
- split(m_attributeIds, sdup, is_space(), algorithm::token_compress_on);
-
- aid = e->getAttributeNS(nullptr, format);
- if (aid && *aid)
- m_format = aid;
- }
-
- string exid(XMLHelper::getAttrString(e, nullptr, exceptionId));
- if (!exid.empty())
- m_exceptionId.push_back(exid);
-
- DOMElement* child = XMLHelper::getFirstChildElement(e, _MetadataProvider);
- if (child) {
- string t(XMLHelper::getAttrString(child, nullptr, _type));
- if (t.empty())
- throw ConfigurationException("MetadataProvider element missing type attribute.");
- m_log.info("building MetadataProvider of type %s...", t.c_str());
- m_metadata.reset(SAMLConfig::getConfig().MetadataProviderManager.newPlugin(t.c_str(), child, deprecationSupport));
- m_metadata->init();
- }
-
- child = XMLHelper::getFirstChildElement(e, _TrustEngine);
- if (child) {
- string t(XMLHelper::getAttrString(child, nullptr, _type));
- if (t.empty())
- throw ConfigurationException("TrustEngine element missing type attribute.");
- m_log.info("building TrustEngine of type %s...", t.c_str());
- m_trust.reset(XMLToolingConfig::getConfig().TrustEngineManager.newPlugin(t.c_str(), child, deprecationSupport));
- }
-
- child = XMLHelper::getFirstChildElement(e, _AttributeExtractor);
- if (child) {
- string t(XMLHelper::getAttrString(child, nullptr, _type));
- if (t.empty())
- throw ConfigurationException("AttributeExtractor element missing type attribute.");
- m_log.info("building AttributeExtractor of type %s...", t.c_str());
- m_extractor.reset(SPConfig::getConfig().AttributeExtractorManager.newPlugin(t.c_str(), child, deprecationSupport));
- }
-
- child = XMLHelper::getFirstChildElement(e, _AttributeFilter);
- if (child) {
- string t(XMLHelper::getAttrString(child, nullptr, _type));
- if (t.empty())
- throw ConfigurationException("AttributeFilter element missing type attribute.");
- m_log.info("building AttributeFilter of type %s...", t.c_str());
- m_filter.reset(SPConfig::getConfig().AttributeFilterManager.newPlugin(t.c_str(), child, deprecationSupport));
- }
-
- child = XMLHelper::getFirstChildElement(e);
- while (child) {
- if (child->hasChildNodes() && XMLString::equals(child->getLocalName(), Entity)) {
- aid = child->getFirstChild()->getNodeValue();
- if (aid && *aid) {
- auto_ptr_char taid(aid);
- m_sources.push_back(pair<string,bool>(taid.get(),true));
- }
- }
- else if (child->hasChildNodes() && XMLString::equals(child->getLocalName(), EntityReference)) {
- aid = child->getFirstChild()->getNodeValue();
- if (aid && *aid) {
- auto_ptr_char taid(aid);
- m_sources.push_back(pair<string,bool>(taid.get(),false));
- }
- }
- else if (XMLHelper::isNodeNamed(child, samlconstants::SAML20_NS, saml2::Attribute::LOCAL_NAME)) {
- try {
- auto_ptr<XMLObject> obj(saml2::AttributeBuilder::buildOneFromElement(child));
- saml2::Attribute* down = dynamic_cast<saml2::Attribute*>(obj.get());
- if (down) {
- m_designators.push_back(down);
- obj.release();
- }
- }
- catch (const std::exception& ex) {
- m_log.error("exception loading attribute designator: %s", ex.what());
- }
- }
- child = XMLHelper::getNextSiblingElement(child);
- }
-}
-
-void SimpleAggregationResolver::doQuery(SimpleAggregationContext& ctx, const char* entityID, const NameID* name) const
-{
-#ifdef _DEBUG
- xmltooling::NDC ndc("doQuery");
-#endif
- const Application& application = ctx.getApplication();
- MetadataProviderCriteria mc(application, entityID, &AttributeAuthorityDescriptor::ELEMENT_QNAME, samlconstants::SAML20P_NS);
- Locker mlocker(m_metadata.get());
- const AttributeAuthorityDescriptor* AA=nullptr;
- pair<const EntityDescriptor*,const RoleDescriptor*> mdresult =
- (m_metadata ? m_metadata.get() : application.getMetadataProvider())->getEntityDescriptor(mc);
- if (!mdresult.first) {
- m_log.warn("unable to locate metadata for provider (%s)", entityID);
- throw MetadataException("Unable to locate metadata for provider ($entityID)", namedparams(1, "entityID", entityID));
- }
- else if (!(AA=dynamic_cast<const AttributeAuthorityDescriptor*>(mdresult.second))) {
- m_log.warn("no SAML 2 AttributeAuthority role found in metadata for (%s)", entityID);
- throw MetadataException("Unable to locate SAML 2.0 AttributeAuthority role for provider ($entityID)", namedparams(1, "entityID", entityID));
- }
-
- const PropertySet* relyingParty = application.getRelyingParty(mdresult.first);
- pair<bool,bool> signedAssertions = relyingParty->getBool("requireSignedAssertions");
- pair<bool,const char*> encryption = relyingParty->getString("encryption");
-
- // Locate policy key.
- const char* policyId = m_policyId.empty() ? application.getString("policyId").second : m_policyId.c_str();
-
- // Set up policy and SOAP client.
- scoped_ptr<SecurityPolicy> policy(
- application.getServiceProvider().getSecurityPolicyProvider()->createSecurityPolicy(
- samlconstants::SAML20_PROFILE_QUERY, application, nullptr, policyId
- )
- );
- if (m_metadata)
- policy->setMetadataProvider(m_metadata.get());
- if (m_trust)
- policy->setTrustEngine(m_trust.get());
- policy->getAudiences().push_back(relyingParty->getXMLString("entityID").second);
-
- MetadataCredentialCriteria mcc(*AA);
- shibsp::SOAPClient soaper(*policy.get());
-
- auto_ptr_XMLCh binding(samlconstants::SAML20_BINDING_SOAP);
- auto_ptr<saml2p::StatusResponseType> srt;
- const vector<AttributeService*>& endpoints=AA->getAttributeServices();
- for (indirect_iterator<vector<AttributeService*>::const_iterator> ep = make_indirect_iterator(endpoints.begin());
- !srt.get() && ep != make_indirect_iterator(endpoints.end()); ++ep) {
- if (!XMLString::equals(ep->getBinding(), binding.get()) || !ep->getLocation())
- continue;
- auto_ptr_char loc(ep->getLocation());
- try {
- auto_ptr<saml2::Subject> subject(saml2::SubjectBuilder::buildSubject());
-
- // Encrypt the NameID?
- if (SPConfig::shouldSignOrEncrypt(encryption.first ? encryption.second : "conditional", loc.get(), false)) {
- try {
- auto_ptr<EncryptedID> encrypted(EncryptedIDBuilder::buildEncryptedID());
- encrypted->encrypt(
- *name,
- *(policy->getMetadataProvider()),
- mcc,
- false,
- relyingParty->getXMLString("encryptionAlg").second
- );
- subject->setEncryptedID(encrypted.get());
- encrypted.release();
- }
- catch (const std::exception& ex) {
- // If we're encrypting deliberately, failure should be fatal.
- if (encryption.first && strcmp(encryption.second, "conditional")) {
- throw;
- }
- // If opportunistically, just log and move on.
- m_log.info("Conditional encryption of NameID in AttributeQuery failed: %s", ex.what());
- auto_ptr<NameID> namewrapper(name->cloneNameID());
- subject->setNameID(namewrapper.get());
- namewrapper.release();
- }
- }
- else {
- auto_ptr<NameID> namewrapper(name->cloneNameID());
- subject->setNameID(namewrapper.get());
- namewrapper.release();
- }
-
- saml2p::AttributeQuery* query = saml2p::AttributeQueryBuilder::buildAttributeQuery();
- query->setSubject(subject.release());
- Issuer* iss = IssuerBuilder::buildIssuer();
- iss->setName(relyingParty->getXMLString("entityID").second);
- query->setIssuer(iss);
- for (ptr_vector<saml2::Attribute>::const_iterator ad = m_designators.begin(); ad != m_designators.end(); ++ad) {
- auto_ptr<saml2::Attribute> adwrapper(ad->cloneAttribute());
- query->getAttributes().push_back(adwrapper.get());
- adwrapper.release();
- }
-
- SAML2SOAPClient client(soaper, false);
- client.sendSAML(query, application.getId(), mcc, loc.get());
- srt.reset(client.receiveSAML());
- }
- catch (const std::exception& ex) {
- m_log.error("exception during SAML query to %s: %s", loc.get(), ex.what());
- soaper.reset();
- }
- }
-
- if (!srt.get()) {
- m_log.error("unable to obtain a SAML response from attribute authority (%s)", entityID);
- throw BindingException("Unable to obtain a SAML response from attribute authority.");
- }
-
- saml2p::Response* response = dynamic_cast<saml2p::Response*>(srt.get());
- if (!response) {
- m_log.error("message was not a samlp:Response");
- throw FatalProfileException("Attribute authority returned an unrecognized message.");
- }
- else if (!response->getStatus() || !response->getStatus()->getStatusCode() ||
- !XMLString::equals(response->getStatus()->getStatusCode()->getValue(), saml2p::StatusCode::SUCCESS)) {
- m_log.error("attribute authority (%s) returned a SAML error", entityID);
- throw FatalProfileException("Attribute authority returned a SAML error.");
- }
-
- saml2::Assertion* newtoken = nullptr;
- auto_ptr<saml2::Assertion> newtokenwrapper;
- const vector<saml2::Assertion*>& assertions = const_cast<const saml2p::Response*>(response)->getAssertions();
- if (assertions.empty()) {
- // Check for encryption.
- const vector<saml2::EncryptedAssertion*>& encassertions =
- const_cast<const saml2p::Response*>(response)->getEncryptedAssertions();
- if (encassertions.empty()) {
- m_log.warn("response from attribute authority was empty");
- return;
- }
- else if (encassertions.size() > 1) {
- m_log.warn("simple resolver only supports one assertion in the query response");
- }
-
- CredentialResolver* cr=application.getCredentialResolver();
- if (!cr) {
- m_log.warn("found encrypted assertion, but no CredentialResolver was available");
- throw FatalProfileException("Assertion was encrypted, but no decryption credentials are available.");
- }
-
- // With this flag on, we block unauthenticated ciphertext when decrypting,
- // unless the protocol was authenticated.
- pair<bool,bool> authenticatedCipher = application.getBool("requireAuthenticatedEncryption");
- if (policy->isAuthenticated())
- authenticatedCipher.second = false;
-
- // Attempt to decrypt it.
- try {
- Locker credlocker(cr);
- auto_ptr<XMLObject> tokenwrapper(
- encassertions.front()->decrypt(
- *cr, relyingParty->getXMLString("entityID").second, &mcc, authenticatedCipher.first && authenticatedCipher.second
- )
- );
- newtoken = dynamic_cast<saml2::Assertion*>(tokenwrapper.get());
- if (newtoken) {
- tokenwrapper.release();
- newtokenwrapper.reset(newtoken);
- if (m_log.isDebugEnabled())
- m_log.debugStream() << "decrypted assertion: " << *newtoken << logging::eol;
- }
- }
- catch (const std::exception& ex) {
- m_log.error("failed to decrypt assertion: %s", ex.what());
- throw;
- }
- }
- else {
- if (assertions.size() > 1)
- m_log.warn("simple resolver only supports one assertion in the query response");
- newtoken = assertions.front();
- }
-
- if (!newtoken->getSignature() && signedAssertions.first && signedAssertions.second) {
- m_log.error("assertion unsigned, rejecting it based on signedAssertions policy");
- throw SecurityPolicyException("Rejected unsigned assertion based on local policy.");
- }
-
- try {
- // We're going to insist that the assertion issuer is the same as the peer.
- // Reset the policy's message bits and extract them from the assertion.
- policy->reset(true);
- policy->setMessageID(newtoken->getID());
- policy->setIssueInstant(newtoken->getIssueInstantEpoch());
- policy->setIssuer(newtoken->getIssuer());
- policy->evaluate(*newtoken);
-
- // Now we can check the security status of the policy.
- if (!policy->isAuthenticated())
- throw SecurityPolicyException("Security of SAML 2.0 query result not established.");
-
- if (m_subjectMatch) {
- // Check for subject match.
- auto_ptr<NameID> nameIDwrapper;
- NameID* respName = newtoken->getSubject() ? newtoken->getSubject()->getNameID() : nullptr;
- if (!respName) {
- // Check for encryption.
- EncryptedID* encname = newtoken->getSubject() ? newtoken->getSubject()->getEncryptedID() : nullptr;
- if (encname) {
- CredentialResolver* cr=application.getCredentialResolver();
- if (!cr)
- m_log.warn("found EncryptedID, but no CredentialResolver was available");
- else {
- Locker credlocker(cr);
- auto_ptr<XMLObject> decryptedID(encname->decrypt(*cr, relyingParty->getXMLString("entityID").second, &mcc));
- respName = dynamic_cast<NameID*>(decryptedID.get());
- if (respName) {
- decryptedID.release();
- nameIDwrapper.reset(respName);
- if (m_log.isDebugEnabled())
- m_log.debugStream() << "decrypted NameID: " << *respName << logging::eol;
- }
- }
- }
- }
-
- if (!respName || !XMLString::equals(respName->getName(), name->getName()) ||
- !XMLString::equals(respName->getFormat(), name->getFormat()) ||
- !XMLString::equals(respName->getNameQualifier(), name->getNameQualifier()) ||
- !XMLString::equals(respName->getSPNameQualifier(), name->getSPNameQualifier())) {
- if (respName)
- m_log.warnStream() << "ignoring Assertion without strongly matching NameID in Subject: " <<
- *respName << logging::eol;
- else
- m_log.warn("ignoring Assertion without NameID in Subject");
- return;
- }
- }
- }
- catch (const std::exception& ex) {
- m_log.error("assertion failed policy validation: %s", ex.what());
- throw;
- }
-
- // If the token's embedded, detach it.
- if (!newtokenwrapper.get()) {
- newtoken->detach();
- srt.release(); // detach blows away the Response, so avoid a double free
- newtokenwrapper.reset(newtoken);
- }
- ctx.getResolvedAssertions().push_back(newtoken);
- newtokenwrapper.release();
-
- // Finally, extract and filter the result.
- try {
- AttributeExtractor* extractor = m_extractor ? m_extractor.get() : application.getAttributeExtractor();
- if (extractor) {
- Locker extlocker(extractor);
- extractor->extractAttributes(application, ctx.getRequest(), AA, *newtoken, ctx.getResolvedAttributes());
- }
-
- AttributeFilter* filter = m_filter ? m_filter.get() : application.getAttributeFilter();
- if (filter) {
- BasicFilteringContext fc(application, ctx.getResolvedAttributes(), AA, ctx.getClassRef(), ctx.getDeclRef());
- Locker filtlocker(filter);
- filter->filterAttributes(fc, ctx.getResolvedAttributes());
- }
- }
- catch (const std::exception& ex) {
- m_log.error("caught exception extracting/filtering attributes from query result: %s", ex.what());
- for_each(ctx.getResolvedAttributes().begin(), ctx.getResolvedAttributes().end(), xmltooling::cleanup<shibsp::Attribute>());
- ctx.getResolvedAttributes().clear();
- throw;
- }
-}
-
-void SimpleAggregationResolver::resolveAttributes(ResolutionContext& ctx) const
-{
-#ifdef _DEBUG
- xmltooling::NDC ndc("resolveAttributes");
-#endif
-
- SimpleAggregationContext& qctx = dynamic_cast<SimpleAggregationContext&>(ctx);
-
- // First we manufacture the appropriate NameID to use.
- scoped_ptr<NameID> n;
- for (vector<string>::const_iterator a = m_attributeIds.begin(); !n.get() && a != m_attributeIds.end(); ++a) {
- const Attribute* attr=nullptr;
- if (qctx.getSession()) {
- // Input attributes should be available via multimap.
- pair<multimap<string,const Attribute*>::const_iterator, multimap<string,const Attribute*>::const_iterator> range =
- qctx.getSession()->getIndexedAttributes().equal_range(*a);
- for (; !attr && range.first != range.second; ++range.first) {
- if (range.first->second->valueCount() > 0)
- attr = range.first->second;
- }
- }
- else if (qctx.getInputAttributes()) {
- // Have to loop over unindexed set.
- const vector<Attribute*>* matches = qctx.getInputAttributes();
- for (indirect_iterator<vector<Attribute*>::const_iterator> match = make_indirect_iterator(matches->begin());
- !attr && match != make_indirect_iterator(matches->end()); ++match) {
- if (*a == match->getId() && match->valueCount() > 0)
- attr = &(*match);
- }
- }
-
- if (attr) {
- m_log.debug("using input attribute (%s) as identifier for queries", attr->getId());
- n.reset(NameIDBuilder::buildNameID());
- const NameIDAttribute* down = dynamic_cast<const NameIDAttribute*>(attr);
- if (down) {
- // We can create a NameID directly from the source material.
- const NameIDAttribute::Value& v = down->getValues().front();
- auto_arrayptr<XMLCh> val(fromUTF8(v.m_Name.c_str()));
- n->setName(val.get());
-
- if (!v.m_Format.empty()) {
- auto_arrayptr<XMLCh> format(fromUTF8(v.m_Format.c_str()));
- n->setFormat(format.get());
- }
- if (!v.m_NameQualifier.empty()) {
- auto_arrayptr<XMLCh> nq(fromUTF8(v.m_NameQualifier.c_str()));
- n->setNameQualifier(nq.get());
- }
- if (!v.m_SPNameQualifier.empty()) {
- auto_arrayptr<XMLCh> spnq(fromUTF8(v.m_SPNameQualifier.c_str()));
- n->setSPNameQualifier(spnq.get());
- }
- if (!v.m_SPProvidedID.empty()) {
- auto_arrayptr<XMLCh> sppid(fromUTF8(v.m_SPProvidedID.c_str()));
- n->setSPProvidedID(sppid.get());
- }
- }
- else {
- // We have to mock up the NameID.
- auto_arrayptr<XMLCh> val(fromUTF8(attr->getSerializedValues().front().c_str()));
- n->setName(val.get());
- if (!m_format.empty())
- n->setFormat(m_format.c_str());
- }
- }
- }
-
- if (!n) {
- if (qctx.getNameID() && m_attributeIds.empty()) {
- m_log.debug("using authenticated NameID as identifier for queries");
- }
- else {
- m_log.warn("unable to resolve attributes, no suitable query identifier found");
- return;
- }
- }
-
- set<string> history;
-
- // Put initial IdP into history to prevent extra query.
- if (qctx.getEntityID())
- history.insert(qctx.getEntityID());
-
- // Prepare to track exceptions.
- auto_ptr<SimpleAttribute> exceptAttr;
- if (!m_exceptionId.empty())
- exceptAttr.reset(new SimpleAttribute(m_exceptionId));
-
- // We have a master loop over all the possible sources of material.
- for (vector< pair<string,bool> >::const_iterator source = m_sources.begin(); source != m_sources.end(); ++source) {
- if (source->second) {
- // A literal entityID to query.
- if (history.count(source->first) == 0) {
- m_log.debug("issuing SAML query to (%s)", source->first.c_str());
- try {
- doQuery(qctx, source->first.c_str(), n ? n.get() : qctx.getNameID());
- }
- catch (const std::exception& ex) {
- if (exceptAttr.get())
- exceptAttr->getValues().push_back(XMLToolingConfig::getConfig().getURLEncoder()->encode(ex.what()));
- }
- history.insert(source->first);
- }
- else {
- m_log.debug("skipping previously queried attribute source (%s)", source->first.c_str());
- }
- }
- else {
- m_log.debug("using attribute sources referenced in attribute (%s)", source->first.c_str());
- if (qctx.getSession()) {
- // Input attributes should be available via multimap.
- pair<multimap<string,const Attribute*>::const_iterator, multimap<string,const Attribute*>::const_iterator> range =
- qctx.getSession()->getIndexedAttributes().equal_range(source->first);
- for (; range.first != range.second; ++range.first) {
- const vector<string>& links = range.first->second->getSerializedValues();
- for (vector<string>::const_iterator link = links.begin(); link != links.end(); ++link) {
- if (history.count(*link) == 0) {
- m_log.debug("issuing SAML query to (%s)", link->c_str());
- try {
- doQuery(qctx, link->c_str(), n ? n.get() : qctx.getNameID());
- }
- catch (const std::exception& ex) {
- if (exceptAttr.get())
- exceptAttr->getValues().push_back(XMLToolingConfig::getConfig().getURLEncoder()->encode(ex.what()));
- }
- history.insert(*link);
- }
- else {
- m_log.debug("skipping previously queried attribute source (%s)", link->c_str());
- }
- }
- }
- }
- else if (qctx.getInputAttributes()) {
- // Have to loop over unindexed set.
- const vector<Attribute*>* matches = qctx.getInputAttributes();
- for (indirect_iterator<vector<Attribute*>::const_iterator> match = make_indirect_iterator(matches->begin());
- match != make_indirect_iterator(matches->end()); ++match) {
- if (source->first == match->getId()) {
- const vector<string>& links = match->getSerializedValues();
- for (vector<string>::const_iterator link = links.begin(); link != links.end(); ++link) {
- if (history.count(*link) == 0) {
- m_log.debug("issuing SAML query to (%s)", link->c_str());
- try {
- doQuery(qctx, link->c_str(), n ? n.get() : qctx.getNameID());
- }
- catch (const std::exception& ex) {
- if (exceptAttr.get())
- exceptAttr->getValues().push_back(XMLToolingConfig::getConfig().getURLEncoder()->encode(ex.what()));
- }
- history.insert(*link);
- }
- else {
- m_log.debug("skipping previously queried attribute source (%s)", link->c_str());
- }
- }
- }
- }
- }
- }
- }
-
- if (exceptAttr.get()) {
- qctx.getResolvedAttributes().push_back(exceptAttr.get());
- exceptAttr.release();
- }
-}
diff --git a/shibsp/attribute/resolver/impl/XMLAttributeExtractor.cpp b/shibsp/attribute/resolver/impl/XMLAttributeExtractor.cpp
deleted file mode 100644
index 927788c8..00000000
--- a/shibsp/attribute/resolver/impl/XMLAttributeExtractor.cpp
+++ /dev/null
@@ -1,1068 +0,0 @@
-/**
- * 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.
- */
-
-/**
- * XMLAttributeExtractor.cpp
- *
- * AttributeExtractor based on an XML mapping file.
- */
-
-#include "internal.h"
-#include "exceptions.h"
-#include "Application.h"
-#include "ServiceProvider.h"
-#include "attribute/Attribute.h"
-#include "attribute/AttributeDecoder.h"
-#include "attribute/filtering/AttributeFilter.h"
-#include "attribute/filtering/BasicFilteringContext.h"
-#include "attribute/resolver/AttributeExtractor.h"
-#include "remoting/ddf.h"
-#include "security/SecurityPolicy.h"
-#include "util/SPConstants.h"
-
-#define BOOST_BIND_GLOBAL_PLACEHOLDERS
-#include <boost/bind.hpp>
-#include <boost/shared_ptr.hpp>
-#include <boost/algorithm/string.hpp>
-#include <boost/iterator/indirect_iterator.hpp>
-#include <boost/ptr_container/ptr_vector.hpp>
-#include <boost/tuple/tuple.hpp>
-#include <saml/SAMLConfig.h>
-#include <saml/saml1/core/Assertions.h>
-#include <saml/saml2/core/Assertions.h>
-#include <saml/saml2/metadata/Metadata.h>
-#include <saml/saml2/metadata/MetadataCredentialCriteria.h>
-#include <saml/saml2/metadata/ObservableMetadataProvider.h>
-#include <xmltooling/XMLToolingConfig.h>
-#include <xmltooling/security/TrustEngine.h>
-#include <xmltooling/util/NDC.h>
-#include <xmltooling/util/ReloadableXMLFile.h>
-#include <xmltooling/util/Threads.h>
-#include <xmltooling/util/XMLHelper.h>
-#include <xercesc/util/XMLUniDefs.hpp>
-
-using namespace shibsp;
-using namespace opensaml::saml2md;
-using namespace opensaml;
-using namespace xmltooling;
-using namespace boost;
-using namespace std;
-using saml1::NameIdentifier;
-using saml2::NameID;
-using saml2::EncryptedAttribute;
-
-namespace shibsp {
-
-#if defined (_MSC_VER)
- #pragma warning( push )
- #pragma warning( disable : 4250 )
-#endif
-
- class XMLExtractorImpl : public ObservableMetadataProvider::Observer
- {
- public:
- XMLExtractorImpl(const DOMElement* e, Category& log, bool deprecationSupport);
- ~XMLExtractorImpl() {
- for (map<const ObservableMetadataProvider*,decoded_t>::iterator i=m_decodedMap.begin(); i!=m_decodedMap.end(); ++i) {
- i->first->removeObserver(this);
- for (decoded_t::iterator attrs = i->second.begin(); attrs!=i->second.end(); ++attrs)
- for_each(attrs->second.begin(), attrs->second.end(), mem_fun_ref<DDF&,DDF>(&DDF::destroy));
- }
- if (m_document)
- m_document->release();
- }
-
- void setDocument(DOMDocument* doc) {
- m_document = doc;
- }
-
- void onEvent(const ObservableMetadataProvider& metadata) const {
- // Destroy attributes we cached from this provider.
- m_attrLock->wrlock();
- SharedLock wrapper(m_attrLock, false);
- decoded_t& d = m_decodedMap[&metadata];
- for (decoded_t::iterator a = d.begin(); a!=d.end(); ++a)
- for_each(a->second.begin(), a->second.end(), mem_fun_ref<DDF&,DDF>(&DDF::destroy));
- d.clear();
- }
-
- void onEvent(const ObservableMetadataProvider& metadata, const EntityDescriptor& entity) const {
- // Destroy attributes we cached from this provider and entity.
- m_attrLock->wrlock();
- SharedLock wrapper(m_attrLock, false);
- decoded_t& d = m_decodedMap[&metadata];
- decoded_t::iterator i = d.find(entity.getEntityID());
- if (i != d.end()) {
- for_each(i->second.begin(), i->second.end(), mem_fun_ref<DDF&, DDF>(&DDF::destroy));
- d.erase(i);
- }
- }
-
-
- void extractAttributes(const Application&, const char*, const char*, const NameIdentifier&, ptr_vector<Attribute>&) const;
- void extractAttributes(const Application&, const char*, const char*, const NameID&, ptr_vector<Attribute>&) const;
- void extractAttributes(const Application&, const GenericRequest*, const char*, const char*, const saml1::Attribute&, ptr_vector<Attribute>&) const;
- void extractAttributes(const Application&, const GenericRequest*, const char*, const char*, const saml2::Attribute&, ptr_vector<Attribute>&) const;
- void extractAttributes(const Application&, const GenericRequest*, const char*, const char*, const saml1::AttributeStatement&, ptr_vector<Attribute>&) const;
- void extractAttributes(const Application&, const GenericRequest*, const char*, const char*, const saml2::AttributeStatement&, ptr_vector<Attribute>&) const;
- void extractAttributes(
- const Application&, const GenericRequest*, const ObservableMetadataProvider*, const XMLCh*, const char*, const Extensions&, ptr_vector<Attribute>&
- ) const;
-
- void getAttributeIds(vector<string>& attributes) const {
- attributes.insert(attributes.end(), m_attributeIds.begin(), m_attributeIds.end());
- }
-
- void generateMetadata(SPSSODescriptor& role) const;
-
- private:
- Category& m_log;
- DOMDocument* m_document;
- typedef map< pair<xstring,xstring>,pair< boost::shared_ptr<AttributeDecoder>,vector<string> > > attrmap_t;
- attrmap_t m_attrMap;
- vector<string> m_attributeIds;
- vector< boost::tuple<xstring,xstring,bool> > m_requestedAttrs;
-
- // settings for embedded assertions in metadata
- string m_policyId;
- scoped_ptr<AttributeFilter> m_filter;
- scoped_ptr<MetadataProvider> m_metadata;
- scoped_ptr<TrustEngine> m_trust;
- bool m_entityAssertions,m_metaAttrCaching;
-
- // manages caching of decoded Attributes
- scoped_ptr<RWLock> m_attrLock;
- typedef map< xstring,vector<DDF> > decoded_t;
- mutable map<const ObservableMetadataProvider*,decoded_t> m_decodedMap;
- };
-
- class XMLExtractor : public AttributeExtractor, public ReloadableXMLFile
- {
- public:
- XMLExtractor(const DOMElement* e, bool deprecationSupport=true)
- : ReloadableXMLFile(e, Category::getInstance(SHIBSP_LOGCAT ".AttributeExtractor.XML"), true, deprecationSupport),
- m_deprecationSupport(deprecationSupport)
- {
- if (m_local && m_lock)
- m_log.warn("attribute mappings are reloadable; be sure to restart web server when adding new attribute IDs");
- background_load();
- }
-
- ~XMLExtractor() {
- shutdown();
- }
-
- void extractAttributes(const Application&, const GenericRequest*, const RoleDescriptor*, const XMLObject&, vector<Attribute*>&) const;
-
- void getAttributeIds(std::vector<std::string>& attributes) const {
- if (m_impl)
- m_impl->getAttributeIds(attributes);
- }
-
- void generateMetadata(SPSSODescriptor& role) const {
- if (m_impl)
- m_impl->generateMetadata(role);
- }
-
- protected:
- pair<bool,DOMElement*> background_load();
-
- private:
- bool m_deprecationSupport;
- scoped_ptr<XMLExtractorImpl> m_impl;
-
- void extractAttributes(const Application&, const GenericRequest*, const RoleDescriptor*, const XMLObject&, ptr_vector<Attribute>&) const;
- };
-
-#if defined (_MSC_VER)
- #pragma warning( pop )
-#endif
-
- AttributeExtractor* SHIBSP_DLLLOCAL XMLAttributeExtractorFactory(const DOMElement* const & e, bool)
- {
- return new XMLExtractor(e);
- }
-
- static const XMLCh _aliases[] = UNICODE_LITERAL_7(a,l,i,a,s,e,s);
- static const XMLCh _AttributeDecoder[] = UNICODE_LITERAL_16(A,t,t,r,i,b,u,t,e,D,e,c,o,d,e,r);
- static const XMLCh _AttributeFilter[] = UNICODE_LITERAL_15(A,t,t,r,i,b,u,t,e,F,i,l,t,e,r);
- static const XMLCh Attributes[] = UNICODE_LITERAL_10(A,t,t,r,i,b,u,t,e,s);
- static const XMLCh _id[] = UNICODE_LITERAL_2(i,d);
- static const XMLCh isRequested[] = UNICODE_LITERAL_11(i,s,R,e,q,u,e,s,t,e,d);
- static const XMLCh _MetadataProvider[] = UNICODE_LITERAL_16(M,e,t,a,d,a,t,a,P,r,o,v,i,d,e,r);
- static const XMLCh metadataAttributeCaching[] = UNICODE_LITERAL_24(m,e,t,a,d,a,t,a,A,t,t,r,i,b,u,t,e,C,a,c,h,i,n,g);
- static const XMLCh metadataPolicyId[] = UNICODE_LITERAL_16(m,e,t,a,d,a,t,a,P,o,l,i,c,y,I,d);
- static const XMLCh _name[] = UNICODE_LITERAL_4(n,a,m,e);
- static const XMLCh nameFormat[] = UNICODE_LITERAL_10(n,a,m,e,F,o,r,m,a,t);
- static const XMLCh _TrustEngine[] = UNICODE_LITERAL_11(T,r,u,s,t,E,n,g,i,n,e);
- static const XMLCh _type[] = UNICODE_LITERAL_4(t,y,p,e);
-};
-
-XMLExtractorImpl::XMLExtractorImpl(const DOMElement* e, Category& log, bool deprecationSupport)
- : m_log(log),
- m_document(nullptr),
- m_policyId(XMLHelper::getAttrString(e, nullptr, metadataPolicyId)),
- m_entityAssertions(true),
- m_metaAttrCaching(XMLHelper::getAttrBool(e, false, metadataAttributeCaching))
-{
-#ifdef _DEBUG
- xmltooling::NDC ndc("XMLExtractorImpl");
-#endif
-
- if (!XMLHelper::isNodeNamed(e, shibspconstants::SHIB2ATTRIBUTEMAP_NS, Attributes))
- throw ConfigurationException("XML AttributeExtractor requires am:Attributes at root of configuration.");
-
- DOMElement* child = XMLHelper::getFirstChildElement(e, shibspconstants::SHIB2ATTRIBUTEMAP_NS, _MetadataProvider);
- if (child) {
- try {
- string t(XMLHelper::getAttrString(child, nullptr, _type));
- if (t.empty())
- throw ConfigurationException("MetadataProvider element missing type attribute.");
- m_log.info("building MetadataProvider of type %s...", t.c_str());
- m_metadata.reset(SAMLConfig::getConfig().MetadataProviderManager.newPlugin(t.c_str(), child, deprecationSupport));
- m_metadata->init();
- }
- catch (const std::exception& ex) {
- m_metadata.reset();
- m_entityAssertions = false;
- m_log.crit("error building/initializing dedicated MetadataProvider: %s", ex.what());
- m_log.crit("disabling support for Assertions in EntityAttributes extension");
- }
- }
-
- if (m_entityAssertions) {
- child = XMLHelper::getFirstChildElement(e, shibspconstants::SHIB2ATTRIBUTEMAP_NS, _TrustEngine);
- if (child) {
- try {
- string t(XMLHelper::getAttrString(child, nullptr, _type));
- if (t.empty())
- throw ConfigurationException("TrustEngine element missing type attribute.");
- m_log.info("building TrustEngine of type %s...", t.c_str());
- m_trust.reset(XMLToolingConfig::getConfig().TrustEngineManager.newPlugin(t.c_str(), child, deprecationSupport));
- }
- catch (const std::exception& ex) {
- m_entityAssertions = false;
- m_log.crit("error building/initializing dedicated TrustEngine: %s", ex.what());
- m_log.crit("disabling support for Assertions in EntityAttributes extension");
- }
- }
- }
-
- if (m_entityAssertions) {
- child = XMLHelper::getFirstChildElement(e, shibspconstants::SHIB2ATTRIBUTEMAP_NS, _AttributeFilter);
- if (child) {
- try {
- string t(XMLHelper::getAttrString(child, nullptr, _type));
- if (t.empty())
- throw ConfigurationException("AttributeFilter element missing type attribute.");
- m_log.info("building AttributeFilter of type %s...", t.c_str());
- m_filter.reset(SPConfig::getConfig().AttributeFilterManager.newPlugin(t.c_str(), child, deprecationSupport));
- }
- catch (const std::exception& ex) {
- m_entityAssertions = false;
- m_log.crit("error building/initializing dedicated AttributeFilter: %s", ex.what());
- m_log.crit("disabling support for Assertions in EntityAttributes extension");
- }
- }
- }
-
- child = XMLHelper::getFirstChildElement(e, shibspconstants::SHIB2ATTRIBUTEMAP_NS, saml1::Attribute::LOCAL_NAME);
- while (child) {
- // Check for missing name or id.
- const XMLCh* name = child->getAttributeNS(nullptr, _name);
- if (!name || !*name) {
- m_log.warn("skipping Attribute with no name");
- child = XMLHelper::getNextSiblingElement(child, shibspconstants::SHIB2ATTRIBUTEMAP_NS, saml1::Attribute::LOCAL_NAME);
- continue;
- }
-
- auto_ptr_char id(child->getAttributeNS(nullptr, _id));
- if (!id.get() || !*id.get()) {
- m_log.warn("skipping Attribute with no id");
- child = XMLHelper::getNextSiblingElement(child, shibspconstants::SHIB2ATTRIBUTEMAP_NS, saml1::Attribute::LOCAL_NAME);
- continue;
- }
- else if (!strcmp(id.get(), "REMOTE_USER")) {
- m_log.warn("skipping Attribute, id of REMOTE_USER is a reserved name");
- child = XMLHelper::getNextSiblingElement(child, shibspconstants::SHIB2ATTRIBUTEMAP_NS, saml1::Attribute::LOCAL_NAME);
- continue;
- }
-
- boost::shared_ptr<AttributeDecoder> decoder;
- try {
- DOMElement* dchild = XMLHelper::getFirstChildElement(child, shibspconstants::SHIB2ATTRIBUTEMAP_NS, _AttributeDecoder);
- if (dchild) {
- scoped_ptr<xmltooling::QName> q(XMLHelper::getXSIType(dchild));
- if (q)
- decoder.reset(SPConfig::getConfig().AttributeDecoderManager.newPlugin(*q, dchild, deprecationSupport));
- }
- if (!decoder)
- decoder.reset(SPConfig::getConfig().AttributeDecoderManager.newPlugin(StringAttributeDecoderType, nullptr, deprecationSupport));
- }
- catch (const std::exception& ex) {
- m_log.error("skipping Attribute (%s), error building AttributeDecoder: %s", id.get(), ex.what());
- }
-
- if (!decoder) {
- child = XMLHelper::getNextSiblingElement(child, shibspconstants::SHIB2ATTRIBUTEMAP_NS, saml1::Attribute::LOCAL_NAME);
- continue;
- }
-
- // Empty NameFormat implies the usual Shib URI naming defaults.
- const XMLCh* format = child->getAttributeNS(nullptr, nameFormat);
- if (!format || XMLString::equals(format, shibspconstants::SHIB1_ATTRIBUTE_NAMESPACE_URI) ||
- XMLString::equals(format, saml2::Attribute::URI_REFERENCE))
- format = &chNull; // ignore default Format/Namespace values
-
- // Fetch/create the map entry and see if it's a duplicate rule.
- // Trim the format, or the name only if the format is the default (URI).
- pair<xstring,xstring> entryKey;
- if (*format == chNull) {
- auto_ptr_XMLCh copyName(name);
- entryKey.first = copyName.get();
- } else {
- entryKey.first = name;
- auto_ptr_XMLCh copyFormat(format);
- entryKey.second = copyFormat.get();
- }
- pair< boost::shared_ptr<AttributeDecoder>,vector<string> >& decl = m_attrMap[entryKey];
- if (decl.first) {
- m_log.warn("skipping duplicate Attribute mapping (same name and nameFormat)");
- child = XMLHelper::getNextSiblingElement(child, shibspconstants::SHIB2ATTRIBUTEMAP_NS, saml1::Attribute::LOCAL_NAME);
- continue;
- }
-
- if (m_log.isInfoEnabled()) {
- auto_ptr_char n(entryKey.first.c_str());
- auto_ptr_char f(entryKey.second.c_str());
- m_log.info("creating mapping for Attribute %s%s%s", n.get(), *f.get() ? ", Format/Namespace:" : "", f.get());
- }
-
- decl.first = decoder;
- decl.second.push_back(id.get());
- m_attributeIds.push_back(id.get());
-
- // Check for isRequired/isRequested.
- bool requested = XMLHelper::getAttrBool(child, false, isRequested);
- bool required = XMLHelper::getAttrBool(child, false, RequestedAttribute::ISREQUIRED_ATTRIB_NAME);
- if (required || requested) {
- m_requestedAttrs.push_back(boost::tuple<xstring,xstring,bool>(entryKey.first, entryKey.second, required));
- }
-
- if (deprecationSupport) {
- name = child->getAttributeNS(nullptr, _aliases);
- if (name && *name) {
- SPConfig::getConfig().deprecation().warn("attribute mapping rule (%s) uses deprecated aliases feature", id.get());
- auto_ptr_char aliases(name);
- string dup(aliases.get());
- set<string> new_aliases;
- split(new_aliases, dup, is_space(), algorithm::token_compress_on);
- set<string>::iterator ru = new_aliases.find("REMOTE_USER");
- if (ru != new_aliases.end()) {
- m_log.warn("skipping alias, REMOTE_USER is a reserved name");
- new_aliases.erase(ru);
- }
- decl.second.insert(decl.second.end(), new_aliases.begin(), new_aliases.end());
- m_attributeIds.insert(m_attributeIds.end(), new_aliases.begin(), new_aliases.end());
- }
- }
-
- child = XMLHelper::getNextSiblingElement(child, shibspconstants::SHIB2ATTRIBUTEMAP_NS, saml1::Attribute::LOCAL_NAME);
- }
-
- if (m_metaAttrCaching)
- m_attrLock.reset(RWLock::create());
-}
-
-void XMLExtractorImpl::generateMetadata(SPSSODescriptor& role) const
-{
- if (m_requestedAttrs.empty())
- return;
- int index = 1;
- const vector<AttributeConsumingService*>& svcs = const_cast<const SPSSODescriptor*>(&role)->getAttributeConsumingServices();
- for (vector<AttributeConsumingService*>::const_iterator s =svcs.begin(); s != svcs.end(); ++s) {
- pair<bool,int> i = (*s)->getIndex();
- if (i.first && index == i.second)
- index = i.second + 1;
- }
- AttributeConsumingService* svc = AttributeConsumingServiceBuilder::buildAttributeConsumingService();
- role.getAttributeConsumingServices().push_back(svc);
- svc->setIndex(index);
- ServiceName* sn = ServiceNameBuilder::buildServiceName();
- svc->getServiceNames().push_back(sn);
- sn->setName(dynamic_cast<EntityDescriptor*>(role.getParent())->getEntityID());
- static const XMLCh english[] = UNICODE_LITERAL_2(e,n);
- sn->setLang(english);
-
- for (vector< boost::tuple<xstring,xstring,bool> >::const_iterator i = m_requestedAttrs.begin(); i != m_requestedAttrs.end(); ++i) {
- RequestedAttribute* req = RequestedAttributeBuilder::buildRequestedAttribute();
- svc->getRequestedAttributes().push_back(req);
- req->setName(i->get<0>().c_str());
- if (i->get<1>().empty())
- req->setNameFormat(saml2::Attribute::URI_REFERENCE);
- else
- req->setNameFormat(i->get<1>().c_str());
- if (i->get<2>())
- req->isRequired(true);
- }
-}
-
-void XMLExtractorImpl::extractAttributes(
- const Application& application,
- const char* assertingParty,
- const char* relyingParty,
- const NameIdentifier& nameid,
- ptr_vector<Attribute>& attributes
- ) const
-{
- const XMLCh* format = nameid.getFormat();
- if (!format || !*format)
- format = NameIdentifier::UNSPECIFIED;
- attrmap_t::const_iterator rule;
- if ((rule = m_attrMap.find(pair<xstring,xstring>(format,xstring()))) != m_attrMap.end()) {
- auto_ptr<Attribute> a(rule->second.first->decode(nullptr, rule->second.second, &nameid, assertingParty, relyingParty));
- if (a.get()) {
- attributes.push_back(a.get());
- a.release();
- }
- }
- else if (m_log.isDebugEnabled()) {
- auto_ptr_char temp(format);
- m_log.debug("skipping NameIdentifier with format (%s)", temp.get());
- }
-}
-
-void XMLExtractorImpl::extractAttributes(
- const Application& application,
- const char* assertingParty,
- const char* relyingParty,
- const NameID& nameid,
- ptr_vector<Attribute>& attributes
- ) const
-{
- const XMLCh* format = nameid.getFormat();
- if (!format || !*format)
- format = NameID::UNSPECIFIED;
- attrmap_t::const_iterator rule;
- if ((rule = m_attrMap.find(pair<xstring,xstring>(format,xstring()))) != m_attrMap.end()) {
- auto_ptr<Attribute> a(rule->second.first->decode(nullptr, rule->second.second, &nameid, assertingParty, relyingParty));
- if (a.get()) {
- attributes.push_back(a.get());
- a.release();
- }
- }
- else if (m_log.isDebugEnabled()) {
- auto_ptr_char temp(format);
- m_log.debug("skipping NameID with format (%s)", temp.get());
- }
-}
-
-void XMLExtractorImpl::extractAttributes(
- const Application& application,
- const GenericRequest* request,
- const char* assertingParty,
- const char* relyingParty,
- const saml1::Attribute& attr,
- ptr_vector<Attribute>& attributes
- ) const
-{
- const XMLCh* name = attr.getAttributeName();
- const XMLCh* format = attr.getAttributeNamespace();
- if (!name || !*name)
- return;
- if (!format || XMLString::equals(format, shibspconstants::SHIB1_ATTRIBUTE_NAMESPACE_URI))
- format = &chNull;
- attrmap_t::const_iterator rule;
- if ((rule = m_attrMap.find(pair<xstring,xstring>(name,format))) != m_attrMap.end()) {
- auto_ptr<Attribute> a(rule->second.first->decode(request, rule->second.second, &attr, assertingParty, relyingParty));
- if (a.get()) {
- attributes.push_back(a.get());
- a.release();
- }
- }
- else if (m_log.isInfoEnabled()) {
- auto_ptr_char temp1(name);
- auto_ptr_char temp2(format);
- m_log.info("skipping SAML 1.x Attribute with Name: %s%s%s", temp1.get(), *temp2.get() ? ", Namespace:" : "", temp2.get());
- }
-}
-
-void XMLExtractorImpl::extractAttributes(
- const Application& application,
- const GenericRequest* request,
- const char* assertingParty,
- const char* relyingParty,
- const saml2::Attribute& attr,
- ptr_vector<Attribute>& attributes
- ) const
-{
- const XMLCh* name = attr.getName();
- const XMLCh* format = attr.getNameFormat();
- if (!name || !*name)
- return;
- if (!format || !*format)
- format = saml2::Attribute::UNSPECIFIED;
- else if (XMLString::equals(format, saml2::Attribute::URI_REFERENCE))
- format = &chNull;
- attrmap_t::const_iterator rule;
- if ((rule = m_attrMap.find(pair<xstring,xstring>(name,format))) != m_attrMap.end()) {
- auto_ptr<Attribute> a(rule->second.first->decode(request, rule->second.second, &attr, assertingParty, relyingParty));
- if (a.get()) {
- attributes.push_back(a.get());
- a.release();
- return;
- }
- }
- else if (XMLString::equals(format, saml2::Attribute::UNSPECIFIED)) {
- // As a fallback, if the format is "unspecified", null out the value and re-map.
- if ((rule = m_attrMap.find(pair<xstring,xstring>(name,xstring()))) != m_attrMap.end()) {
- auto_ptr<Attribute> a(rule->second.first->decode(request, rule->second.second, &attr, assertingParty, relyingParty));
- if (a.get()) {
- attributes.push_back(a.get());
- a.release();
- return;
- }
- }
- }
-
- if (m_log.isInfoEnabled()) {
- auto_ptr_char temp1(name);
- auto_ptr_char temp2(format);
- m_log.info("skipping SAML 2.0 Attribute with Name: %s%s%s", temp1.get(), *temp2.get() ? ", Format:" : "", temp2.get());
- }
-}
-
-void XMLExtractorImpl::extractAttributes(
- const Application& application,
- const GenericRequest* request,
- const char* assertingParty,
- const char* relyingParty,
- const saml1::AttributeStatement& statement,
- ptr_vector<Attribute>& attributes
- ) const
-{
- static void (XMLExtractorImpl::* extract)(
- const Application&, const GenericRequest*, const char*, const char*, const saml1::Attribute&, ptr_vector<Attribute>&
- ) const = &XMLExtractorImpl::extractAttributes;
- for_each(
- make_indirect_iterator(statement.getAttributes().begin()), make_indirect_iterator(statement.getAttributes().end()),
- boost::bind(extract, this, boost::cref(application), request, assertingParty, relyingParty, _1, boost::ref(attributes))
- );
-}
-
-void XMLExtractorImpl::extractAttributes(
- const Application& application,
- const GenericRequest* request,
- const char* assertingParty,
- const char* relyingParty,
- const saml2::AttributeStatement& statement,
- ptr_vector<Attribute>& attributes
- ) const
-{
- static void (XMLExtractorImpl::* extract)(
- const Application&, const GenericRequest*, const char*, const char*, const saml2::Attribute&, ptr_vector<Attribute>&
- ) const = &XMLExtractorImpl::extractAttributes;
- for_each(
- make_indirect_iterator(statement.getAttributes().begin()), make_indirect_iterator(statement.getAttributes().end()),
- boost::bind(extract, this, boost::cref(application), request, assertingParty, relyingParty, _1, boost::ref(attributes))
- );
-}
-
-void XMLExtractorImpl::extractAttributes(
- const Application& application,
- const GenericRequest* request,
- const ObservableMetadataProvider* observable,
- const XMLCh* entityID,
- const char* relyingParty,
- const Extensions& ext,
- ptr_vector<Attribute>& attributes
- ) const
-{
-
- const XMLCh* cacheID = nullptr;
- if (observable && m_metaAttrCaching && dynamic_cast<const EntityDescriptor*>(ext.getParent())) {
- cacheID = dynamic_cast<const EntityDescriptor*>(ext.getParent())->getEntityID();
- }
-
- const vector<XMLObject*>& exts = ext.getUnknownXMLObjects();
- for (vector<XMLObject*>::const_iterator i = exts.begin(); i != exts.end(); ++i) {
- const EntityAttributes* container = dynamic_cast<const EntityAttributes*>(*i);
- if (!container)
- continue;
-
- map<const ObservableMetadataProvider*,decoded_t>::iterator cacheEntry;
-
- // Check for cached result.
- if (cacheID) {
- m_attrLock->rdlock();
- cacheEntry = m_decodedMap.find(observable);
- if (cacheEntry == m_decodedMap.end()) {
- // We need to elevate the lock and retry.
- m_attrLock->unlock();
- m_attrLock->wrlock();
- cacheEntry = m_decodedMap.find(observable);
- if (cacheEntry == m_decodedMap.end()) {
- SharedLock locker(m_attrLock, false); // guard in case these throw
-
- // It's still brand new, so hook it for cache activation.
- observable->addObserver(this);
-
- // Prime the map reference with an empty decoded map.
- cacheEntry = m_decodedMap.insert(make_pair(observable,decoded_t())).first;
-
- // Downgrade the lock.
- // We don't have to recheck because we never erase the master map entry entirely, even on changes.
- locker.release(); // unguard for lock downgrade
- m_attrLock->unlock();
- m_attrLock->rdlock();
- }
- }
- }
-
- if (cacheID) {
- // We're holding the lock, so check the cache.
- decoded_t::iterator d = cacheEntry->second.find(cacheID);
- if (d != cacheEntry->second.end()) {
- SharedLock locker(m_attrLock, false); // pop the lock when we're done
- for (vector<DDF>::iterator obj = d->second.begin(); obj != d->second.end(); ++obj) {
- auto_ptr<Attribute> wrapper(Attribute::unmarshall(*obj));
- m_log.debug("recovered cached metadata attribute (%s)", wrapper->getId());
- attributes.push_back(wrapper.get());
- wrapper.release();
- }
- break;
- }
- }
-
- // Add a guard for the lock if we're caching.
- SharedLock locker(cacheID ? m_attrLock.get() : nullptr, false);
-
- // Use a holding area to support caching.
- ptr_vector<Attribute> holding;
-
- // Extract attributes into holding area with no asserting party set.
- static void (XMLExtractorImpl::* extractV2Attr)(
- const Application&, const GenericRequest*, const char*, const char*, const saml2::Attribute&, ptr_vector<Attribute>&
- ) const = &XMLExtractorImpl::extractAttributes;
- for_each(
- make_indirect_iterator(container->getAttributes().begin()), make_indirect_iterator(container->getAttributes().end()),
- boost::bind(extractV2Attr, this, boost::ref(application), request, (const char*)nullptr, relyingParty, _1, boost::ref(holding))
- );
-
- if (entityID && m_entityAssertions) {
- const vector<saml2::Assertion*>& asserts = container->getAssertions();
- for (indirect_iterator<vector<saml2::Assertion*>::const_iterator> assert = make_indirect_iterator(asserts.begin());
- assert != make_indirect_iterator(asserts.end()); ++assert) {
- if (!(assert->getSignature())) {
- if (m_log.isDebugEnabled()) {
- auto_ptr_char eid(entityID);
- m_log.debug("skipping unsigned assertion in metadata extension for entity (%s)", eid.get());
- }
- continue;
- }
- else if (assert->getAttributeStatements().empty()) {
- if (m_log.isDebugEnabled()) {
- auto_ptr_char eid(entityID);
- m_log.debug("skipping assertion with no AttributeStatement in metadata extension for entity (%s)", eid.get());
- }
- continue;
- }
- else {
- // Check subject.
- const NameID* subject = assert->getSubject() ? assert->getSubject()->getNameID() : nullptr;
- if (!subject ||
- !XMLString::equals(subject->getFormat(), NameID::ENTITY) ||
- !XMLString::equals(subject->getName(), entityID)) {
- if (m_log.isDebugEnabled()) {
- auto_ptr_char eid(entityID);
- m_log.debug("skipping assertion with improper Subject in metadata extension for entity (%s)", eid.get());
- }
- continue;
- }
- }
-
- try {
- // Set up and evaluate a policy for an AA asserting attributes to us.
- shibsp::SecurityPolicy policy(application, &AttributeAuthorityDescriptor::ELEMENT_QNAME, false, m_policyId.c_str());
- Locker locker(m_metadata.get());
- if (m_metadata)
- policy.setMetadataProvider(m_metadata.get());
- if (m_trust)
- policy.setTrustEngine(m_trust.get());
- // Populate recipient as audience.
- const XMLCh* issuer = assert->getIssuer() ? assert->getIssuer()->getName() : nullptr;
- policy.getAudiences().push_back(application.getRelyingParty(issuer)->getXMLString("entityID").second);
-
- // Extract assertion information for policy.
- policy.setMessageID(assert->getID());
- policy.setIssueInstant(assert->getIssueInstantEpoch());
- policy.setIssuer(assert->getIssuer());
-
- // Look up metadata for issuer.
- if (policy.getIssuer() && policy.getMetadataProvider()) {
- if (policy.getIssuer()->getFormat() && !XMLString::equals(policy.getIssuer()->getFormat(), saml2::NameIDType::ENTITY)) {
- m_log.debug("non-system entity issuer, skipping metadata lookup");
- }
- else {
- m_log.debug("searching metadata for entity assertion issuer...");
- pair<const EntityDescriptor*,const RoleDescriptor*> lookup;
- MetadataProvider::Criteria& mc = policy.getMetadataProviderCriteria();
- mc.entityID_unicode = policy.getIssuer()->getName();
- mc.role = &AttributeAuthorityDescriptor::ELEMENT_QNAME;
- mc.protocol = samlconstants::SAML20P_NS;
- lookup = policy.getMetadataProvider()->getEntityDescriptor(mc);
- if (!lookup.first) {
- auto_ptr_char iname(policy.getIssuer()->getName());
- m_log.debug("no metadata found, can't establish identity of issuer (%s)", iname.get());
- }
- else if (!lookup.second) {
- m_log.debug("unable to find compatible AA role in metadata");
- }
- else {
- policy.setIssuerMetadata(lookup.second);
- }
- }
- }
-
- // Authenticate the assertion. We have to clone and marshall it to establish the signature for verification.
- scoped_ptr<saml2::Assertion> tokencopy(assert->cloneAssertion());
- tokencopy->marshall();
- policy.evaluate(*tokencopy);
- if (!policy.isAuthenticated()) {
- if (m_log.isDebugEnabled()) {
- auto_ptr_char tempid(tokencopy->getID());
- auto_ptr_char eid(entityID);
- m_log.debug(
- "failed to authenticate assertion (%s) in metadata extension for entity (%s)", tempid.get(), eid.get()
- );
- }
- continue;
- }
-
- // Override the asserting/relying party names based on this new issuer.
- const EntityDescriptor* inlineEntity =
- policy.getIssuerMetadata() ? dynamic_cast<const EntityDescriptor*>(policy.getIssuerMetadata()->getParent()) : nullptr;
- auto_ptr_char inlineAssertingParty(inlineEntity ? inlineEntity->getEntityID() : nullptr);
- relyingParty = application.getRelyingParty(inlineEntity)->getString("entityID").second;
-
- // Use a private holding area for filtering purposes.
- ptr_vector<Attribute> holding2;
- const vector<saml2::Attribute*>& attrs2 =
- const_cast<const saml2::AttributeStatement*>(tokencopy->getAttributeStatements().front())->getAttributes();
- for_each(
- make_indirect_iterator(attrs2.begin()), make_indirect_iterator(attrs2.end()),
- boost::bind(extractV2Attr, this, boost::ref(application), request, inlineAssertingParty.get(), relyingParty, _1, boost::ref(holding2))
- );
-
- // Now we locally filter the attributes so that the actual issuer can be properly set.
- // If we relied on outside filtering, the attributes couldn't be distinguished from the
- // ones that come from the user's IdP.
- if (m_filter && !holding2.empty()) {
-
- // The filter API uses an unsafe container, so we have to transfer everything into one and back.
- vector<Attribute*> unsafe_holding2;
-
- // Use a local exception context since the container is unsafe.
- try {
- while (!holding2.empty()) {
- ptr_vector<Attribute>::auto_type ptr = holding2.pop_back();
- unsafe_holding2.push_back(ptr.get());
- ptr.release();
- }
- BasicFilteringContext fc(application, unsafe_holding2, policy.getIssuerMetadata());
- Locker filtlocker(m_filter.get());
- m_filter->filterAttributes(fc, unsafe_holding2);
-
- // Transfer back to safe container
- while (!unsafe_holding2.empty()) {
- auto_ptr<Attribute> ptr(unsafe_holding2.back());
- unsafe_holding2.pop_back();
- holding2.push_back(ptr.get());
- ptr.release();
- }
- }
- 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(unsafe_holding2.begin(), unsafe_holding2.end(), xmltooling::cleanup<Attribute>());
- holding2.clear(); // in case the exception was during transfer between containers
- }
- }
-
- if (!holding2.empty()) {
- // Copy them over to the main holding tank, which transfers ownership.
- holding.transfer(holding.end(), holding2);
- }
- }
- catch (std::exception& ex) {
- // Known exceptions are handled gracefully by skipping the assertion.
- if (m_log.isDebugEnabled()) {
- auto_ptr_char tempid(assert->getID());
- auto_ptr_char eid(entityID);
- m_log.debug(
- "exception authenticating assertion (%s) in metadata extension for entity (%s): %s",
- tempid.get(),
- eid.get(),
- ex.what()
- );
- }
- continue;
- }
- }
- }
-
- if (!holding.empty()) {
- if (cacheID) {
- locker.release(); // unguard to upgrade lock
- m_attrLock->unlock();
- m_attrLock->wrlock();
- SharedLock locker2(m_attrLock, false); // pop the lock when we're done
- if (cacheEntry->second.count(cacheID) == 0) {
- static void (vector<DDF>::* push_back)(DDF const &) = &vector<DDF>::push_back;
- vector<DDF>& marshalled = cacheEntry->second[cacheID];
- for_each(
- holding.begin(), holding.end(),
- boost::bind(push_back, boost::ref(marshalled), boost::bind(&Attribute::marshall, _1))
- );
- }
- }
-
- // Copy them to the output parameter, which transfers ownership.
- attributes.transfer(attributes.end(), holding);
- }
-
- // If the lock is held, it's guarded.
-
- break; // only process a single extension element
- }
-}
-
-void XMLExtractor::extractAttributes(
- const Application& application, const GenericRequest* request, const RoleDescriptor* issuer, const XMLObject& xmlObject, vector<Attribute*>& attributes
- ) const
-{
- if (!m_impl)
- return;
-
- ptr_vector<Attribute> holding;
- extractAttributes(application, request, issuer, xmlObject, holding);
-
- // Transfer ownership from the ptr_vector to the unsafe vector for API compatibility.
- // Any throws should leave each container in a consistent state. The holding container
- // is freed by us, and the result container by the caller.
- while (!holding.empty()) {
- ptr_vector<Attribute>::auto_type ptr = holding.pop_back();
- attributes.push_back(ptr.get());
- ptr.release();
- }
-}
-
-void XMLExtractor::extractAttributes(
- const Application& application, const GenericRequest* request, const RoleDescriptor* issuer, const XMLObject& xmlObject, ptr_vector<Attribute>& attributes
- ) const
-{
- static void (XMLExtractor::* extractEncrypted)(
- const Application&, const GenericRequest*, const RoleDescriptor*, const XMLObject&, ptr_vector<Attribute>&
- ) const = &XMLExtractor::extractAttributes;
- static void (XMLExtractorImpl::* extractV1Statement)(
- const Application&, const GenericRequest*, const char*, const char*, const saml1::AttributeStatement&, ptr_vector<Attribute>&
- ) const = &XMLExtractorImpl::extractAttributes;
-
- const EntityDescriptor* entity = issuer ? dynamic_cast<const EntityDescriptor*>(issuer->getParent()) : nullptr;
- const char* relyingParty = application.getRelyingParty(entity)->getString("entityID").second;
-
- // Check for statements.
- if (XMLString::equals(xmlObject.getElementQName().getLocalPart(), saml1::AttributeStatement::LOCAL_NAME)) {
- const saml2::AttributeStatement* statement2 = dynamic_cast<const saml2::AttributeStatement*>(&xmlObject);
- if (statement2) {
- auto_ptr_char assertingParty(entity ? entity->getEntityID() : nullptr);
- m_impl->extractAttributes(application, request, assertingParty.get(), relyingParty, *statement2, attributes);
- // Handle EncryptedAttributes inline so we have access to the role descriptor.
- const vector<saml2::EncryptedAttribute*>& encattrs = statement2->getEncryptedAttributes();
- for_each(
- make_indirect_iterator(encattrs.begin()), make_indirect_iterator(encattrs.end()),
- boost::bind(extractEncrypted, this, boost::ref(application), request, issuer, _1, boost::ref(attributes))
- );
- return;
- }
-
- const saml1::AttributeStatement* statement1 = dynamic_cast<const saml1::AttributeStatement*>(&xmlObject);
- if (statement1) {
- auto_ptr_char assertingParty(entity ? entity->getEntityID() : nullptr);
- m_impl->extractAttributes(application, request, assertingParty.get(), relyingParty, *statement1, attributes);
- return;
- }
-
- throw AttributeExtractionException("Unable to extract attributes, unknown object type.");
- }
-
- // Check for assertions.
- if (XMLString::equals(xmlObject.getElementQName().getLocalPart(), saml1::Assertion::LOCAL_NAME)) {
- const saml2::Assertion* token2 = dynamic_cast<const saml2::Assertion*>(&xmlObject);
- if (token2) {
- auto_ptr_char assertingParty(entity ? entity->getEntityID() : nullptr);
- const vector<saml2::AttributeStatement*>& statements = token2->getAttributeStatements();
- for (indirect_iterator<vector<saml2::AttributeStatement*>::const_iterator> s = make_indirect_iterator(statements.begin());
- s != make_indirect_iterator(statements.end()); ++s) {
- m_impl->extractAttributes(application, request, assertingParty.get(), relyingParty, *s, attributes);
- // Handle EncryptedAttributes inline so we have access to the role descriptor.
- const vector<saml2::EncryptedAttribute*>& encattrs = const_cast<const saml2::AttributeStatement&>(*s).getEncryptedAttributes();
- for_each(
- make_indirect_iterator(encattrs.begin()), make_indirect_iterator(encattrs.end()),
- boost::bind(extractEncrypted, this, boost::ref(application), request, issuer, _1, boost::ref(attributes))
- );
- }
- return;
- }
-
- const saml1::Assertion* token1 = dynamic_cast<const saml1::Assertion*>(&xmlObject);
- if (token1) {
- auto_ptr_char assertingParty(entity ? entity->getEntityID() : nullptr);
- const vector<saml1::AttributeStatement*>& statements = token1->getAttributeStatements();
- for_each(make_indirect_iterator(statements.begin()), make_indirect_iterator(statements.end()),
- boost::bind(extractV1Statement, m_impl.get(), boost::ref(application), request, assertingParty.get(), relyingParty, _1, boost::ref(attributes))
- );
- return;
- }
-
- throw AttributeExtractionException("Unable to extract attributes, unknown object type.");
- }
-
- // Check for metadata.
- if (XMLString::equals(xmlObject.getElementQName().getNamespaceURI(), samlconstants::SAML20MD_NS)) {
- const RoleDescriptor* roleToExtract = dynamic_cast<const RoleDescriptor*>(&xmlObject);
- const EntityDescriptor* entityToExtract = roleToExtract ? dynamic_cast<const EntityDescriptor*>(roleToExtract->getParent()) : nullptr;
- if (!entityToExtract)
- throw AttributeExtractionException("Unable to extract attributes, unknown metadata object type.");
- const Extensions* ext = entityToExtract->getExtensions();
- if (ext) {
- m_impl->extractAttributes(
- application,
- request,
- dynamic_cast<const ObservableMetadataProvider*>(application.getMetadataProvider(false)),
- entityToExtract->getEntityID(),
- relyingParty,
- *ext,
- attributes
- );
- }
- const EntitiesDescriptor* group = dynamic_cast<const EntitiesDescriptor*>(entityToExtract->getParent());
- while (group) {
- ext = group->getExtensions();
- if (ext) {
- m_impl->extractAttributes(
- application,
- request,
- dynamic_cast<const ObservableMetadataProvider*>(application.getMetadataProvider(false)),
- nullptr, // not an entity, so inline assertions won't be processed
- relyingParty,
- *ext,
- attributes
- );
- }
- group = dynamic_cast<const EntitiesDescriptor*>(group->getParent());
- }
- return;
- }
-
- // Check for attributes.
- if (XMLString::equals(xmlObject.getElementQName().getLocalPart(), saml1::Attribute::LOCAL_NAME)) {
- auto_ptr_char assertingParty(entity ? entity->getEntityID() : nullptr);
- const saml2::Attribute* attr2 = dynamic_cast<const saml2::Attribute*>(&xmlObject);
- if (attr2)
- return m_impl->extractAttributes(application, request, assertingParty.get(), relyingParty, *attr2, attributes);
-
- const saml1::Attribute* attr1 = dynamic_cast<const saml1::Attribute*>(&xmlObject);
- if (attr1)
- return m_impl->extractAttributes(application, request, assertingParty.get(), relyingParty, *attr1, attributes);
-
- throw AttributeExtractionException("Unable to extract attributes, unknown object type.");
- }
-
- if (XMLString::equals(xmlObject.getElementQName().getLocalPart(), EncryptedAttribute::LOCAL_NAME)) {
- const EncryptedAttribute* encattr = dynamic_cast<const EncryptedAttribute*>(&xmlObject);
- if (encattr) {
- const XMLCh* recipient = application.getXMLString("entityID").second;
- CredentialResolver* cr = application.getCredentialResolver();
- if (!cr) {
- m_log.warn("found encrypted attribute, but no CredentialResolver was available");
- return;
- }
-
- try {
- Locker credlocker(cr);
- if (issuer) {
- MetadataCredentialCriteria mcc(*issuer);
- scoped_ptr<XMLObject> decrypted(encattr->decrypt(*cr, recipient, &mcc));
- if (m_log.isDebugEnabled())
- m_log.debugStream() << "decrypted Attribute: " << *decrypted << logging::eol;
- return extractAttributes(application, request, issuer, *decrypted, attributes);
- }
- else {
- scoped_ptr<XMLObject> decrypted(encattr->decrypt(*cr, recipient));
- if (m_log.isDebugEnabled())
- m_log.debugStream() << "decrypted Attribute: " << *decrypted << logging::eol;
- return extractAttributes(application, request, issuer, *decrypted, attributes);
- }
- }
- catch (std::exception& ex) {
- m_log.error("failed to decrypt Attribute: %s", ex.what());
- return;
- }
- }
- }
-
- // Check for NameIDs.
- const NameID* name2 = dynamic_cast<const NameID*>(&xmlObject);
- if (name2) {
- auto_ptr_char assertingParty(entity ? entity->getEntityID() : nullptr);
- return m_impl->extractAttributes(application, assertingParty.get(), relyingParty, *name2, attributes);
- }
-
- const NameIdentifier* name1 = dynamic_cast<const NameIdentifier*>(&xmlObject);
- if (name1) {
- auto_ptr_char assertingParty(entity ? entity->getEntityID() : nullptr);
- return m_impl->extractAttributes(application, assertingParty.get(), relyingParty, *name1, attributes);
- }
-
- m_log.debug("unable to extract attributes, unknown XML object type: %s", xmlObject.getElementQName().toString().c_str());
-}
-
-pair<bool,DOMElement*> XMLExtractor::background_load()
-{
- // Load from source using base class.
- pair<bool,DOMElement*> raw = ReloadableXMLFile::load();
-
- // If we own it, wrap it.
- XercesJanitor<DOMDocument> docjanitor(raw.first ? raw.second->getOwnerDocument() : nullptr);
-
- scoped_ptr<XMLExtractorImpl> impl(new XMLExtractorImpl(raw.second, m_log, m_deprecationSupport));
-
- // If we held the document, transfer it to the impl. If we didn't, it's a no-op.
- impl->setDocument(docjanitor.release());
-
- // Perform the swap inside a lock.
- if (m_lock)
- m_lock->wrlock();
- SharedLock locker(m_lock, false);
- m_impl.swap(impl);
-
- return make_pair(false,(DOMElement*)nullptr);
-}
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list