Change license header.
[shibboleth/cpp-sp.git] / shibsp / attribute / filtering / impl / NameIDQualifierStringFunctor.cpp
1 /**
2  * Licensed to the University Corporation for Advanced Internet
3  * Development, Inc. (UCAID) under one or more contributor license
4  * agreements. See the NOTICE file distributed with this work for
5  * additional information regarding copyright ownership.
6  *
7  * UCAID licenses this file to you under the Apache License,
8  * Version 2.0 (the "License"); you may not use this file except
9  * in compliance with the License. You may obtain a copy of the
10  * License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing,
15  * software distributed under the License is distributed on an
16  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
17  * either express or implied. See the License for the specific
18  * language governing permissions and limitations under the License.
19  */\r
20 \r
21 /**\r
22  * NameIDQualifierStringFunctor.cpp\r
23  * \r
24  * A match function that ensures that a NameID-valued attribute's qualifier(s)\r
25  * match particular values.\r
26  */\r
27 \r
28 #include "internal.h"\r
29 #include "exceptions.h"\r
30 #include "attribute/NameIDAttribute.h"\r
31 #include "attribute/filtering/FilteringContext.h"\r
32 #include "attribute/filtering/FilterPolicyContext.h"\r
33 #include "attribute/filtering/MatchFunctor.h"\r
34 \r
35 #include <saml/saml2/core/Assertions.h>\r
36 #include <xmltooling/util/XMLHelper.h>\r
37 \r
38 using namespace shibsp;\r
39 using namespace xmltooling::logging;\r
40 using namespace xmltooling;\r
41 using namespace std;\r
42 using opensaml::saml2::NameID;\r
43 \r
44 namespace shibsp {\r
45 \r
46     static const XMLCh attributeID[] =  UNICODE_LITERAL_11(a,t,t,r,i,b,u,t,e,I,D);\r
47 \r
48     /**\r
49      * A match function that ensures that a NameID-valued attribute's qualifier(s)\r
50      * match particular values.\r
51      */\r
52     class SHIBSP_DLLLOCAL NameIDQualifierStringFunctor : public MatchFunctor\r
53     {\r
54         string m_attributeID,m_matchNameQualifier,m_matchSPNameQualifier;\r
55 \r
56         bool hasValue(const FilteringContext& filterContext) const;\r
57         bool matches(const FilteringContext& filterContext, const Attribute& attribute, size_t index) const;\r
58 \r
59     public:\r
60         NameIDQualifierStringFunctor(const DOMElement* e)\r
61             : m_attributeID(XMLHelper::getAttrString(e, nullptr, attributeID)),\r
62                 m_matchNameQualifier(XMLHelper::getAttrString(e, nullptr, NameID::NAMEQUALIFIER_ATTRIB_NAME)),\r
63                 m_matchSPNameQualifier(XMLHelper::getAttrString(e, nullptr, NameID::SPNAMEQUALIFIER_ATTRIB_NAME)) {\r
64         }\r
65 \r
66         virtual ~NameIDQualifierStringFunctor() {\r
67         }\r
68 \r
69         bool evaluatePolicyRequirement(const FilteringContext& filterContext) const {\r
70             if (m_attributeID.empty())\r
71                 throw AttributeFilteringException("No attributeID specified.");\r
72             return hasValue(filterContext);\r
73         }\r
74 \r
75         bool evaluatePermitValue(const FilteringContext& filterContext, const Attribute& attribute, size_t index) const {\r
76             if (m_attributeID.empty() || m_attributeID == attribute.getId())\r
77                 return matches(filterContext, attribute, index);\r
78             return hasValue(filterContext);\r
79         }\r
80     };\r
81 \r
82     MatchFunctor* SHIBSP_DLLLOCAL NameIDQualifierStringFactory(const std::pair<const FilterPolicyContext*,const DOMElement*>& p)\r
83     {\r
84         return new NameIDQualifierStringFunctor(p.second);\r
85     }\r
86 \r
87 };\r
88 \r
89 bool NameIDQualifierStringFunctor::hasValue(const FilteringContext& filterContext) const\r
90 {\r
91     size_t count;\r
92     pair<multimap<string,Attribute*>::const_iterator,multimap<string,Attribute*>::const_iterator> attrs =\r
93         filterContext.getAttributes().equal_range(m_attributeID);\r
94     for (; attrs.first != attrs.second; ++attrs.first) {\r
95         count = attrs.first->second->valueCount();\r
96         for (size_t index = 0; index < count; ++index) {\r
97             if (matches(filterContext, *(attrs.first->second), index))\r
98                 return true;\r
99         }\r
100     }\r
101     return false;\r
102 }\r
103 \r
104 bool NameIDQualifierStringFunctor::matches(const FilteringContext& filterContext, const Attribute& attribute, size_t index) const\r
105 {\r
106     const NameIDAttribute* nameattr = dynamic_cast<const NameIDAttribute*>(&attribute);\r
107     if (!nameattr) {\r
108         Category::getInstance(SHIBSP_LOGCAT".AttributeFilter").warn(\r
109             "NameIDQualifierString MatchFunctor applied to non-NameID-valued attribute (%s)", attribute.getId()\r
110             );\r
111         return false;\r
112     }\r
113 \r
114     const NameIDAttribute::Value& val = nameattr->getValues()[index];\r
115     if (!val.m_NameQualifier.empty()) {\r
116         if (m_matchNameQualifier.empty()) {\r
117             auto_ptr_char issuer(filterContext.getAttributeIssuer());\r
118             if (issuer.get() && *issuer.get()) {\r
119                 if (val.m_NameQualifier != issuer.get()) {\r
120                     Category::getInstance(SHIBSP_LOGCAT".AttributeFilter").warn(\r
121                         "NameIDQualifierString MatchFunctor rejecting NameQualifier (%s), should be (%s)",\r
122                         val.m_NameQualifier.c_str(), issuer.get()\r
123                         );\r
124                     return false;\r
125                 }\r
126             }\r
127             else {\r
128                 Category::getInstance(SHIBSP_LOGCAT".AttributeFilter").warn(\r
129                     "NameIDQualifierString MatchFunctor rejecting NameQualifier (%s), attribute issuer unknown",\r
130                     val.m_NameQualifier.c_str()\r
131                     );\r
132                 return false;\r
133             }\r
134         }\r
135         else if (m_matchNameQualifier != val.m_NameQualifier) {\r
136             Category::getInstance(SHIBSP_LOGCAT".AttributeFilter").warn(\r
137                 "NameIDQualifierString MatchFunctor rejecting NameQualifier (%s), should be (%s)",\r
138                 val.m_NameQualifier.c_str(), m_matchNameQualifier.c_str()\r
139                 );\r
140             return false;\r
141         }\r
142     }\r
143     if (!val.m_SPNameQualifier.empty()) {\r
144         if (m_matchSPNameQualifier.empty()) {\r
145             auto_ptr_char req(filterContext.getAttributeRequester());\r
146             if (req.get() && *req.get()) {\r
147                 if (val.m_SPNameQualifier != req.get()) {\r
148                     Category::getInstance(SHIBSP_LOGCAT".AttributeFilter").warn(\r
149                         "NameIDQualifierString MatchFunctor rejecting SPNameQualifier (%s), should be (%s)",\r
150                         val.m_SPNameQualifier.c_str(), req.get()\r
151                         );\r
152                     return false;\r
153                 }\r
154             }\r
155             else {\r
156                 Category::getInstance(SHIBSP_LOGCAT".AttributeFilter").warn(\r
157                     "NameIDQualifierString MatchFunctor rejecting SPNameQualifier (%s), attribute requester unknown",\r
158                     val.m_SPNameQualifier.c_str()\r
159                     );\r
160                 return false;\r
161             }\r
162         }\r
163         else if (m_matchSPNameQualifier != val.m_SPNameQualifier) {\r
164             Category::getInstance(SHIBSP_LOGCAT".AttributeFilter").warn(\r
165                 "NameIDQualifierString MatchFunctor rejecting SPNameQualifier (%s), should be (%s)",\r
166                 val.m_SPNameQualifier.c_str(), m_matchSPNameQualifier.c_str()\r
167                 );\r
168             return false;\r
169         }\r
170     }\r
171 \r
172     return true;\r
173 }\r