X-Git-Url: http://www.project-moonshot.org/gitweb/?p=shibboleth%2Fcpp-sp.git;a=blobdiff_plain;f=shibsp%2Fattribute%2Ffiltering%2Fimpl%2FXMLAttributeFilter.cpp;h=ede31950307008491e1f2392314bfc74efd7464c;hp=67abf9b5ec3186ad5cab55e471a534917774fe04;hb=f0cab28136e0758f7bf7c60581d714f5f5dbbf08;hpb=f30f2eccedeba087846b23bee6bc9e214ee19e54 diff --git a/shibsp/attribute/filtering/impl/XMLAttributeFilter.cpp b/shibsp/attribute/filtering/impl/XMLAttributeFilter.cpp index 67abf9b..ede3195 100644 --- a/shibsp/attribute/filtering/impl/XMLAttributeFilter.cpp +++ b/shibsp/attribute/filtering/impl/XMLAttributeFilter.cpp @@ -1,17 +1,21 @@ -/* - * Copyright 2001-2009 Internet2 +/** + * 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. * - * 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 + * 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 + * 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. + * 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. */ /** @@ -31,8 +35,11 @@ #include "attribute/filtering/MatchFunctor.h" #include "util/SPConstants.h" +#include +#include #include #include +#include #include #include @@ -41,6 +48,7 @@ using namespace shibsp; using namespace opensaml::saml2md; using namespace opensaml; using namespace xmltooling; +using namespace boost; using namespace std; namespace shibsp { @@ -51,10 +59,10 @@ namespace shibsp { #endif // Each Policy has a functor for determining applicability and a map of - // attribute IDs to Accept/Deny functor pairs (which can include NULLs). + // attribute IDs to Accept/Deny functor pairs (which can include nullptrs). struct SHIBSP_DLLLOCAL Policy { - Policy() : m_applies(NULL) {} + Policy() : m_applies(nullptr) {} const MatchFunctor* m_applies; typedef multimap< string,pair > rules_t; rules_t m_rules; @@ -82,14 +90,14 @@ namespace shibsp { MatchFunctor* buildFunctor( const DOMElement* e, const FilterPolicyContext& functorMap, const char* logname, bool standalone ); - pair< string,pair > buildAttributeRule( + boost::tuple buildAttributeRule( const DOMElement* e, const FilterPolicyContext& permMap, const FilterPolicyContext& denyMap, bool standalone ); Category& m_log; DOMDocument* m_document; vector m_policies; - map< string,pair > > m_attrRules; + map< string,boost::tuple > m_attrRules; multimap m_policyReqRules; multimap m_permitValRules; multimap m_denyValRules; @@ -98,11 +106,11 @@ namespace shibsp { class SHIBSP_DLLLOCAL XMLFilter : public AttributeFilter, public ReloadableXMLFile { public: - XMLFilter(const DOMElement* e) : ReloadableXMLFile(e, Category::getInstance(SHIBSP_LOGCAT".AttributeFilter")), m_impl(NULL) { - load(); + XMLFilter(const DOMElement* e) : ReloadableXMLFile(e, Category::getInstance(SHIBSP_LOGCAT ".AttributeFilter")) { + background_load(); } ~XMLFilter() { - delete m_impl; + shutdown(); } void filterAttributes(const FilteringContext& context, vector& attributes) const { @@ -110,10 +118,10 @@ namespace shibsp { } protected: - pair load(); + pair background_load(); private: - XMLFilterImpl* m_impl; + scoped_ptr m_impl; }; #if defined (_MSC_VER) @@ -140,7 +148,7 @@ namespace shibsp { static const XMLCh _ref[] = UNICODE_LITERAL_3(r,e,f); }; -XMLFilterImpl::XMLFilterImpl(const DOMElement* e, Category& log) : m_log(log), m_document(NULL) +XMLFilterImpl::XMLFilterImpl(const DOMElement* e, Category& log) : m_log(log), m_document(nullptr) { #ifdef _DEBUG xmltooling::NDC ndc("XMLFilterImpl"); @@ -169,15 +177,15 @@ XMLFilterImpl::XMLFilterImpl(const DOMElement* e, Category& log) : m_log(log), m } else if (XMLHelper::isNodeNamed(child, SHIB2ATTRIBUTEFILTER_NS, AttributeFilterPolicy)) { e = XMLHelper::getFirstChildElement(child); - MatchFunctor* func = NULL; + MatchFunctor* func = nullptr; if (e && XMLHelper::isNodeNamed(e, SHIB2ATTRIBUTEFILTER_NS, PolicyRequirementRule)) { func = buildFunctor(e, reqFunctors, "PolicyRequirementRule", false); } else if (e && XMLHelper::isNodeNamed(e, SHIB2ATTRIBUTEFILTER_NS, PolicyRequirementRuleReference)) { - auto_ptr_char ref(e->getAttributeNS(NULL, _ref)); - if (ref.get() && *ref.get()) { - multimap::const_iterator prr = m_policyReqRules.find(ref.get()); - func = (prr!=m_policyReqRules.end()) ? prr->second : NULL; + string ref(XMLHelper::getAttrString(e, nullptr, _ref)); + if (!ref.empty()) { + multimap::const_iterator prr = m_policyReqRules.find(ref); + func = (prr!=m_policyReqRules.end()) ? prr->second : nullptr; } } if (func) { @@ -186,18 +194,22 @@ XMLFilterImpl::XMLFilterImpl(const DOMElement* e, Category& log) : m_log(log), m e = XMLHelper::getNextSiblingElement(e); while (e) { if (e && XMLHelper::isNodeNamed(e, SHIB2ATTRIBUTEFILTER_NS, AttributeRule)) { - pair< string,pair > rule = buildAttributeRule(e, permFunctors, denyFunctors, false); - if (rule.second.first || rule.second.second) - m_policies.back().m_rules.insert(Policy::rules_t::value_type(rule.first, rule.second)); + boost::tuple rule = buildAttributeRule(e, permFunctors, denyFunctors, false); + if (rule.get<1>() || rule.get<2>()) + m_policies.back().m_rules.insert(Policy::rules_t::value_type(rule.get<0>(), make_pair(rule.get<1>(), rule.get<2>()))); } else if (e && XMLHelper::isNodeNamed(e, SHIB2ATTRIBUTEFILTER_NS, AttributeRuleReference)) { - auto_ptr_char ref(e->getAttributeNS(NULL, _ref)); - if (ref.get() && *ref.get()) { - map< string,pair< string,pair< const MatchFunctor*,const MatchFunctor*> > >::const_iterator ar = m_attrRules.find(ref.get()); - if (ar != m_attrRules.end()) - m_policies.back().m_rules.insert(Policy::rules_t::value_type(ar->second.first, ar->second.second)); - else - m_log.warn("skipping invalid AttributeRuleReference (%s)", ref.get()); + string ref(XMLHelper::getAttrString(e, nullptr, _ref)); + if (!ref.empty()) { + map< string,boost::tuple >::const_iterator ar = m_attrRules.find(ref); + if (ar != m_attrRules.end()) { + m_policies.back().m_rules.insert( + Policy::rules_t::value_type(ar->second.get<0>(), make_pair(ar->second.get<1>(), ar->second.get<2>())) + ); + } + else { + m_log.warn("skipping invalid AttributeRuleReference (%s)", ref.c_str()); + } } } e = XMLHelper::getNextSiblingElement(e); @@ -215,28 +227,27 @@ MatchFunctor* XMLFilterImpl::buildFunctor( const DOMElement* e, const FilterPolicyContext& functorMap, const char* logname, bool standalone ) { - auto_ptr_char temp(e->getAttributeNS(NULL,_id)); - const char* id = (temp.get() && *temp.get()) ? temp.get() : ""; + string id(XMLHelper::getAttrString(e, nullptr, _id)); - if (standalone && !*id) { + if (standalone && id.empty()) { m_log.warn("skipping stand-alone %s with no id", logname); - return NULL; + return nullptr; } - else if (*id && functorMap.getMatchFunctors().count(id)) { + else if (!id.empty() && functorMap.getMatchFunctors().count(id)) { if (standalone) { - m_log.warn("skipping duplicate stand-alone %s with id (%s)", logname, id); - return NULL; + m_log.warn("skipping duplicate stand-alone %s with id (%s)", logname, id.c_str()); + return nullptr; } else - id = ""; + id.clear(); } - auto_ptr type(XMLHelper::getXSIType(e)); - if (type.get()) { + scoped_ptr type(XMLHelper::getXSIType(e)); + if (type) { try { - MatchFunctor* func = SPConfig::getConfig().MatchFunctorManager.newPlugin(*type.get(), make_pair(&functorMap,e)); - functorMap.getMatchFunctors().insert(multimap::value_type(id, func)); - return func; + auto_ptr func(SPConfig::getConfig().MatchFunctorManager.newPlugin(*type, make_pair(&functorMap,e))); + functorMap.getMatchFunctors().insert(multimap::value_type(id, func.get())); + return func.release(); } catch (exception& ex) { m_log.error("error building %s with type (%s): %s", logname, type->toString().c_str(), ex.what()); @@ -247,35 +258,34 @@ MatchFunctor* XMLFilterImpl::buildFunctor( else m_log.error("%s with no xsi:type", logname); - return NULL; + return nullptr; } -pair< string,pair > XMLFilterImpl::buildAttributeRule( +boost::tuple XMLFilterImpl::buildAttributeRule( const DOMElement* e, const FilterPolicyContext& permMap, const FilterPolicyContext& denyMap, bool standalone ) { - auto_ptr_char temp(e->getAttributeNS(NULL,_id)); - const char* id = (temp.get() && *temp.get()) ? temp.get() : ""; + string id(XMLHelper::getAttrString(e, nullptr, _id)); - if (standalone && !*id) { + if (standalone && id.empty()) { m_log.warn("skipping stand-alone AttributeRule with no id"); - return make_pair(string(),pair(NULL,NULL)); + return boost::tuple(string(),nullptr,nullptr); } - else if (*id && m_attrRules.count(id)) { + else if (!id.empty() && m_attrRules.count(id)) { if (standalone) { - m_log.warn("skipping duplicate stand-alone AttributeRule with id (%s)", id); - return make_pair(string(),pair(NULL,NULL)); + m_log.warn("skipping duplicate stand-alone AttributeRule with id (%s)", id.c_str()); + return boost::tuple(string(),nullptr,nullptr); } else - id = ""; + id.clear(); } - auto_ptr_char attrID(e->getAttributeNS(NULL,attributeID)); - if (!attrID.get() || !*attrID.get()) + string attrID(XMLHelper::getAttrString(e, nullptr, attributeID)); + if (attrID.empty()) m_log.warn("skipping AttributeRule with no attributeID"); - MatchFunctor* perm=NULL; - MatchFunctor* deny=NULL; + MatchFunctor* perm = nullptr; + MatchFunctor* deny = nullptr; e = XMLHelper::getFirstChildElement(e); if (e && XMLHelper::isNodeNamed(e, SHIB2ATTRIBUTEFILTER_NS, PermitValueRule)) { @@ -283,10 +293,10 @@ pair< string,pair > XMLFilterImpl::buil e = XMLHelper::getNextSiblingElement(e); } else if (e && XMLHelper::isNodeNamed(e, SHIB2ATTRIBUTEFILTER_NS, PermitValueRuleReference)) { - auto_ptr_char ref(e->getAttributeNS(NULL, _ref)); - if (ref.get() && *ref.get()) { - multimap::const_iterator pvr = m_permitValRules.find(ref.get()); - perm = (pvr!=m_permitValRules.end()) ? pvr->second : NULL; + string ref(XMLHelper::getAttrString(e, nullptr, _ref)); + if (!ref.empty()) { + multimap::const_iterator pvr = m_permitValRules.find(ref); + perm = (pvr!=m_permitValRules.end()) ? pvr->second : nullptr; } e = XMLHelper::getNextSiblingElement(e); } @@ -295,28 +305,28 @@ pair< string,pair > XMLFilterImpl::buil deny = buildFunctor(e, denyMap, "DenyValueRule", false); } else if (e && XMLHelper::isNodeNamed(e, SHIB2ATTRIBUTEFILTER_NS, DenyValueRuleReference)) { - auto_ptr_char ref(e->getAttributeNS(NULL, _ref)); - if (ref.get() && *ref.get()) { - multimap::const_iterator pvr = m_denyValRules.find(ref.get()); - deny = (pvr!=m_denyValRules.end()) ? pvr->second : NULL; + string ref(XMLHelper::getAttrString(e, nullptr, _ref)); + if (!ref.empty()) { + multimap::const_iterator pvr = m_denyValRules.find(ref); + deny = (pvr!=m_denyValRules.end()) ? pvr->second : nullptr; } } if (perm || deny) { - if (*id) { - m_attrRules[id] = pair< string,pair >(attrID.get(), pair(perm,deny)); + if (!id.empty()) { + m_attrRules[id] = boost::make_tuple(attrID, perm, deny); return m_attrRules[id]; } else { - return pair< string,pair >(attrID.get(), pair(perm,deny)); + return boost::make_tuple(attrID, perm, deny); } } - if (*id) - m_log.warn("skipping AttributeRule (%s), permit and denial rule(s) invalid or missing", id); + if (!id.empty()) + m_log.warn("skipping AttributeRule (%s), permit and denial rule(s) invalid or missing", id.c_str()); else m_log.warn("skipping AttributeRule, permit and denial rule(s) invalid or missing"); - return pair< string,pair >(string(),pair(NULL,NULL)); + return boost::tuple(string(),nullptr,nullptr); } void XMLFilterImpl::filterAttributes(const FilteringContext& context, vector& attributes) const @@ -336,7 +346,7 @@ void XMLFilterImpl::filterAttributes(const FilteringContext& context, vector applicablePolicies; - for (vector::const_iterator p=m_policies.begin(); p!=m_policies.end(); ++p) { + for (vector::const_iterator p = m_policies.begin(); p != m_policies.end(); ++p) { if (p->m_applies->evaluatePolicyRequirement(context)) applicablePolicies.push_back(&(*p)); } @@ -346,8 +356,9 @@ void XMLFilterImpl::filterAttributes(const FilteringContext& context, vector > wildcardRules; // Store off the wildcards ahead of time. - for (vector::const_iterator pol=applicablePolicies.begin(); pol!=applicablePolicies.end(); ++pol) { - pair rules = (*pol)->m_rules.equal_range("*"); + for (indirect_iterator::const_iterator> pol = make_indirect_iterator(applicablePolicies.begin()); + pol != make_indirect_iterator(applicablePolicies.end()); ++pol) { + pair rules = pol->m_rules.equal_range("*"); for (; rules.first!=rules.second; ++rules.first) wildcardRules.push_back(rules.first->second); } @@ -359,26 +370,28 @@ void XMLFilterImpl::filterAttributes(const FilteringContext& context, vector > deletedPositions; // Loop over each attribute to filter them. - for (vector::size_type a=0; a::size_type a = 0; a < attributes.size(); ++a) { Attribute* attr = attributes[a]; // Clear the rule store. applicableRules.clear(); // Look for rules to run in each policy. - for (vector::const_iterator pol=applicablePolicies.begin(); pol!=applicablePolicies.end(); ++pol) { - pair rules = (*pol)->m_rules.equal_range(attr->getId()); + for (indirect_iterator::const_iterator> pol = make_indirect_iterator(applicablePolicies.begin()); + pol != make_indirect_iterator(applicablePolicies.end()); ++pol) { + pair rules = pol->m_rules.equal_range(attr->getId()); for (; rules.first!=rules.second; ++rules.first) applicableRules.push_back(rules.first->second); } // If no rules found, apply wildcards. - const vector< pair >& rulesToRun = applicableRules.empty() ? wildcardRules : applicableRules; + const vector< pair >& rulesToRun = + applicableRules.empty() ? wildcardRules : applicableRules; // If no rules apply, remove the attribute entirely. if (rulesToRun.empty()) { m_log.warn( - "no rule found, removing attribute (%s) from (%s)", + "no rule found, will remove attribute (%s) from (%s)", attr->getId(), issuer.get() ? issuer.get() : "unknown source" ); deletedAttributes[a] = true; @@ -399,7 +412,7 @@ void XMLFilterImpl::filterAttributes(const FilteringContext& context, vector >::const_iterator r=rulesToRun.begin(); r!=rulesToRun.end(); ++r) { + for (vector< pair >::const_iterator r = rulesToRun.begin(); r != rulesToRun.end(); ++r) { // If there's a permit rule that passes, don't kick it. if (r->first && r->first->evaluatePermitValue(context, *attr, index)) kickit = false; @@ -421,10 +434,14 @@ void XMLFilterImpl::filterAttributes(const FilteringContext& context, vector::size_type a=0; a::size_type a = 0; a < attributes.size();) { Attribute* attr = attributes[a]; if (deletedAttributes[a]) { + m_log.warn( + "removing filtered attribute (%s) from (%s)", + attr->getId(), issuer.get() ? issuer.get() : "unknown source" + ); delete attr; deletedAttributes.erase(deletedAttributes.begin() + a); attributes.erase(attributes.begin() + a); @@ -448,6 +465,7 @@ void XMLFilterImpl::filterAttributes(const FilteringContext& context, vectorgetId(), issuer.get() ? issuer.get() : "unknown source" ); delete attr; + deletedAttributes.erase(deletedAttributes.begin() + a); attributes.erase(attributes.begin() + a); continue; } @@ -456,21 +474,24 @@ void XMLFilterImpl::filterAttributes(const FilteringContext& context, vector XMLFilter::load() +pair XMLFilter::background_load() { // Load from source using base class. pair raw = ReloadableXMLFile::load(); // If we own it, wrap it. - XercesJanitor docjanitor(raw.first ? raw.second->getOwnerDocument() : NULL); + XercesJanitor docjanitor(raw.first ? raw.second->getOwnerDocument() : nullptr); - XMLFilterImpl* impl = new XMLFilterImpl(raw.second, m_log); + scoped_ptr impl(new XMLFilterImpl(raw.second, m_log)); // If we held the document, transfer it to the impl. If we didn't, it's a no-op. impl->setDocument(docjanitor.release()); - delete m_impl; - m_impl = impl; + // 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*)NULL); + return make_pair(false,(DOMElement*)nullptr); }