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