SSPCPP-697 - Align the filter schema(s) and functor types where feasible.
[shibboleth/cpp-sp.git] / shibsp / attribute / filtering / impl / RegistrationAuthorityFunctor.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  */
20
21 /**
22  * AttributeIssuerRegistrationAuthority.cpp
23  * 
24  * A match function that evaluates to true if the attribute issuer's metadata includes
25  * a matching RegistrationAuthority extension.
26  */
27
28 #include "internal.h"
29 #include "exceptions.h"
30 #include "attribute/filtering/FilteringContext.h"
31 #include "attribute/filtering/FilterPolicyContext.h"
32 #include "attribute/filtering/MatchFunctor.h"
33
34 #include <set>
35 #include <boost/algorithm/string.hpp>
36 #include <boost/lambda/bind.hpp>
37 #include <boost/lambda/casts.hpp>
38 #include <boost/lambda/lambda.hpp>
39 #include <xmltooling/util/XMLHelper.h>
40 #include <saml/saml2/metadata/Metadata.h>
41
42 using namespace opensaml::saml2md;
43 using namespace xmltooling;
44 using namespace boost::lambda;
45 using namespace boost;
46 using namespace std;
47
48 namespace shibsp {
49
50     static const XMLCh registrars[] = UNICODE_LITERAL_10(r,e,g,i,s,t,r,a,r,s);
51     static const XMLCh matchIfMetadataSilent[] = UNICODE_LITERAL_21(m,a,t,c,h,I,f,M,e,t,a,d,a,t,a,S,i,l,e,n,t);
52
53     /**
54      * A match function base class that evaluates to true if the supplied metadata includes
55      * a matching RegistrationAuthority extension.
56      */
57     class SHIBSP_DLLLOCAL AbstractRegistrationAuthorityFunctor : public MatchFunctor
58     {
59         bool m_matchIfMetadataSilent;
60         set<string> m_registrars;
61     public:
62         AbstractRegistrationAuthorityFunctor(const DOMElement* e)
63                 : m_matchIfMetadataSilent(XMLHelper::getAttrBool(e, false, matchIfMetadataSilent)) {
64             const XMLCh* prop = e ? e->getAttributeNS(nullptr,registrars) : nullptr;
65             if (!prop || !*prop)
66                 throw ConfigurationException("AttributeIssuerRegistrationAuthorityFunctor MatchFunctor requires non-empty registrars attribute.");
67             auto_ptr_char regs(prop);
68             string dup(regs.get());
69             split(m_registrars, dup, is_space(), algorithm::token_compress_on);
70             if (m_registrars.empty())
71                 throw ConfigurationException("AttributeIssuerRegistrationAuthorityFunctor MatchFunctor requires non-empty registrars attribute.");
72         }
73
74         bool evaluatePolicyRequirement(const FilteringContext& filterContext) const {
75             const RoleDescriptor* issuer = getMetadata(filterContext);
76             if (!issuer)
77                 return m_matchIfMetadataSilent;
78
79             const EntityDescriptor* entity = dynamic_cast<const EntityDescriptor*>(issuer->getParent());
80             const RegistrationInfo* info = getRegistrationInfo(entity->getExtensions());
81             if (!info) {
82                 const EntitiesDescriptor* group = dynamic_cast<const EntitiesDescriptor*>(entity->getParent());
83                 while (!info && group) {
84                     info = getRegistrationInfo(group->getExtensions());
85                     group = dynamic_cast<const EntitiesDescriptor*>(group->getParent());
86                 }
87             }
88
89             if (info) {
90                 auto_ptr_char authority(info->getRegistrationAuthority());
91                 return authority.get() &&  m_registrars.find(authority.get()) != m_registrars.end();
92             }
93             return m_matchIfMetadataSilent;
94         }
95
96         bool evaluatePermitValue(const FilteringContext& filterContext, const Attribute& attribute, size_t index) const {
97             return evaluatePolicyRequirement(filterContext);
98         }
99
100     protected:
101         virtual const RoleDescriptor* getMetadata(const FilteringContext& filterContext) const = 0;
102
103     private:
104         const RegistrationInfo* getRegistrationInfo(const Extensions* extensions) const {
105             if (extensions) {
106                 const vector<XMLObject*>& exts = extensions->getUnknownXMLObjects();
107                 const XMLObject* xo = find_if(exts, ll_dynamic_cast<RegistrationInfo*>(_1) != ((RegistrationInfo*)nullptr));
108                 if (xo) {
109                     return dynamic_cast<const RegistrationInfo*>(xo);
110                 }
111             }
112             return nullptr;
113         }
114     };
115
116     class SHIBSP_DLLLOCAL AttributeIssuerRegistrationAuthorityFunctor : public AbstractRegistrationAuthorityFunctor
117     {
118     public:
119         AttributeIssuerRegistrationAuthorityFunctor(const DOMElement* e) : AbstractRegistrationAuthorityFunctor(e) {}
120
121     protected:
122         const RoleDescriptor* getMetadata(const FilteringContext& filterContext) const {
123             return filterContext.getAttributeIssuerMetadata();
124         }
125     };
126
127     class SHIBSP_DLLLOCAL AttributeRequesterRegistrationAuthorityFunctor : public AbstractRegistrationAuthorityFunctor
128     {
129     public:
130         AttributeRequesterRegistrationAuthorityFunctor(const DOMElement* e) : AbstractRegistrationAuthorityFunctor(e) {}
131
132     protected:
133         const RoleDescriptor* getMetadata(const FilteringContext& filterContext) const {
134             return filterContext.getAttributeRequesterMetadata();
135         }
136     };
137
138
139     MatchFunctor* SHIBSP_DLLLOCAL AttributeIssuerRegistrationAuthorityFactory(const std::pair<const FilterPolicyContext*,const DOMElement*>& p)
140     {
141         return new AttributeIssuerRegistrationAuthorityFunctor(p.second);
142     }
143
144     MatchFunctor* SHIBSP_DLLLOCAL RegistrationAuthorityFactory(const std::pair<const FilterPolicyContext*,const DOMElement*>& p)
145     {
146         return new AttributeRequesterRegistrationAuthorityFunctor(p.second);
147     }
148
149 };