Reducing header overuse, non-inlining selected methods (CPPOST-35).
[shibboleth/cpp-opensaml.git] / saml / binding / SecurityPolicy.h
1 /*
2  *  Copyright 2001-2009 Internet2
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 /**
18  * @file saml/binding/SecurityPolicy.h
19  *
20  * Overall policy used to verify the security of an incoming message.
21  */
22
23 #ifndef __saml_secpol_h__
24 #define __saml_secpol_h__
25
26 #include <saml/saml2/metadata/MetadataProvider.h>
27
28 #include <ctime>
29 #include <vector>
30 #include <xmltooling/unicode.h>
31
32 #if defined (_MSC_VER)
33     #pragma warning( push )
34     #pragma warning( disable : 4250 4251 )
35 #endif
36
37 namespace xmltooling {
38     class XMLTOOL_API GenericRequest;
39     class XMLTOOL_API TrustEngine;
40 };
41
42 namespace opensaml {
43
44     namespace saml2 {
45         class SAML_API Issuer;
46     };
47
48     class SAML_API SecurityPolicyRule;
49
50     /**
51      * A policy used to verify the security of an incoming message.
52      *
53      * <p>Its security mechanisms may be used to examine the transport layer
54      * (e.g client certificates and HTTP basic auth passwords) or to check the
55      * payload of a request to ensure it meets certain criteria (e.g. valid
56      * digital signature, freshness, replay).
57      *
58      * <p>Policy objects can be reused, but are not thread-safe.
59      */
60     class SAML_API SecurityPolicy
61     {
62         MAKE_NONCOPYABLE(SecurityPolicy);
63     public:
64         /**
65          * Constructor for policy.
66          *
67          * @param metadataProvider  locked MetadataProvider instance
68          * @param role              identifies the role (generally IdP or SP) of the policy peer
69          * @param trustEngine       TrustEngine to authenticate policy peer
70          * @param validate          true iff XML parsing should be done with validation
71          */
72         SecurityPolicy(
73             const saml2md::MetadataProvider* metadataProvider=NULL,
74             const xmltooling::QName* role=NULL,
75             const xmltooling::TrustEngine* trustEngine=NULL,
76             bool validate=true
77             );
78
79         virtual ~SecurityPolicy();
80
81         /**
82          * Returns the locked MetadataProvider supplied to the policy.
83          *
84          * @return the supplied MetadataProvider or NULL
85          */
86         const saml2md::MetadataProvider* getMetadataProvider() const {
87             return m_metadata;
88         }
89
90         /**
91          * Returns a reference to a MetadataProvider::Criteria instance suitable for use with the
92          * installed MetadataProvider.
93          *
94          * <p>The object will be cleared/reset when returned, so do not mutate it and then
95          * call the method again before using it.
96          *
97          * @return reference to a MetadataProvider::Criteria instance
98          */
99         virtual saml2md::MetadataProvider::Criteria& getMetadataProviderCriteria() const;
100
101         /**
102          * Returns the peer role element/type supplied to the policy.
103          *
104          * @return the peer role element/type, or an empty QName
105          */
106         const xmltooling::QName* getRole() const {
107             return m_role;
108         }
109
110         /**
111          * Returns the TrustEngine supplied to the policy.
112          *
113          * @return the supplied TrustEngine or NULL
114          */
115         const xmltooling::TrustEngine* getTrustEngine() const {
116             return m_trust;
117         }
118
119         /**
120          * Returns XML message validation setting.
121          *
122          * @return validation flag
123          */
124         bool getValidating() const {
125             return m_validate;
126         }
127
128         /**
129          * Returns flag controlling non-entity issuer support.
130          *
131          * @return flag controlling non-entity issuer support
132          */
133         bool requireEntityIssuer() const {
134             return m_entityOnly;
135         }
136
137         /**
138          * Returns the SAML audiences that represent the receiving peer.
139          *
140          * @return audience values of the peer processing the message
141          */
142         const std::vector<xmltooling::xstring>& getAudiences() const {
143             return m_audiences;
144         }
145
146         /**
147          * Returns the SAML audiences that represent the receiving peer.
148          *
149          * @return audience values of the peer processing the message
150          */
151         std::vector<xmltooling::xstring>& getAudiences() {
152             return m_audiences;
153         }
154
155         /**
156          * Gets the effective time of message processing.
157          *
158          * @return  the time at which the message is being processed
159          */
160         time_t getTime() const {
161             if (m_ts == 0)
162                 return m_ts = time(NULL);
163             return m_ts;
164         }
165
166         /**
167          * Returns the message identifier to which the message being evaluated
168          * is a response.
169          *
170          * @return correlated message identifier
171          */
172         const XMLCh* getCorrelationID() const {
173             return m_correlationID.c_str();
174         }
175
176         /**
177          * Gets a mutable array of installed policy rules.
178          *
179          * <p>If adding rules, their lifetime must be at least as long as the policy object.
180          *
181          * @return  mutable array of rules
182          */
183         std::vector<const SecurityPolicyRule*>& getRules() {
184             return m_rules;
185         }
186
187         /**
188          * Sets a locked MetadataProvider for the policy.
189          *
190          * @param metadata a locked MetadataProvider or NULL
191          */
192         void setMetadataProvider(const saml2md::MetadataProvider* metadata) {
193             m_metadata = metadata;
194         }
195
196         /**
197          * Sets a MetadataProvider::Criteria instance suitable for use with the
198          * installed MetadataProvider.
199          *
200          * <p>The policy will take ownership of the criteria object when this
201          * method completes.
202          *
203          * @param criteria a MetadataProvider::Criteria instance, or NULL
204          */
205         void setMetadataProviderCriteria(saml2md::MetadataProvider::Criteria* criteria);
206
207         /**
208          * Sets a peer role element/type for to the policy.
209          *
210          * @param role the peer role element/type or NULL
211          */
212         void setRole(const xmltooling::QName* role);
213
214         /**
215          * Sets a TrustEngine for the policy.
216          *
217          * @param trust a TrustEngine or NULL
218          */
219         void setTrustEngine(const xmltooling::TrustEngine* trust) {
220             m_trust = trust;
221         }
222
223         /**
224          * Controls schema validation of incoming XML messages.
225          * This is separate from other forms of programmatic validation of objects,
226          * but can detect a much wider range of syntax errors.
227          *
228          * @param validate  validation setting
229          */
230         void setValidating(bool validate=true) {
231             m_validate = validate;
232         }
233
234         /**
235          * Sets flag controlling non-entity issuer support.
236          *
237          * @param entityOnly require that Issuer be in entity format
238          */
239         void requireEntityIssuer(bool entityOnly=true) {
240             m_entityOnly = entityOnly;
241         }
242
243         /**
244          * Sets effective time of message processing.
245          *
246          * <p>Assumed to be the time of policy instantiation, can be adjusted to pre- or post-date
247          * message processing.
248          *
249          * @param ts    the time at which the message is being processed
250          */
251         void setTime(time_t ts) {
252             m_ts = ts;
253         }
254
255         /**
256          * Sets the message identifier to which the message being evaluated
257          * is a response.
258          *
259          * @param correlationID correlated message identifier
260          */
261         void setCorrelationID(const XMLCh* correlationID) {
262             m_correlationID.erase();
263             if (correlationID)
264                 m_correlationID = correlationID;
265         }
266
267         /**
268          * Evaluates the policy against the given request and message,
269          * possibly populating message information in the policy object.
270          *
271          * @param message           the incoming message
272          * @param request           the protocol request
273          *
274          * @throws BindingException raised if the message/request is invalid according to the supplied rules
275          */
276         void evaluate(const xmltooling::XMLObject& message, const xmltooling::GenericRequest* request=NULL);
277
278         /**
279          * Resets the policy object and/or clears any per-message state.
280          *
281          * <p>Resets can be complete (the default) or merely clear the previous message ID and timestamp
282          * when evaluating multiple layers of a message.
283          *
284          * @param messageOnly   true iff security and issuer state should be left in place
285          */
286         virtual void reset(bool messageOnly=false);
287
288         /**
289          * Resets the policy object and/or clears any per-message state for only this specific class.
290          *
291          * <p>Resets can be complete (the default) or merely clear the previous message ID and timestamp
292          * when evaluating multiple layers of a message.
293          *
294          * @param messageOnly   true iff security and issuer state should be left in place
295          */
296         void _reset(bool messageOnly=false);
297
298         /**
299          * Returns the message identifier as determined by the registered policies.
300          *
301          * @return message identifier as determined by the registered policies
302          */
303         const XMLCh* getMessageID() const {
304             return m_messageID.c_str();
305         }
306
307         /**
308          * Returns the message timestamp as determined by the registered policies.
309          *
310          * @return message timestamp as determined by the registered policies
311          */
312         time_t getIssueInstant() const {
313             return m_issueInstant;
314         }
315
316         /**
317          * Gets the issuer of the message as determined by the registered policies.
318          *
319          * @return issuer of the message as determined by the registered policies
320          */
321         const saml2::Issuer* getIssuer() const {
322             return m_issuer;
323         }
324
325         /**
326          * Gets the metadata for the role the issuer is operating in.
327          *
328          * @return metadata for the role the issuer is operating in
329          */
330         const saml2md::RoleDescriptor* getIssuerMetadata() const {
331             return m_issuerRole;
332         }
333
334         /**
335          * Returns the authentication status of the message as determined by the registered policies.
336          *
337          * @return true iff a SecurityPolicyRule has indicated the issuer/message has been authenticated
338          */
339         bool isAuthenticated() const {
340             return m_authenticated;
341         }
342
343         /**
344          * Sets the message identifier as determined by the registered policies.
345          *
346          * @param id message identifier
347          */
348         void setMessageID(const XMLCh* id) {
349             m_messageID.erase();
350             if (id)
351                 m_messageID = id;
352         }
353
354         /**
355          * Sets the message timestamp as determined by the registered policies.
356          *
357          * @param issueInstant message timestamp
358          */
359         void setIssueInstant(time_t issueInstant) {
360             m_issueInstant = issueInstant;
361         }
362
363         /**
364          * Sets the issuer of the message as determined by the registered policies.
365          *
366          * @param issuer issuer of the message
367          */
368         void setIssuer(const saml2::Issuer* issuer);
369
370         /**
371          * Sets the issuer of the message as determined by the registered policies.
372          *
373          * @param issuer issuer of the message
374          */
375         void setIssuer(const XMLCh* issuer);
376
377         /**
378          * Sets the metadata for the role the issuer is operating in.
379          *
380          * @param issuerRole metadata for the role the issuer is operating in
381          */
382         void setIssuerMetadata(const saml2md::RoleDescriptor* issuerRole);
383
384         /**
385          * Sets the authentication status of the message as determined by the registered policies.
386          *
387          * @param auth indicates whether the issuer/message has been authenticated
388          */
389         void setAuthenticated(bool auth) {
390             m_authenticated = auth;
391         }
392
393         /** Allows override of rules for comparing saml2:Issuer information. */
394         class SAML_API IssuerMatchingPolicy {
395             MAKE_NONCOPYABLE(IssuerMatchingPolicy);
396         public:
397             IssuerMatchingPolicy() {}
398             virtual ~IssuerMatchingPolicy() {}
399
400             /**
401              * Returns true iff the two operands "match". Applications can override this method to
402              * support non-standard issuer matching for complex policies.
403              *
404              * <p>The default implementation does a basic comparison of the XML content, treating
405              * an unsupplied Format as an "entityID".
406              *
407              * @param issuer1   the first Issuer to match
408              * @param issuer2   the second Issuer to match
409              * @return  true iff the operands match
410              */
411             virtual bool issuerMatches(const saml2::Issuer* issuer1, const saml2::Issuer* issuer2) const;
412
413             /**
414              * Returns true iff the two operands "match". Applications can override this method to
415              * support non-standard issuer matching for complex policies.
416              *
417              * <p>The default implementation does a basic comparison of the XML content, treating
418              * an unsupplied Format as an "entityID".
419              *
420              * @param issuer1   the first Issuer to match
421              * @param issuer2   the second Issuer to match
422              * @return  true iff the operands match
423              */
424             virtual bool issuerMatches(const saml2::Issuer* issuer1, const XMLCh* issuer2) const;
425         };
426
427         /**
428          * Returns the IssuerMatchingPolicy in effect.
429          *
430          * @return the effective IssuerMatchingPolicy
431          */
432         const IssuerMatchingPolicy& getIssuerMatchingPolicy() const {
433             return m_matchingPolicy ? *m_matchingPolicy : m_defaultMatching;
434         }
435
436         /**
437          * Sets the IssuerMatchingPolicy in effect. Setting no policy will
438          * cause the simple, default approach to be used.
439          *
440          * <p>The matching object will be freed by the SecurityPolicy.
441          *
442          * @param matchingPolicy the IssuerMatchingPolicy to use
443          */
444         void setIssuerMatchingPolicy(IssuerMatchingPolicy* matchingPolicy) {
445             delete m_matchingPolicy;
446             m_matchingPolicy = matchingPolicy;
447         }
448
449     protected:
450         /** A shared matching object that just supports the default matching rules. */
451         static IssuerMatchingPolicy m_defaultMatching;
452
453         /** Manufactured MetadataProvider::Criteria instance. */
454         mutable saml2md::MetadataProvider::Criteria* m_metadataCriteria;
455
456     private:
457         // information extracted from message
458         xmltooling::xstring m_messageID;
459         time_t m_issueInstant;
460         saml2::Issuer* m_issuer;
461         const saml2md::RoleDescriptor* m_issuerRole;
462         bool m_authenticated;
463
464         // components governing policy rules
465         IssuerMatchingPolicy* m_matchingPolicy;
466         std::vector<const SecurityPolicyRule*> m_rules;
467         const saml2md::MetadataProvider* m_metadata;
468         xmltooling::QName* m_role;
469         const xmltooling::TrustEngine* m_trust;
470         bool m_validate;
471         bool m_entityOnly;
472
473         // contextual information
474         mutable time_t m_ts;
475         xmltooling::xstring m_correlationID;
476         std::vector<xmltooling::xstring> m_audiences;
477     };
478
479 };
480
481 #if defined (_MSC_VER)
482     #pragma warning( pop )
483 #endif
484
485 #endif /* __saml_secpol_h__ */