+/*\r
+ * Copyright 2010 Internet2\r
+ * \r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+/**\r
+ * NameIDQualifierStringFunctor.cpp\r
+ * \r
+ * A match function that ensures that a NameID-valued attribute's qualifier(s)\r
+ * match particular values.\r
+ */\r
+\r
+#include "internal.h"\r
+#include "exceptions.h"\r
+#include "attribute/NameIDAttribute.h"\r
+#include "attribute/filtering/FilteringContext.h"\r
+#include "attribute/filtering/FilterPolicyContext.h"\r
+#include "attribute/filtering/MatchFunctor.h"\r
+\r
+#include <saml/saml2/core/Assertions.h>\r
+#include <xmltooling/util/XMLHelper.h>\r
+\r
+using namespace shibsp;\r
+using namespace xmltooling::logging;\r
+using namespace xmltooling;\r
+using namespace std;\r
+using opensaml::saml2::NameID;\r
+\r
+namespace shibsp {\r
+\r
+ static const XMLCh attributeID[] = UNICODE_LITERAL_11(a,t,t,r,i,b,u,t,e,I,D);\r
+\r
+ /**\r
+ * A match function that ensures that a NameID-valued attribute's qualifier(s)\r
+ * match particular values.\r
+ */\r
+ class SHIBSP_DLLLOCAL NameIDQualifierStringFunctor : public MatchFunctor\r
+ {\r
+ string m_attributeID,m_matchNameQualifier,m_matchSPNameQualifier;\r
+\r
+ bool hasValue(const FilteringContext& filterContext) const;\r
+ bool matches(const FilteringContext& filterContext, const Attribute& attribute, size_t index) const;\r
+\r
+ public:\r
+ NameIDQualifierStringFunctor(const DOMElement* e)\r
+ : m_attributeID(XMLHelper::getAttrString(e, nullptr, attributeID)),\r
+ m_matchNameQualifier(XMLHelper::getAttrString(e, nullptr, NameID::NAMEQUALIFIER_ATTRIB_NAME)),\r
+ m_matchSPNameQualifier(XMLHelper::getAttrString(e, nullptr, NameID::SPNAMEQUALIFIER_ATTRIB_NAME)) {\r
+ }\r
+\r
+ virtual ~NameIDQualifierStringFunctor() {\r
+ }\r
+\r
+ bool evaluatePolicyRequirement(const FilteringContext& filterContext) const {\r
+ if (m_attributeID.empty())\r
+ throw AttributeFilteringException("No attributeID specified.");\r
+ return hasValue(filterContext);\r
+ }\r
+\r
+ bool evaluatePermitValue(const FilteringContext& filterContext, const Attribute& attribute, size_t index) const {\r
+ if (m_attributeID.empty() || m_attributeID == attribute.getId())\r
+ return matches(filterContext, attribute, index);\r
+ return hasValue(filterContext);\r
+ }\r
+ };\r
+\r
+ MatchFunctor* SHIBSP_DLLLOCAL NameIDQualifierStringFactory(const std::pair<const FilterPolicyContext*,const DOMElement*>& p)\r
+ {\r
+ return new NameIDQualifierStringFunctor(p.second);\r
+ }\r
+\r
+};\r
+\r
+bool NameIDQualifierStringFunctor::hasValue(const FilteringContext& filterContext) const\r
+{\r
+ size_t count;\r
+ pair<multimap<string,Attribute*>::const_iterator,multimap<string,Attribute*>::const_iterator> attrs =\r
+ filterContext.getAttributes().equal_range(m_attributeID);\r
+ for (; attrs.first != attrs.second; ++attrs.first) {\r
+ count = attrs.first->second->valueCount();\r
+ for (size_t index = 0; index < count; ++index) {\r
+ if (matches(filterContext, *(attrs.first->second), index))\r
+ return true;\r
+ }\r
+ }\r
+ return false;\r
+}\r
+\r
+bool NameIDQualifierStringFunctor::matches(const FilteringContext& filterContext, const Attribute& attribute, size_t index) const\r
+{\r
+ const NameIDAttribute* nameattr = dynamic_cast<const NameIDAttribute*>(&attribute);\r
+ if (!nameattr) {\r
+ Category::getInstance(SHIBSP_LOGCAT".AttributeFilter").warn(\r
+ "NameIDQualifierString MatchFunctor applied to non-NameID-valued attribute (%s)", attribute.getId()\r
+ );\r
+ return false;\r
+ }\r
+\r
+ const NameIDAttribute::Value& val = nameattr->getValues()[index];\r
+ if (!val.m_NameQualifier.empty()) {\r
+ if (m_matchNameQualifier.empty()) {\r
+ auto_ptr_char issuer(filterContext.getAttributeIssuer());\r
+ if (issuer.get() && *issuer.get()) {\r
+ if (val.m_NameQualifier != issuer.get()) {\r
+ Category::getInstance(SHIBSP_LOGCAT".AttributeFilter").warn(\r
+ "NameIDQualifierString MatchFunctor rejecting NameQualifier (%s), should be (%s)",\r
+ val.m_NameQualifier.c_str(), issuer.get()\r
+ );\r
+ return false;\r
+ }\r
+ }\r
+ else {\r
+ Category::getInstance(SHIBSP_LOGCAT".AttributeFilter").warn(\r
+ "NameIDQualifierString MatchFunctor rejecting NameQualifier (%s), attribute issuer unknown",\r
+ val.m_NameQualifier.c_str()\r
+ );\r
+ return false;\r
+ }\r
+ }\r
+ else if (m_matchNameQualifier != val.m_NameQualifier) {\r
+ Category::getInstance(SHIBSP_LOGCAT".AttributeFilter").warn(\r
+ "NameIDQualifierString MatchFunctor rejecting NameQualifier (%s), should be (%s)",\r
+ val.m_NameQualifier.c_str(), m_matchNameQualifier.c_str()\r
+ );\r
+ return false;\r
+ }\r
+ }\r
+ if (!val.m_SPNameQualifier.empty()) {\r
+ if (m_matchSPNameQualifier.empty()) {\r
+ auto_ptr_char req(filterContext.getAttributeRequester());\r
+ if (req.get() && *req.get()) {\r
+ if (val.m_SPNameQualifier != req.get()) {\r
+ Category::getInstance(SHIBSP_LOGCAT".AttributeFilter").warn(\r
+ "NameIDQualifierString MatchFunctor rejecting SPNameQualifier (%s), should be (%s)",\r
+ val.m_SPNameQualifier.c_str(), req.get()\r
+ );\r
+ return false;\r
+ }\r
+ }\r
+ else {\r
+ Category::getInstance(SHIBSP_LOGCAT".AttributeFilter").warn(\r
+ "NameIDQualifierString MatchFunctor rejecting SPNameQualifier (%s), attribute requester unknown",\r
+ val.m_SPNameQualifier.c_str()\r
+ );\r
+ return false;\r
+ }\r
+ }\r
+ else if (m_matchSPNameQualifier != val.m_SPNameQualifier) {\r
+ Category::getInstance(SHIBSP_LOGCAT".AttributeFilter").warn(\r
+ "NameIDQualifierString MatchFunctor rejecting SPNameQualifier (%s), should be (%s)",\r
+ val.m_SPNameQualifier.c_str(), m_matchSPNameQualifier.c_str()\r
+ );\r
+ return false;\r
+ }\r
+ }\r
+\r
+ return true;\r
+}\r