Revert to exception-based policy errors, add "secure" flag to policy to track authn.
[shibboleth/cpp-opensaml.git] / saml / binding / SecurityPolicy.h
1 /*
2  *  Copyright 2001-2006 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/binding/GenericRequest.h>
27
28 #include <ctime>
29 #include <vector>
30 #include <xmltooling/XMLObject.h>
31 #include <xmltooling/security/TrustEngine.h>
32
33 #if defined (_MSC_VER)
34     #pragma warning( push )
35     #pragma warning( disable : 4250 4251 )
36 #endif
37
38 namespace opensaml {
39
40     namespace saml2 {
41         class SAML_API Issuer;
42     };
43     namespace saml2md {
44         class SAML_API MetadataProvider;
45         class SAML_API RoleDescriptor;
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          */
71         SecurityPolicy(
72             const saml2md::MetadataProvider* metadataProvider=NULL,
73             const xmltooling::QName* role=NULL,
74             const xmltooling::TrustEngine* trustEngine=NULL
75             ) : m_messageQName(NULL), m_messageID(NULL), m_issueInstant(0), m_issuer(NULL), m_issuerRole(NULL), m_secure(false),
76                 m_matchingPolicy(NULL), m_metadata(metadataProvider), m_role(NULL), m_trust(trustEngine) {
77             if (role)
78                 m_role = new xmltooling::QName(*role);
79         }
80
81         /**
82          * Constructor for policy using existing rules. The lifetime of the policy rules
83          * must be at least as long as the policy object.
84          *
85          * @param rules             reference to array of policy rules to use 
86          * @param metadataProvider  locked MetadataProvider instance
87          * @param role              identifies the role (generally IdP or SP) of the policy peer 
88          * @param trustEngine       TrustEngine to authenticate policy peer
89          */
90         SecurityPolicy(
91             const std::vector<const SecurityPolicyRule*>& rules,
92             const saml2md::MetadataProvider* metadataProvider=NULL,
93             const xmltooling::QName* role=NULL,
94             const xmltooling::TrustEngine* trustEngine=NULL
95             ) : m_messageQName(NULL), m_messageID(NULL), m_issueInstant(0), m_issuer(NULL), m_issuerRole(NULL), m_secure(false),
96                 m_matchingPolicy(NULL), m_rules(rules), m_metadata(metadataProvider), m_role(NULL), m_trust(trustEngine) {
97             if (role)
98                 m_role = new xmltooling::QName(*role);
99         }
100
101         virtual ~SecurityPolicy();
102
103         /**
104          * Returns the locked MetadataProvider supplied to the policy.
105          * 
106          * @return the supplied MetadataProvider or NULL
107          */
108         const saml2md::MetadataProvider* getMetadataProvider() const {
109             return m_metadata;
110         }
111
112         /**
113          * Returns the peer role element/type supplied to the policy.
114          * 
115          * @return the peer role element/type, or an empty QName
116          */
117         const xmltooling::QName* getRole() const {
118             return m_role;
119         }
120
121         /**
122          * Returns the TrustEngine supplied to the policy.
123          * 
124          * @return the supplied TrustEngine or NULL
125          */
126         const xmltooling::TrustEngine* getTrustEngine() const {
127             return m_trust;
128         }
129
130         /**
131          * Adds a SecurityPolicyRule to the policy. The lifetime of the policy rule
132          * must be at least as long as the policy object.
133          * 
134          * @param rule  SecurityPolicyRule to add
135          */
136         void addRule(const SecurityPolicyRule* rule) {
137             m_rules.push_back(rule);
138         }
139
140         /**
141          * Sets a locked MetadataProvider for the policy.
142          * 
143          * @param metadata a locked MetadataProvider or NULL
144          */
145         void setMetadataProvider(const saml2md::MetadataProvider* metadata) {
146             m_metadata = metadata;
147         }
148
149         /**
150          * Sets a peer role element/type for to the policy.
151          * 
152          * @param role the peer role element/type or NULL
153          */
154         void setRole(const xmltooling::QName* role) {
155             delete m_role;
156             m_role = role ? new xmltooling::QName(*role) : NULL;
157         }
158
159         /**
160          * Sets a TrustEngine for the policy.
161          * 
162          * @param trust a TrustEngine or NULL
163          */
164         void setTrustEngine(const xmltooling::TrustEngine* trust) {
165             m_trust = trust;
166         }
167
168         /**
169          * Evaluates the policy against the given request and message,
170          * possibly populating message information in the policy object.
171          * 
172          * @param message           the incoming message
173          * @param request           the protocol request
174          *
175          * @throws BindingException raised if the message/request is invalid according to the supplied rules
176          */
177         void evaluate(const xmltooling::XMLObject& message, const GenericRequest* request=NULL);
178
179         /**
180          * Resets the policy object and clears any per-message state.
181          */
182         void reset();
183         
184         /**
185          * Returns the message element/type as determined by the registered policies.
186          * 
187          * @return message element/type as determined by the registered policies
188          */
189         const xmltooling::QName* getMessageQName() const {
190             return m_messageQName;
191         }
192
193         /**
194          * Returns the message identifier as determined by the registered policies.
195          * 
196          * @return message identifier as determined by the registered policies
197          */
198         const XMLCh* getMessageID() const {
199             return m_messageID;
200         }
201
202         /**
203          * Returns the message timestamp as determined by the registered policies.
204          * 
205          * @return message timestamp as determined by the registered policies
206          */
207         time_t getIssueInstant() const {
208             return m_issueInstant;
209         }
210
211         /**
212          * Gets the issuer of the message as determined by the registered policies.
213          * 
214          * @return issuer of the message as determined by the registered policies
215          */
216         const saml2::Issuer* getIssuer() const {
217             return m_issuer;
218         }
219
220         /**
221          * Gets the metadata for the role the issuer is operating in.
222          * 
223          * @return metadata for the role the issuer is operating in
224          */
225         const saml2md::RoleDescriptor* getIssuerMetadata() const {
226             return m_issuerRole;
227         }
228
229         /**
230          * Returns the security status as determined by the registered policies.
231          * 
232          * @return true iff a SecurityPolicyRule has indicated the issuer/message has been authenticated 
233          */
234         bool isSecure() const {
235             return m_secure;
236         }
237
238         /**
239          * Sets the message element/type as determined by the registered policies.
240          * 
241          * @param messageQName message element/type
242          */
243         void setMessageQName(const xmltooling::QName* messageQName) {
244             delete m_messageQName;
245             m_messageQName = messageQName ? new xmltooling::QName(*messageQName) : NULL;
246         }
247
248         /**
249          * Sets the message identifier as determined by the registered policies.
250          * 
251          * @param id message identifier
252          */
253         void setMessageID(const XMLCh* id) {
254             XMLString::release(&m_messageID);
255             m_messageID = XMLString::replicate(id);
256         }
257
258         /**
259          * Sets the message timestamp as determined by the registered policies.
260          * 
261          * @param issueInstant message timestamp
262          */
263         void setIssueInstant(time_t issueInstant) {
264             m_issueInstant = issueInstant;
265         }
266
267         /**
268          * Sets the issuer of the message as determined by the registered policies.
269          * The policy object takes ownership of the Issuer object.
270          * 
271          * @param issuer issuer of the message
272          */
273         void setIssuer(saml2::Issuer* issuer);
274         
275         /**
276          * Sets the metadata for the role the issuer is operating in.
277          * 
278          * @param issuerRole metadata for the role the issuer is operating in
279          */
280         void setIssuerMetadata(const saml2md::RoleDescriptor* issuerRole);
281
282         /**
283          * Sets the security status as determined by the registered policies.
284          * 
285          * @param secure indicates whether the issuer/message has been authenticated
286          */
287         void setSecure(bool secure) {
288             m_secure = secure;
289         }
290         
291         /** Allows override of rules for comparing saml2:Issuer information. */
292         class SAML_API IssuerMatchingPolicy {
293             MAKE_NONCOPYABLE(IssuerMatchingPolicy);
294         public:
295             IssuerMatchingPolicy() {}
296             virtual ~IssuerMatchingPolicy() {}
297             
298             /**
299              * Returns true iff the two operands "match". Applications can override this method to
300              * support non-standard issuer matching for complex policies. 
301              * 
302              * <p>The default implementation does a basic comparison of the XML content, treating
303              * an unsupplied Format as an "entityID".
304              * 
305              * @param issuer1   the first Issuer to match
306              * @param issuer2   the second Issuer to match
307              * @return  true iff the operands match
308              */
309             virtual bool issuerMatches(const saml2::Issuer* issuer1, const saml2::Issuer* issuer2) const;
310         };
311
312         /**
313          * Returns the IssuerMatchingPolicy in effect.
314          * 
315          * @return the effective IssuerMatchingPolicy
316          */
317         const IssuerMatchingPolicy& getIssuerMatchingPolicy() const {
318             return m_matchingPolicy ? *m_matchingPolicy : m_defaultMatching;
319         }
320
321         /**
322          * Sets the IssuerMatchingPolicy in effect. Setting no policy will
323          * cause the simple, default approach to be used.
324          * 
325          * <p>The matching object will be freed by the SecurityPolicy.
326          * 
327          * @param matchingPolicy the IssuerMatchingPolicy to use
328          */
329         void setIssuerMatchingPolicy(IssuerMatchingPolicy* matchingPolicy) {
330             delete m_matchingPolicy;
331             m_matchingPolicy = matchingPolicy;
332         }
333
334     protected:
335         /** A shared matching object that just supports the default matching rules. */
336         static IssuerMatchingPolicy m_defaultMatching;
337
338     private:
339         // information extracted from message 
340         xmltooling::QName* m_messageQName;
341         XMLCh* m_messageID;
342         time_t m_issueInstant;
343         saml2::Issuer* m_issuer;
344         const saml2md::RoleDescriptor* m_issuerRole;
345         bool m_secure;
346         
347         // components governing policy rules
348         IssuerMatchingPolicy* m_matchingPolicy;
349         std::vector<const SecurityPolicyRule*> m_rules;
350         const saml2md::MetadataProvider* m_metadata;
351         xmltooling::QName* m_role;
352         const xmltooling::TrustEngine* m_trust;
353     };
354
355 };
356
357 #if defined (_MSC_VER)
358     #pragma warning( pop )
359 #endif
360
361 #endif /* __saml_secpol_h__ */