From: cantor Date: Mon, 7 May 2007 15:57:48 +0000 (+0000) Subject: Boolean match functors, policy context to manage lifetime and references. X-Git-Tag: 2.4~949 X-Git-Url: http://www.project-moonshot.org/gitweb/?a=commitdiff_plain;h=2612dec799334488dd7354abcf4393346f73b82c;p=shibboleth%2Fsp.git Boolean match functors, policy context to manage lifetime and references. git-svn-id: https://svn.middleware.georgetown.edu/cpp-sp/trunk@2233 cb58f699-b61c-0410-a6fe-9272a202ed29 --- diff --git a/shibsp/Makefile.am b/shibsp/Makefile.am index 61b152d..2ad3d3f 100644 --- a/shibsp/Makefile.am +++ b/shibsp/Makefile.am @@ -49,6 +49,7 @@ attrfiltinclude_HEADERS = \ attribute/filtering/AttributeFilter.h \ attribute/filtering/BasicFilteringContext.h \ attribute/filtering/FilteringContext.h \ + attribute/filtering/FilterPolicyContext.h \ attribute/filtering/MatchFunctor.h attrresinclude_HEADERS = \ @@ -100,8 +101,12 @@ libshibsp_la_SOURCES = \ attribute/StringAttributeDecoder.cpp \ attribute/filtering/AttributeFilter.cpp \ attribute/filtering/ChainingAttributeFilter.cpp \ - attribute/filtering/MatchFunctor.cpp \ attribute/filtering/XMLAttributeFilter.cpp \ + attribute/filtering/MatchFunctor.cpp \ + attribute/filtering/AndMatchFunctor.cpp \ + attribute/filtering/AnyMatchFunctor.cpp \ + attribute/filtering/NotMatchFunctor.cpp \ + attribute/filtering/OrMatchFunctor.cpp \ attribute/resolver/impl/ChainingAttributeResolver.cpp \ attribute/resolver/impl/QueryAttributeResolver.cpp \ attribute/resolver/impl/XMLAttributeExtractor.cpp \ diff --git a/shibsp/SPConfig.h b/shibsp/SPConfig.h index 4e62b8c..7de91c5 100644 --- a/shibsp/SPConfig.h +++ b/shibsp/SPConfig.h @@ -39,6 +39,7 @@ namespace shibsp { class SHIBSP_API AttributeExtractor; class SHIBSP_API AttributeFilter; class SHIBSP_API AttributeResolver; + class SHIBSP_API FilterPolicyContext; class SHIBSP_API Handler; class SHIBSP_API ListenerService; class SHIBSP_API MatchFunctor; @@ -208,7 +209,7 @@ namespace shibsp { /** * Manages factories for MatchFunctor plugins. */ - xmltooling::PluginManager MatchFunctorManager; + xmltooling::PluginManager< MatchFunctor,xmltooling::QName,std::pair > MatchFunctorManager; /** * Manages factories for Handler plugins that implement ManageNameIDService functionality. diff --git a/shibsp/attribute/Attribute.h b/shibsp/attribute/Attribute.h index 0b282ad..401749f 100644 --- a/shibsp/attribute/Attribute.h +++ b/shibsp/attribute/Attribute.h @@ -142,6 +142,16 @@ namespace shibsp { virtual void clearSerializedValues()=0; /** + * Removes the value at the specified position (starting from zero). + * + * @param index position of value to remove + */ + virtual void removeValue(size_t index) { + if (index < m_serialized.size()) + m_serialized.erase(m_serialized.begin() + index); + } + + /** * Marshalls an Attribute for remoting. * *

This allows Attribute objects to be communicated across process boundaries diff --git a/shibsp/attribute/NameIDAttribute.h b/shibsp/attribute/NameIDAttribute.h index d2decee..0ba4ab7 100644 --- a/shibsp/attribute/NameIDAttribute.h +++ b/shibsp/attribute/NameIDAttribute.h @@ -116,7 +116,13 @@ namespace shibsp { void clearSerializedValues() { m_serialized.clear(); } - + + void removeValue(size_t index) { + Attribute::removeValue(index); + if (index < m_values.size()) + m_values.erase(m_values.begin() + index); + } + const std::vector& getSerializedValues() const { if (m_serialized.empty()) { for (std::vector::const_iterator i=m_values.begin(); i!=m_values.end(); ++i) { diff --git a/shibsp/attribute/ScopedAttribute.h b/shibsp/attribute/ScopedAttribute.h index 4baab6e..9fb81e2 100644 --- a/shibsp/attribute/ScopedAttribute.h +++ b/shibsp/attribute/ScopedAttribute.h @@ -90,6 +90,12 @@ namespace shibsp { m_serialized.clear(); } + void removeValue(size_t index) { + Attribute::removeValue(index); + if (index < m_values.size()) + m_values.erase(m_values.begin() + index); + } + const std::vector& getSerializedValues() const { if (m_serialized.empty()) { for (std::vector< std::pair >::const_iterator i=m_values.begin(); i!=m_values.end(); ++i) diff --git a/shibsp/attribute/filtering/FilterPolicyContext.h b/shibsp/attribute/filtering/FilterPolicyContext.h new file mode 100644 index 0000000..2fff8ae --- /dev/null +++ b/shibsp/attribute/filtering/FilterPolicyContext.h @@ -0,0 +1,67 @@ +/* + * Copyright 2001-2007 Internet2 + * + * Licensed 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/filtering/FilterPolicyContext.h + * + * Context for lookup of instantiated MatchFunctor objects. + */ + +#ifndef __shibsp_filtpolctx_h__ +#define __shibsp_filtpolctx_h__ + +#include + +#include +#include + +namespace shibsp { + + /** + * Context for lookup of instantiated MatchFunctor objects. + */ + class SHIBSP_API FilterPolicyContext + { + MAKE_NONCOPYABLE(FilterPolicyContext); + public: + /** + * Constructor. + * + * @param functors reference to a map of id/functor pairs + */ + FilterPolicyContext(std::multimap& functors) : m_functors(functors) { + } + + virtual ~FilterPolicyContext() {} + + /** + * Gets a mutable map to store id/functor pairs. + * + *

When storing new instances, use an empty string for unnamed objects. + * + * @return reference to a mutable map containing available MatchFunctors + */ + std::multimap& getMatchFunctors() const { + return m_functors; + } + + private: + std::multimap& m_functors; + }; + +}; + +#endif /* __shibsp_filtpolctx_h__ */ diff --git a/shibsp/attribute/filtering/MatchFunctor.h b/shibsp/attribute/filtering/MatchFunctor.h index 373aa01..db18391 100644 --- a/shibsp/attribute/filtering/MatchFunctor.h +++ b/shibsp/attribute/filtering/MatchFunctor.h @@ -64,6 +64,18 @@ namespace shibsp { virtual bool evaluatePermitValue(const FilteringContext& filterContext, const Attribute& attribute, size_t index) const=0; }; + /** Always evaluates to true. */ + extern SHIBSP_API xmltooling::QName AnyMatchFunctorType; + + /** Conjunction MatchFunctor. */ + extern SHIBSP_API xmltooling::QName AndMatchFunctorType; + + /** Disjunction MatchFunctor. */ + extern SHIBSP_API xmltooling::QName OrMatchFunctorType; + + /** Negating MatchFunctor. */ + extern SHIBSP_API xmltooling::QName NotMatchFunctorType; + /** * Registers MatchFunctor classes into the runtime. */ diff --git a/shibsp/attribute/filtering/impl/AndMatchFunctor.cpp b/shibsp/attribute/filtering/impl/AndMatchFunctor.cpp new file mode 100644 index 0000000..b1645b8 --- /dev/null +++ b/shibsp/attribute/filtering/impl/AndMatchFunctor.cpp @@ -0,0 +1,119 @@ +/* + * Copyright 2001-2007 Internet2 + * + * Licensed 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. + */ + +/** + * AndMatchFunctor.cpp + * + * A MatchFunctor that logical ANDs the results of contained functors. + */ + +#include "internal.h" +#include "exceptions.h" +#include "attribute/filtering/FilterPolicyContext.h" +#include "util/SPConstants.h" + +#include +#include + +using namespace shibsp; +using namespace xmltooling; +using namespace std; + +namespace shibsp { + + /** + * A MatchFunctor that logical ANDs the results of contained functors. + */ + class SHIBSP_DLLLOCAL AndMatchFunctor : public MatchFunctor + { + public: + AndMatchFunctor(const pair& p); + + bool evaluatePolicyRequirement(const FilteringContext& filterContext) const { + if (m_functors.empty()) + return false; + for (vector::const_iterator mf = m_functors.begin(); mf!=m_functors.end(); ++mf) + if (!(*mf)->evaluatePolicyRequirement(filterContext)) + return false; + return true; + } + + bool evaluatePermitValue(const FilteringContext& filterContext, const Attribute& attribute, size_t index) const { + if (m_functors.empty()) + return false; + for (vector::const_iterator mf = m_functors.begin(); mf!=m_functors.end(); ++mf) + if (!(*mf)->evaluatePermitValue(filterContext, attribute, index)) + return false; + return true; + } + + private: + MatchFunctor* buildFunctor(const DOMElement* e, const FilterPolicyContext* functorMap); + + vector m_functors; + }; + + MatchFunctor* SHIBSP_DLLLOCAL AndFunctorFactory(const pair& p) + { + return new AndMatchFunctor(p); + } + + static XMLCh _id[] = UNICODE_LITERAL_2(i,d); + static XMLCh _ref[] = UNICODE_LITERAL_3(r,e,f); + static XMLCh Rule[] = UNICODE_LITERAL_4(R,u,l,e); + static XMLCh RuleReference[] = UNICODE_LITERAL_13(R,u,l,e,R,e,f,e,r,e,n,c,e); +}; + +AndMatchFunctor::AndMatchFunctor(const pair& p) +{ + MatchFunctor* func; + const DOMElement* e = XMLHelper::getFirstChildElement(p.second); + while (e) { + func = NULL; + if (XMLHelper::isNodeNamed(e, shibspconstants::SHIB2ATTRIBUTEFILTER_MF_BASIC_NS, Rule)) { + func = buildFunctor(e, p.first); + } + else if (XMLHelper::isNodeNamed(e, shibspconstants::SHIB2ATTRIBUTEFILTER_MF_BASIC_NS, RuleReference)) { + auto_ptr_char ref(e->getAttributeNS(NULL, _ref)); + if (ref.get() && *ref.get()) { + multimap::const_iterator rule = p.first->getMatchFunctors().find(ref.get()); + func = (rule!=p.first->getMatchFunctors().end()) ? rule->second : NULL; + } + } + + if (func) + m_functors.push_back(func); + + e = XMLHelper::getNextSiblingElement(e); + } +} + +MatchFunctor* AndMatchFunctor::buildFunctor(const DOMElement* e, const FilterPolicyContext* functorMap) +{ + // We'll track and map IDs just for consistency, but don't require them or worry about dups. + auto_ptr_char temp(e->getAttributeNS(NULL,_id)); + const char* id = (temp.get() && *temp.get()) ? temp.get() : ""; + if (*id && functorMap->getMatchFunctors().count(id)) + id = ""; + + auto_ptr type(XMLHelper::getXSIType(e)); + if (!type.get()) + throw ConfigurationException("Child Rule found with no xsi:type."); + + MatchFunctor* func = SPConfig::getConfig().MatchFunctorManager.newPlugin(*type.get(), make_pair(functorMap,e)); + functorMap->getMatchFunctors().insert(make_pair(id, func)); + return func; +} diff --git a/shibsp/attribute/filtering/impl/AnyMatchFunctor.cpp b/shibsp/attribute/filtering/impl/AnyMatchFunctor.cpp new file mode 100644 index 0000000..ac352d8 --- /dev/null +++ b/shibsp/attribute/filtering/impl/AnyMatchFunctor.cpp @@ -0,0 +1,50 @@ +/* + * Copyright 2001-2007 Internet2 + * + * Licensed 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. + */ + +/** + * AnyMatchFunctor.cpp + * + * A match function that returns true to evaluations. + */ + +#include "internal.h" +#include "attribute/filtering/FilterPolicyContext.h" + +using namespace shibsp; + +namespace shibsp { + + /** + * A match function that returns true to evaluations. Note, the result may still be negated. + */ + class SHIBSP_DLLLOCAL AnyMatchFunctor : public MatchFunctor + { + public: + bool evaluatePolicyRequirement(const FilteringContext& filterContext) const { + return true; + } + + bool evaluatePermitValue(const FilteringContext& filterContext, const Attribute& attribute, size_t index) const { + return true; + } + }; + + MatchFunctor* SHIBSP_DLLLOCAL AnyFunctorFactory(const std::pair& p) + { + return new AnyMatchFunctor(); + } + +}; diff --git a/shibsp/attribute/filtering/impl/MatchFunctor.cpp b/shibsp/attribute/filtering/impl/MatchFunctor.cpp index 2f81f89..ce6526e 100644 --- a/shibsp/attribute/filtering/impl/MatchFunctor.cpp +++ b/shibsp/attribute/filtering/impl/MatchFunctor.cpp @@ -22,17 +22,36 @@ #include "internal.h" #include "attribute/filtering/MatchFunctor.h" +#include "util/SPConstants.h" + +#include using namespace shibsp; using namespace xmltooling; using namespace std; namespace shibsp { - //SHIBSP_DLLLOCAL PluginManager::Factory FunctorFactory; + SHIBSP_DLLLOCAL PluginManager< MatchFunctor,QName,pair >::Factory AnyFunctorFactory; + SHIBSP_DLLLOCAL PluginManager< MatchFunctor,QName,pair >::Factory AndFunctorFactory; + SHIBSP_DLLLOCAL PluginManager< MatchFunctor,QName,pair >::Factory OrFunctorFactory; + SHIBSP_DLLLOCAL PluginManager< MatchFunctor,QName,pair >::Factory NotFunctorFactory; + + static const XMLCh ANY[] = UNICODE_LITERAL_3(A,N,Y); + static const XMLCh AND[] = UNICODE_LITERAL_3(A,N,D); + static const XMLCh OR[] = UNICODE_LITERAL_2(O,R); + static const XMLCh NOT[] = UNICODE_LITERAL_3(N,O,T); }; +QName shibsp::AnyMatchFunctorType(shibspconstants::SHIB2ATTRIBUTEFILTER_MF_BASIC_NS, ANY); +QName shibsp::AndMatchFunctorType(shibspconstants::SHIB2ATTRIBUTEFILTER_MF_BASIC_NS, AND); +QName shibsp::OrMatchFunctorType(shibspconstants::SHIB2ATTRIBUTEFILTER_MF_BASIC_NS, OR); +QName shibsp::NotMatchFunctorType(shibspconstants::SHIB2ATTRIBUTEFILTER_MF_BASIC_NS, NOT); + void SHIBSP_API shibsp::registerMatchFunctors() { SPConfig& conf = SPConfig::getConfig(); - //conf.MatchFunctorManager.registerFactory("", FunctorFactory); + conf.MatchFunctorManager.registerFactory(AnyMatchFunctorType, AnyFunctorFactory); + conf.MatchFunctorManager.registerFactory(AndMatchFunctorType, AndFunctorFactory); + conf.MatchFunctorManager.registerFactory(OrMatchFunctorType, OrFunctorFactory); + conf.MatchFunctorManager.registerFactory(NotMatchFunctorType, NotFunctorFactory); } diff --git a/shibsp/attribute/filtering/impl/NotMatchFunctor.cpp b/shibsp/attribute/filtering/impl/NotMatchFunctor.cpp new file mode 100644 index 0000000..6d2797e --- /dev/null +++ b/shibsp/attribute/filtering/impl/NotMatchFunctor.cpp @@ -0,0 +1,109 @@ +/* + * Copyright 2001-2007 Internet2 + * + * Licensed 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. + */ + +/** + * NotMatchFunctor.cpp + * + * A MatchFunctor that negates the result of a contained functor. + */ + +#include "internal.h" +#include "exceptions.h" +#include "attribute/filtering/FilterPolicyContext.h" +#include "util/SPConstants.h" + +#include +#include + +using namespace shibsp; +using namespace xmltooling; +using namespace std; + +namespace shibsp { + + /** + * A MatchFunctor that negates the result of a contained functor. + */ + class SHIBSP_DLLLOCAL NotMatchFunctor : public MatchFunctor + { + public: + NotMatchFunctor(const pair& p); + + bool evaluatePolicyRequirement(const FilteringContext& filterContext) const { + if (m_functor) + return !(m_functor->evaluatePolicyRequirement(filterContext)); + return false; + } + + bool evaluatePermitValue(const FilteringContext& filterContext, const Attribute& attribute, size_t index) const { + if (m_functor) + return !(m_functor->evaluatePermitValue(filterContext, attribute, index)); + return false; + } + + private: + MatchFunctor* buildFunctor(const DOMElement* e, const FilterPolicyContext* functorMap); + + const MatchFunctor* m_functor; + }; + + MatchFunctor* SHIBSP_DLLLOCAL NotFunctorFactory(const pair& p) + { + return new NotMatchFunctor(p); + } + + static XMLCh _id[] = UNICODE_LITERAL_2(i,d); + static XMLCh _ref[] = UNICODE_LITERAL_3(r,e,f); + static XMLCh Rule[] = UNICODE_LITERAL_4(R,u,l,e); + static XMLCh RuleReference[] = UNICODE_LITERAL_13(R,u,l,e,R,e,f,e,r,e,n,c,e); +}; + +NotMatchFunctor::NotMatchFunctor(const pair& p) : m_functor(NULL) +{ + const DOMElement* e = XMLHelper::getFirstChildElement(p.second); + if (e) { + if (XMLHelper::isNodeNamed(e, shibspconstants::SHIB2ATTRIBUTEFILTER_MF_BASIC_NS, Rule)) { + m_functor = buildFunctor(e, p.first); + } + else if (XMLHelper::isNodeNamed(e, shibspconstants::SHIB2ATTRIBUTEFILTER_MF_BASIC_NS, RuleReference)) { + auto_ptr_char ref(e->getAttributeNS(NULL, _ref)); + if (ref.get() && *ref.get()) { + multimap::const_iterator rule = p.first->getMatchFunctors().find(ref.get()); + m_functor = (rule!=p.first->getMatchFunctors().end()) ? rule->second : NULL; + } + } + } + + if (!m_functor) + throw ConfigurationException("No child Rule installed into NotMatchFunctor."); +} + +MatchFunctor* NotMatchFunctor::buildFunctor(const DOMElement* e, const FilterPolicyContext* functorMap) +{ + // We'll track and map IDs just for consistency, but don't require them or worry about dups. + auto_ptr_char temp(e->getAttributeNS(NULL,_id)); + const char* id = (temp.get() && *temp.get()) ? temp.get() : ""; + if (*id && functorMap->getMatchFunctors().count(id)) + id = ""; + + auto_ptr type(XMLHelper::getXSIType(e)); + if (!type.get()) + throw ConfigurationException("Child Rule found with no xsi:type."); + + MatchFunctor* func = SPConfig::getConfig().MatchFunctorManager.newPlugin(*type.get(), make_pair(functorMap,e)); + functorMap->getMatchFunctors().insert(make_pair(id, func)); + return func; +} diff --git a/shibsp/attribute/filtering/impl/OrMatchFunctor.cpp b/shibsp/attribute/filtering/impl/OrMatchFunctor.cpp new file mode 100644 index 0000000..32c6f2a --- /dev/null +++ b/shibsp/attribute/filtering/impl/OrMatchFunctor.cpp @@ -0,0 +1,115 @@ +/* + * Copyright 2001-2007 Internet2 + * + * Licensed 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. + */ + +/** + * OrMatchFunctor.cpp + * + * A MatchFunctor that logical ORs the results of contained functors. + */ + +#include "internal.h" +#include "exceptions.h" +#include "attribute/filtering/FilterPolicyContext.h" +#include "util/SPConstants.h" + +#include +#include + +using namespace shibsp; +using namespace xmltooling; +using namespace std; + +namespace shibsp { + + /** + * A MatchFunctor that logical ORs the results of contained functors. + */ + class SHIBSP_DLLLOCAL OrMatchFunctor : public MatchFunctor + { + public: + OrMatchFunctor(const pair& p); + + bool evaluatePolicyRequirement(const FilteringContext& filterContext) const { + for (vector::const_iterator mf = m_functors.begin(); mf!=m_functors.end(); ++mf) + if ((*mf)->evaluatePolicyRequirement(filterContext)) + return true; + return false; + } + + bool evaluatePermitValue(const FilteringContext& filterContext, const Attribute& attribute, size_t index) const { + for (vector::const_iterator mf = m_functors.begin(); mf!=m_functors.end(); ++mf) + if ((*mf)->evaluatePermitValue(filterContext, attribute, index)) + return true; + return false; + } + + private: + MatchFunctor* buildFunctor(const DOMElement* e, const FilterPolicyContext* functorMap); + + vector m_functors; + }; + + MatchFunctor* SHIBSP_DLLLOCAL OrFunctorFactory(const pair& p) + { + return new OrMatchFunctor(p); + } + + static XMLCh _id[] = UNICODE_LITERAL_2(i,d); + static XMLCh _ref[] = UNICODE_LITERAL_3(r,e,f); + static XMLCh Rule[] = UNICODE_LITERAL_4(R,u,l,e); + static XMLCh RuleReference[] = UNICODE_LITERAL_13(R,u,l,e,R,e,f,e,r,e,n,c,e); +}; + +OrMatchFunctor::OrMatchFunctor(const pair& p) +{ + MatchFunctor* func; + const DOMElement* e = XMLHelper::getFirstChildElement(p.second); + while (e) { + func = NULL; + if (XMLHelper::isNodeNamed(e, shibspconstants::SHIB2ATTRIBUTEFILTER_MF_BASIC_NS, Rule)) { + func = buildFunctor(e, p.first); + } + else if (XMLHelper::isNodeNamed(e, shibspconstants::SHIB2ATTRIBUTEFILTER_MF_BASIC_NS, RuleReference)) { + auto_ptr_char ref(e->getAttributeNS(NULL, _ref)); + if (ref.get() && *ref.get()) { + multimap::const_iterator rule = p.first->getMatchFunctors().find(ref.get()); + func = (rule!=p.first->getMatchFunctors().end()) ? rule->second : NULL; + } + } + + if (func) + m_functors.push_back(func); + + e = XMLHelper::getNextSiblingElement(e); + } +} + +MatchFunctor* OrMatchFunctor::buildFunctor(const DOMElement* e, const FilterPolicyContext* functorMap) +{ + // We'll track and map IDs just for consistency, but don't require them or worry about dups. + auto_ptr_char temp(e->getAttributeNS(NULL,_id)); + const char* id = (temp.get() && *temp.get()) ? temp.get() : ""; + if (*id && functorMap->getMatchFunctors().count(id)) + id = ""; + + auto_ptr type(XMLHelper::getXSIType(e)); + if (!type.get()) + throw ConfigurationException("Child Rule found with no xsi:type."); + + MatchFunctor* func = SPConfig::getConfig().MatchFunctorManager.newPlugin(*type.get(), make_pair(functorMap,e)); + functorMap->getMatchFunctors().insert(make_pair(id, func)); + return func; +} diff --git a/shibsp/attribute/filtering/impl/XMLAttributeFilter.cpp b/shibsp/attribute/filtering/impl/XMLAttributeFilter.cpp index 3b8fe52..8184431 100644 --- a/shibsp/attribute/filtering/impl/XMLAttributeFilter.cpp +++ b/shibsp/attribute/filtering/impl/XMLAttributeFilter.cpp @@ -25,7 +25,7 @@ #include "ServiceProvider.h" #include "attribute/Attribute.h" #include "attribute/filtering/AttributeFilter.h" -#include "attribute/filtering/MatchFunctor.h" +#include "attribute/filtering/FilterPolicyContext.h" #include "util/SPConstants.h" #include @@ -74,9 +74,9 @@ namespace shibsp { private: MatchFunctor* buildFunctor( - const DOMElement* e, multimap& functorMap, const char* logname, bool standalone + const DOMElement* e, const FilterPolicyContext& functorMap, const char* logname, bool standalone ); - pair buildAttributeRule(const DOMElement* e, bool standalone); + pair buildAttributeRule(const DOMElement* e, const FilterPolicyContext& functorMap, bool standalone); Category& m_log; DOMDocument* m_document; @@ -138,22 +138,25 @@ XMLFilterImpl::XMLFilterImpl(const DOMElement* e, Category& log) : m_log(log), m if (!XMLHelper::isNodeNamed(e, shibspconstants::SHIB2ATTRIBUTEFILTER_NS, AttributeFilterPolicyGroup)) throw ConfigurationException("XML AttributeFilter requires afp:AttributeFilterPolicyGroup at root of configuration."); + FilterPolicyContext reqFunctors(m_policyReqRules); + FilterPolicyContext valFunctors(m_permitValRules); + DOMElement* child = XMLHelper::getFirstChildElement(e); while (child) { if (XMLHelper::isNodeNamed(child, shibspconstants::SHIB2ATTRIBUTEFILTER_NS, PolicyRequirementRule)) { - buildFunctor(child, m_policyReqRules, "PolicyRequirementRule", true); + buildFunctor(child, reqFunctors, "PolicyRequirementRule", true); } else if (XMLHelper::isNodeNamed(child, shibspconstants::SHIB2ATTRIBUTEFILTER_NS, PermitValueRule)) { - buildFunctor(child, m_permitValRules, "PermitValueRule", true); + buildFunctor(child, valFunctors, "PermitValueRule", true); } else if (XMLHelper::isNodeNamed(child, shibspconstants::SHIB2ATTRIBUTEFILTER_NS, AttributeRule)) { - buildAttributeRule(child, true); + buildAttributeRule(child, valFunctors, true); } else if (XMLHelper::isNodeNamed(child, shibspconstants::SHIB2ATTRIBUTEFILTER_NS, AttributeFilterPolicy)) { e = XMLHelper::getFirstChildElement(child); - MatchFunctor* func; + MatchFunctor* func = NULL; if (e && XMLHelper::isNodeNamed(e, shibspconstants::SHIB2ATTRIBUTEFILTER_NS, PolicyRequirementRule)) { - func = buildFunctor(e, m_policyReqRules, "PolicyRequirementRule", false); + func = buildFunctor(e, reqFunctors, "PolicyRequirementRule", false); } else if (e && XMLHelper::isNodeNamed(e, shibspconstants::SHIB2ATTRIBUTEFILTER_NS, PolicyRequirementRuleReference)) { auto_ptr_char ref(e->getAttributeNS(NULL, _ref)); @@ -168,7 +171,7 @@ XMLFilterImpl::XMLFilterImpl(const DOMElement* e, Category& log) : m_log(log), m e = XMLHelper::getNextSiblingElement(e); while (e) { if (e && XMLHelper::isNodeNamed(e, shibspconstants::SHIB2ATTRIBUTEFILTER_NS, AttributeRule)) { - pair rule = buildAttributeRule(e, false); + pair rule = buildAttributeRule(e, valFunctors, false); if (rule.second) m_policies.back().m_rules.insert(rule); } @@ -194,7 +197,7 @@ XMLFilterImpl::XMLFilterImpl(const DOMElement* e, Category& log) : m_log(log), m } MatchFunctor* XMLFilterImpl::buildFunctor( - const DOMElement* e, multimap& functorMap, const char* logname, bool standalone + const DOMElement* e, const FilterPolicyContext& functorMap, const char* logname, bool standalone ) { auto_ptr_char temp(e->getAttributeNS(NULL,_id)); @@ -204,7 +207,7 @@ MatchFunctor* XMLFilterImpl::buildFunctor( m_log.warn("skipping stand-alone %s with no id", logname); return NULL; } - else if (*id && functorMap.count(id)) { + else if (*id && functorMap.getMatchFunctors().count(id)) { if (standalone) { m_log.warn("skipping duplicate stand-alone %s with id (%s)", logname, id); return NULL; @@ -216,8 +219,8 @@ MatchFunctor* XMLFilterImpl::buildFunctor( auto_ptr type(XMLHelper::getXSIType(e)); if (type.get()) { try { - MatchFunctor* func = SPConfig::getConfig().MatchFunctorManager.newPlugin(*type.get(), e); - functorMap.insert(make_pair(id, func)); + MatchFunctor* func = SPConfig::getConfig().MatchFunctorManager.newPlugin(*type.get(), make_pair(&functorMap,e)); + functorMap.getMatchFunctors().insert(make_pair(id, func)); return func; } catch (exception& ex) { @@ -232,7 +235,7 @@ MatchFunctor* XMLFilterImpl::buildFunctor( return NULL; } -pair XMLFilterImpl::buildAttributeRule(const DOMElement* e, bool standalone) +pair XMLFilterImpl::buildAttributeRule(const DOMElement* e, const FilterPolicyContext& functorMap, bool standalone) { auto_ptr_char temp(e->getAttributeNS(NULL,_id)); const char* id = (temp.get() && *temp.get()) ? temp.get() : ""; @@ -257,7 +260,7 @@ pair XMLFilterImpl::buildAttributeRule(const DOMElem e = XMLHelper::getFirstChildElement(e); MatchFunctor* func=NULL; if (e && XMLHelper::isNodeNamed(e, shibspconstants::SHIB2ATTRIBUTEFILTER_NS, PermitValueRule)) { - func = buildFunctor(e, m_permitValRules, "PermitValueRule", false); + func = buildFunctor(e, functorMap, "PermitValueRule", false); } else if (e && XMLHelper::isNodeNamed(e, shibspconstants::SHIB2ATTRIBUTEFILTER_NS, PermitValueRuleReference)) { auto_ptr_char ref(e->getAttributeNS(NULL, _ref)); @@ -280,16 +283,16 @@ pair XMLFilterImpl::buildAttributeRule(const DOMElem void XMLFilterImpl::filterAttributes(const FilteringContext& context, multimap& attributes) const { - auto_ptr_char issuer(context.getAttributeIssuer()); - - m_log.debug("filtering %lu attribute(s) from (%s)", attributes.size(), issuer.get() ? issuer.get() : "unknown source"); - - if (m_policies.empty()) { - m_log.warn("no filter policies were loaded, filtering out all attributes from (%s)", issuer.get() ? issuer.get() : "unknown source"); - for_each(attributes.begin(), attributes.end(), cleanup_pair()); - attributes.clear(); - return; - } + auto_ptr_char issuer(context.getAttributeIssuer()); + + m_log.debug("filtering %lu attribute(s) from (%s)", attributes.size(), issuer.get() ? issuer.get() : "unknown source"); + + if (m_policies.empty()) { + m_log.warn("no filter policies were loaded, filtering out all attributes from (%s)", issuer.get() ? issuer.get() : "unknown source"); + for_each(attributes.begin(), attributes.end(), cleanup_pair()); + attributes.clear(); + return; + } size_t count,index; @@ -301,24 +304,31 @@ void XMLFilterImpl::filterAttributes(const FilteringContext& context, multimap rules = p->m_rules.equal_range(a->second->getId()); if (rules.first == rules.second) { // No rule found, so we're filtering it out. - m_log.warn( - "no rule found, filtering out values of attribute (%s) from (%s)", a->second->getId(), issuer.get() ? issuer.get() : "unknown source" - ); - multimap::iterator dead = a++; - delete dead->second; - attributes.erase(dead); + m_log.warn( + "no rule found, filtering out values of attribute (%s) from (%s)", a->second->getId(), issuer.get() ? issuer.get() : "unknown source" + ); + multimap::iterator dead = a++; + delete dead->second; + attributes.erase(dead); } else { // Run each rule in sequence. - m_log.debug("filtering values of attribute (%s) from (%s)", a->second->getId(), issuer.get() ? issuer.get() : "unknown source"); + m_log.debug("filtering values of attribute (%s) from (%s)", a->second->getId(), issuer.get() ? issuer.get() : "unknown source"); for (; rules.first!=rules.second; ++rules.first) { count = a->second->valueCount(); for (index=0; index < count;) { // The return value tells us whether to index past the accepted value, or stay put and decrement the count. - if (rules.first->second->evaluatePermitValue(context, *(a->second), index)) + if (rules.first->second->evaluatePermitValue(context, *(a->second), index)) { index++; - else + } + else { + m_log.warn( + "filtered value at position (%lu) of attribute (%s) from (%s)", + index, a->second->getId(), issuer.get() ? issuer.get() : "unknown source" + ); + a->second->removeValue(index); count--; + } } } // See if any values are left, delete if not. @@ -326,9 +336,9 @@ void XMLFilterImpl::filterAttributes(const FilteringContext& context, multimap::iterator dead = a++; - delete dead->second; - attributes.erase(dead); + multimap::iterator dead = a++; + delete dead->second; + attributes.erase(dead); } } } diff --git a/shibsp/shibsp.vcproj b/shibsp/shibsp.vcproj index 74398a7..f551daf 100644 --- a/shibsp/shibsp.vcproj +++ b/shibsp/shibsp.vcproj @@ -187,6 +187,14 @@ > + + + + @@ -203,6 +211,14 @@ > + + + + @@ -457,6 +473,10 @@ > + + diff --git a/shibsp/util/SPConstants.cpp b/shibsp/util/SPConstants.cpp index 890e6b0..48d991c 100644 --- a/shibsp/util/SPConstants.cpp +++ b/shibsp/util/SPConstants.cpp @@ -62,6 +62,20 @@ const XMLCh shibspconstants::SHIB2ATTRIBUTEFILTER_NS[] = // urn:mace:shibboleth: chDigit_2, chPeriod, chDigit_0, chColon, chLatin_a, chLatin_f, chLatin_p, chNull }; +const XMLCh shibspconstants::SHIB2ATTRIBUTEFILTER_MF_BASIC_NS[] = // urn:mace:shibboleth:2.0:afp:mf:basic +{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon, + chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon, + chDigit_2, chPeriod, chDigit_0, chColon, chLatin_a, chLatin_f, chLatin_p, chColon, chLatin_m, chLatin_f, chColon, + chLatin_b, chLatin_a, chLatin_s, chLatin_i, chLatin_c, chNull +}; + +const XMLCh shibspconstants::SHIB2ATTRIBUTEFILTER_MF_SAML_NS[] = // urn:mace:shibboleth:2.0:afp:mf:saml +{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon, + chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon, + chDigit_2, chPeriod, chDigit_0, chColon, chLatin_a, chLatin_f, chLatin_p, chColon, chLatin_m, chLatin_f, chColon, + chLatin_s, chLatin_a, chLatin_m, chLatin_l, chNull +}; + const XMLCh shibspconstants::SHIB1_ATTRIBUTE_NAMESPACE_URI[] = // urn:mace:shibboleth:1.0:attributeNamespace:uri { chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon, chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon, diff --git a/shibsp/util/SPConstants.h b/shibsp/util/SPConstants.h index 00cd146..be5eda2 100644 --- a/shibsp/util/SPConstants.h +++ b/shibsp/util/SPConstants.h @@ -46,6 +46,12 @@ namespace shibspconstants { /** Shibboleth 2.0 attribute filter policy namespace ("urn:mace:shibboleth:2.0:afp") */ extern SHIBSP_API const XMLCh SHIB2ATTRIBUTEFILTER_NS[]; + /** Shibboleth 2.0 basic matching function namespace ("urn:mace:shibboleth:2.0:afp:mf:basic") */ + extern SHIBSP_API const XMLCh SHIB2ATTRIBUTEFILTER_MF_BASIC_NS[]; + + /** Shibboleth 2.0 SAML matching function namespace ("urn:mace:shibboleth:2.0:afp:mf:saml") */ + extern SHIBSP_API const XMLCh SHIB2ATTRIBUTEFILTER_MF_SAML_NS[]; + /** Shibboleth 1.x Protocol Enumeration constant ("urn:mace:shibboleth:1.0") */ extern SHIBSP_API const XMLCh SHIB1_PROTOCOL_ENUM[];