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