Boost related changes
[shibboleth/cpp-opensaml.git] / saml / binding / impl / SecurityPolicy.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  * SecurityPolicy.cpp
23  *
24  * Overall policy used to verify the security of an incoming message.
25  */
26
27 #include "internal.h"
28 #include "exceptions.h"
29 #include "binding/SecurityPolicy.h"
30 #include "binding/SecurityPolicyRule.h"
31 #include "saml2/core/Assertions.h"
32
33 #include <boost/bind.hpp>
34 #include <xercesc/util/XMLUniDefs.hpp>
35
36 using namespace opensaml::saml2md;
37 using namespace opensaml::saml2;
38 using namespace opensaml;
39 using namespace xmltooling;
40 using namespace boost;
41 using namespace std;
42
43 namespace opensaml {
44     SAML_DLLLOCAL PluginManager<SecurityPolicyRule,string,const DOMElement*>::Factory AudienceRestrictionRuleFactory;
45     SAML_DLLLOCAL PluginManager<SecurityPolicyRule,string,const DOMElement*>::Factory ClientCertAuthRuleFactory;
46     SAML_DLLLOCAL PluginManager<SecurityPolicyRule,string,const DOMElement*>::Factory ConditionsRuleFactory;
47     SAML_DLLLOCAL PluginManager<SecurityPolicyRule,string,const DOMElement*>::Factory IgnoreRuleFactory;
48     SAML_DLLLOCAL PluginManager<SecurityPolicyRule,string,const DOMElement*>::Factory MessageFlowRuleFactory;
49     SAML_DLLLOCAL PluginManager<SecurityPolicyRule,string,const DOMElement*>::Factory NullSecurityRuleFactory;
50     SAML_DLLLOCAL PluginManager<SecurityPolicyRule,string,const DOMElement*>::Factory SimpleSigningRuleFactory;
51     SAML_DLLLOCAL PluginManager<SecurityPolicyRule,string,const DOMElement*>::Factory XMLSigningRuleFactory;
52
53     namespace saml1 {
54         SAML_DLLLOCAL PluginManager<SecurityPolicyRule,string,const DOMElement*>::Factory BrowserSSORuleFactory;
55     }
56
57     namespace saml2 {
58         SAML_DLLLOCAL PluginManager<SecurityPolicyRule,string,const DOMElement*>::Factory BearerConfirmationRuleFactory;
59         SAML_DLLLOCAL PluginManager<SecurityPolicyRule,string,const DOMElement*>::Factory DelegationRestrictionRuleFactory;
60     }
61 };
62
63 void SAML_API opensaml::registerSecurityPolicyRules()
64 {
65     SAMLConfig& conf=SAMLConfig::getConfig();
66     conf.SecurityPolicyRuleManager.registerFactory(AUDIENCE_POLICY_RULE, AudienceRestrictionRuleFactory);
67     conf.SecurityPolicyRuleManager.registerFactory(CLIENTCERTAUTH_POLICY_RULE, ClientCertAuthRuleFactory);
68     conf.SecurityPolicyRuleManager.registerFactory(CONDITIONS_POLICY_RULE, ConditionsRuleFactory);
69     conf.SecurityPolicyRuleManager.registerFactory(IGNORE_POLICY_RULE, IgnoreRuleFactory);
70     conf.SecurityPolicyRuleManager.registerFactory(MESSAGEFLOW_POLICY_RULE, MessageFlowRuleFactory);
71     conf.SecurityPolicyRuleManager.registerFactory(NULLSECURITY_POLICY_RULE, NullSecurityRuleFactory);
72     conf.SecurityPolicyRuleManager.registerFactory(SIMPLESIGNING_POLICY_RULE, SimpleSigningRuleFactory);
73     conf.SecurityPolicyRuleManager.registerFactory(XMLSIGNING_POLICY_RULE, XMLSigningRuleFactory);
74     conf.SecurityPolicyRuleManager.registerFactory(SAML1BROWSERSSO_POLICY_RULE, saml1::BrowserSSORuleFactory);
75     conf.SecurityPolicyRuleManager.registerFactory(BEARER_POLICY_RULE, saml2::BearerConfirmationRuleFactory);
76     conf.SecurityPolicyRuleManager.registerFactory(DELEGATION_POLICY_RULE, saml2::DelegationRestrictionRuleFactory);
77 }
78
79 SecurityPolicyRule::SecurityPolicyRule()
80 {
81 }
82
83 SecurityPolicyRule::~SecurityPolicyRule()
84 {
85 }
86
87 SecurityPolicy::SecurityPolicy(
88     const saml2md::MetadataProvider* metadataProvider,
89     const xmltooling::QName* role,
90     const xmltooling::TrustEngine* trustEngine,
91     bool validate
92     ) : m_metadataCriteria(nullptr),
93         m_issueInstant(0),
94         m_issuerRole(nullptr),
95         m_authenticated(false),
96         m_metadata(metadataProvider),
97         m_role(role ? new xmltooling::QName(*role) : nullptr),
98         m_trust(trustEngine),
99         m_validate(validate),
100         m_entityOnly(true),
101         m_ts(0)
102 {
103 }
104
105 SecurityPolicy::~SecurityPolicy()
106 {
107     delete m_metadataCriteria;
108 }
109
110 const MetadataProvider* SecurityPolicy::getMetadataProvider() const
111 {
112     return m_metadata;
113 }
114
115 MetadataProvider::Criteria& SecurityPolicy::getMetadataProviderCriteria() const
116 {
117     if (!m_metadataCriteria)
118         m_metadataCriteria=new MetadataProvider::Criteria();
119     else
120         m_metadataCriteria->reset();
121     return *m_metadataCriteria;
122 }
123
124 const xmltooling::QName* SecurityPolicy::getRole() const
125 {
126     return m_role.get();
127 }
128
129 const TrustEngine* SecurityPolicy::getTrustEngine() const
130 {
131     return m_trust;
132 }
133
134 bool SecurityPolicy::getValidating() const
135 {
136     return m_validate;
137 }
138
139 bool SecurityPolicy::requireEntityIssuer() const
140 {
141     return m_entityOnly;
142 }
143
144 const vector<xstring>& SecurityPolicy::getAudiences() const
145 {
146     return m_audiences;
147 }
148
149 vector<xstring>& SecurityPolicy::getAudiences()
150 {
151     return m_audiences;
152 }
153
154 time_t SecurityPolicy::getTime() const
155 {
156     if (m_ts == 0)
157         return m_ts = time(nullptr);
158     return m_ts;
159 }
160
161 const XMLCh* SecurityPolicy::getCorrelationID() const
162 {
163     return m_correlationID.c_str();
164 }
165
166 vector<const SecurityPolicyRule*>& SecurityPolicy::getRules()
167 {
168     return m_rules;
169 }
170
171 void SecurityPolicy::setMetadataProvider(const MetadataProvider* metadata)
172 {
173     m_metadata = metadata;
174 }
175
176 void SecurityPolicy::setMetadataProviderCriteria(MetadataProvider::Criteria* criteria)
177 {
178     if (m_metadataCriteria)
179         delete m_metadataCriteria;
180     m_metadataCriteria=criteria;
181 }
182
183 void SecurityPolicy::setRole(const xmltooling::QName* role)
184 {
185     m_role.reset(role ? new xmltooling::QName(*role) : nullptr);
186 }
187
188 void SecurityPolicy::setTrustEngine(const TrustEngine* trust)
189 {
190     m_trust = trust;
191 }
192
193 void SecurityPolicy::setValidating(bool validate)
194 {
195     m_validate = validate;
196 }
197
198 void SecurityPolicy::requireEntityIssuer(bool entityOnly)
199 {
200     m_entityOnly = entityOnly;
201 }
202
203 void SecurityPolicy::setTime(time_t ts)
204 {
205     m_ts = ts;
206 }
207
208 void SecurityPolicy::setCorrelationID(const XMLCh* correlationID)
209 {
210     m_correlationID.erase();
211     if (correlationID)
212         m_correlationID = correlationID;
213 }
214
215 void SecurityPolicy::evaluate(const XMLObject& message, const GenericRequest* request)
216 {
217     for_each(
218         m_rules.begin(), m_rules.end(),
219         boost::bind(&SecurityPolicyRule::evaluate, _1, boost::ref(message), request, boost::ref(*this))
220         );
221 }
222
223 void SecurityPolicy::reset(bool messageOnly)
224 {
225     _reset(messageOnly);
226 }
227
228 void SecurityPolicy::_reset(bool messageOnly)
229 {
230     m_messageID.erase();
231     m_issueInstant=0;
232     if (!messageOnly) {
233         m_issuer.reset();
234         m_issuerRole=nullptr;
235         m_authenticated=false;
236     }
237 }
238
239 const XMLCh* SecurityPolicy::getMessageID() const
240 {
241     return m_messageID.c_str();
242 }
243
244 time_t SecurityPolicy::getIssueInstant() const
245 {
246     return m_issueInstant;
247 }
248
249 const Issuer* SecurityPolicy::getIssuer() const
250 {
251     return m_issuer.get();
252 }
253
254 const RoleDescriptor* SecurityPolicy::getIssuerMetadata() const
255 {
256     return m_issuerRole;
257 }
258
259 bool SecurityPolicy::isAuthenticated() const
260 {
261     return m_authenticated;
262 }
263
264 void SecurityPolicy::setMessageID(const XMLCh* id)
265 {
266     m_messageID.erase();
267     if (id)
268         m_messageID = id;
269 }
270
271 void SecurityPolicy::setIssueInstant(time_t issueInstant)
272 {
273     m_issueInstant = issueInstant;
274 }
275
276 void SecurityPolicy::setIssuer(const Issuer* issuer)
277 {
278     if (!getIssuerMatchingPolicy().issuerMatches(m_issuer.get(), issuer))
279         throw SecurityPolicyException("An Issuer was supplied that conflicts with previous results.");
280
281     if (!m_issuer.get()) {
282         if (m_entityOnly && issuer->getFormat() && !XMLString::equals(issuer->getFormat(), NameIDType::ENTITY))
283             throw SecurityPolicyException("A non-entity Issuer was supplied, violating policy.");
284         m_issuerRole = nullptr;
285         m_issuer.reset(issuer->cloneIssuer());
286     }
287 }
288
289 void SecurityPolicy::setIssuer(const XMLCh* issuer)
290 {
291     if (!getIssuerMatchingPolicy().issuerMatches(m_issuer.get(), issuer))
292         throw SecurityPolicyException("An Issuer was supplied that conflicts with previous results.");
293
294     if (!m_issuer.get() && issuer && *issuer) {
295         m_issuerRole = nullptr;
296         m_issuer.reset(IssuerBuilder::buildIssuer());
297         m_issuer->setName(issuer);
298     }
299 }
300
301 void SecurityPolicy::setIssuerMetadata(const RoleDescriptor* issuerRole)
302 {
303     if (issuerRole && m_issuerRole && issuerRole!=m_issuerRole)
304         throw SecurityPolicyException("A rule supplied a RoleDescriptor that conflicts with previous results.");
305     m_issuerRole = issuerRole;
306 }
307
308 void SecurityPolicy::setAuthenticated(bool auth)
309 {
310     m_authenticated = auth;
311 }
312
313 SecurityPolicy::IssuerMatchingPolicy::IssuerMatchingPolicy()
314 {
315 }
316
317 SecurityPolicy::IssuerMatchingPolicy::~IssuerMatchingPolicy()
318 {
319 }
320
321 bool SecurityPolicy::IssuerMatchingPolicy::issuerMatches(const Issuer* issuer1, const Issuer* issuer2) const
322 {
323     // nullptr matches anything for the purposes of this interface.
324     if (!issuer1 || !issuer2)
325         return true;
326
327     const XMLCh* op1=issuer1->getName();
328     const XMLCh* op2=issuer2->getName();
329     if (!op1 || !op2 || !XMLString::equals(op1,op2))
330         return false;
331
332     op1=issuer1->getFormat();
333     op2=issuer2->getFormat();
334     if (!XMLString::equals(op1 ? op1 : NameIDType::ENTITY, op2 ? op2 : NameIDType::ENTITY))
335         return false;
336
337     op1=issuer1->getNameQualifier();
338     op2=issuer2->getNameQualifier();
339     if (!XMLString::equals(op1 ? op1 : &chNull, op2 ? op2 : &chNull))
340         return false;
341
342     op1=issuer1->getSPNameQualifier();
343     op2=issuer2->getSPNameQualifier();
344     if (!XMLString::equals(op1 ? op1 : &chNull, op2 ? op2 : &chNull))
345         return false;
346
347     return true;
348 }
349
350 bool SecurityPolicy::IssuerMatchingPolicy::issuerMatches(const Issuer* issuer1, const XMLCh* issuer2) const
351 {
352     // nullptr matches anything for the purposes of this interface.
353     if (!issuer1 || !issuer2 || !*issuer2)
354         return true;
355
356     const XMLCh* op1=issuer1->getName();
357     if (!op1 || !XMLString::equals(op1,issuer2))
358         return false;
359
360     op1=issuer1->getFormat();
361     if (op1 && *op1 && !XMLString::equals(op1, NameIDType::ENTITY))
362         return false;
363
364     op1=issuer1->getNameQualifier();
365     if (op1 && *op1)
366         return false;
367
368     op1=issuer1->getSPNameQualifier();
369     if (op1 && *op1)
370         return false;
371
372     return true;
373 }
374
375 SecurityPolicy::IssuerMatchingPolicy SecurityPolicy::m_defaultMatching;
376
377 const SecurityPolicy::IssuerMatchingPolicy& SecurityPolicy::getIssuerMatchingPolicy() const
378 {
379     return m_matchingPolicy.get() ? *m_matchingPolicy.get() : m_defaultMatching;
380 }
381
382 void SecurityPolicy::setIssuerMatchingPolicy(IssuerMatchingPolicy* matchingPolicy)
383 {
384     m_matchingPolicy.reset(matchingPolicy);
385 }