Add XML objects for DelegationRestriction and EntityAttributes extensions.
[shibboleth/cpp-opensaml.git] / saml / saml2 / core / impl / Assertions20SchemaValidators.cpp
1 /*
2 *  Copyright 2001-2007 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  * Assertions20SchemaValidators.cpp
19  *
20  * Schema-based validators for SAML 2.0 Assertions classes
21  */
22
23 #include "internal.h"
24 #include "exceptions.h"
25 #include "saml2/core/Assertions.h"
26
27 #include <xmltooling/validation/ValidatorSuite.h>
28
29 using namespace opensaml::saml2;
30 using namespace opensaml;
31 using namespace xmltooling;
32 using namespace std;
33 using samlconstants::SAML20_NS;
34
35 namespace opensaml {
36     namespace saml2 {
37
38         XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,Action);
39         XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,AssertionIDRef);
40         XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,AssertionURIRef);
41         XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,Audience);
42         XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,AuthnContextClassRef);
43         XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,AuthnContextDeclRef);
44         XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,AuthenticatingAuthority);
45         XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,NameIDType);
46         XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,NameID);
47         XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,Issuer);
48
49         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,EncryptedElementType);
50             XMLOBJECTVALIDATOR_REQUIRE(EncryptedElementType,EncryptedData);
51         END_XMLOBJECTVALIDATOR;
52
53         BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,EncryptedID,EncryptedElementType);
54             EncryptedElementTypeSchemaValidator::validate(xmlObject);
55         END_XMLOBJECTVALIDATOR;
56
57         BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,EncryptedAttribute,EncryptedElementType);
58             EncryptedElementTypeSchemaValidator::validate(xmlObject);
59         END_XMLOBJECTVALIDATOR;
60
61         BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,EncryptedAssertion,EncryptedElementType);
62             EncryptedElementTypeSchemaValidator::validate(xmlObject);
63         END_XMLOBJECTVALIDATOR;
64
65         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,AudienceRestriction);
66             XMLOBJECTVALIDATOR_NONEMPTY(AudienceRestriction,Audience);
67         END_XMLOBJECTVALIDATOR;
68
69         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,ProxyRestriction);
70             if (ptr->getAudiences().empty()) {
71                 XMLOBJECTVALIDATOR_REQUIRE_INTEGER(ProxyRestriction,Count);
72             }
73         END_XMLOBJECTVALIDATOR;
74
75         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,Delegate);
76             int count=0;
77             if (ptr->getBaseID())
78                 count++;
79             if (ptr->getNameID())
80                 count++;
81             if (ptr->getEncryptedID())
82                 count++;
83             if (count != 1)
84                 throw ValidationException("Delegate must contain exactly one identifier element.");
85         END_XMLOBJECTVALIDATOR;
86
87         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,DelegationRestrictionType);
88             XMLOBJECTVALIDATOR_NONEMPTY(DelegationRestrictionType,Delegate);
89         END_XMLOBJECTVALIDATOR;
90
91         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,Conditions);
92             if (!ptr->hasChildren()) {
93                 XMLOBJECTVALIDATOR_ONEOF(Conditions,NotBefore,NotOnOrAfter);
94             }
95         END_XMLOBJECTVALIDATOR;
96
97         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,KeyInfoConfirmationDataType);
98             XMLOBJECTVALIDATOR_NONEMPTY(KeyInfoConfirmationDataType,KeyInfo);
99         END_XMLOBJECTVALIDATOR;
100
101         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,SubjectConfirmation);
102             XMLOBJECTVALIDATOR_REQUIRE(SubjectConfirmation,Method);
103             int count=0;
104             if (ptr->getBaseID())
105                 count++;
106             if (ptr->getNameID())
107                 count++;
108             if (ptr->getEncryptedID())
109                 count++;
110             if (count > 1)
111                 throw ValidationException("SubjectConfirmation cannot contain multiple identifier elements.");
112         END_XMLOBJECTVALIDATOR;
113
114         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,Subject);
115             int count=0;
116             if (ptr->getBaseID())
117                 count++;
118             if (ptr->getNameID())
119                 count++;
120             if (ptr->getEncryptedID())
121                 count++;
122             if (count > 1)
123                 throw ValidationException("Subject cannot contain multiple identifier elements.");
124         END_XMLOBJECTVALIDATOR;
125
126         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,SubjectLocality);
127             XMLOBJECTVALIDATOR_ONEOF(SubjectLocality,Address,DNSName);
128         END_XMLOBJECTVALIDATOR;
129
130         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,AuthnContext);
131             if (!ptr->getAuthnContextClassRef()) {
132                 XMLOBJECTVALIDATOR_ONLYONEOF(AuthnContext,AuthnContextDeclRef,AuthnContextDecl);
133             }
134         END_XMLOBJECTVALIDATOR;
135
136         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,AuthnStatement);
137             XMLOBJECTVALIDATOR_REQUIRE(AuthnStatement,AuthnInstant);
138             XMLOBJECTVALIDATOR_REQUIRE(AuthnStatement,AuthnContext);
139         END_XMLOBJECTVALIDATOR;
140
141         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,Evidence);
142             if (!ptr->hasChildren())
143                 throw ValidationException("Evidence must have at least one child element.");
144         END_XMLOBJECTVALIDATOR;
145
146         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,AuthzDecisionStatement);
147             XMLOBJECTVALIDATOR_REQUIRE(AuthzDecisionStatement,Resource);
148             XMLOBJECTVALIDATOR_REQUIRE(AuthzDecisionStatement,Decision);
149             if (!XMLString::equals(ptr->getDecision(),AuthzDecisionStatement::DECISION_PERMIT) &&
150                 !XMLString::equals(ptr->getDecision(),AuthzDecisionStatement::DECISION_DENY) &&
151                 !XMLString::equals(ptr->getDecision(),AuthzDecisionStatement::DECISION_INDETERMINATE))
152                 throw ValidationException("Decision must be one of Deny, Permit, or Indeterminate.");
153             XMLOBJECTVALIDATOR_NONEMPTY(AuthzDecisionStatement,Action);
154         END_XMLOBJECTVALIDATOR;
155
156         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,Attribute);
157             XMLOBJECTVALIDATOR_REQUIRE(Attribute,Name);
158         END_XMLOBJECTVALIDATOR;
159
160         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,AttributeStatement);
161             XMLOBJECTVALIDATOR_NONEMPTY(AttributeStatement,Attribute);
162         END_XMLOBJECTVALIDATOR;
163
164         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,Assertion);
165             XMLOBJECTVALIDATOR_REQUIRE(Assertion,Version);
166             if (!XMLString::equals(samlconstants::SAML20_VERSION, ptr->getVersion()))
167                 throw ValidationException("Assertion has wrong SAML Version.");
168             XMLOBJECTVALIDATOR_REQUIRE(Assertion,ID);
169             XMLOBJECTVALIDATOR_REQUIRE(Assertion,IssueInstant);
170             XMLOBJECTVALIDATOR_REQUIRE(Assertion,Issuer);
171             if ((!ptr->getAuthnStatements().empty() ||
172                 !ptr->getAttributeStatements().empty() ||
173                 !ptr->getAuthzDecisionStatements().empty()) && !ptr->getSubject())
174                 throw ValidationException("Assertion with standard statements must have a Subject.");
175         END_XMLOBJECTVALIDATOR;
176
177         class SAML_DLLLOCAL checkWildcardNS {
178         public:
179             void operator()(const XMLObject* xmlObject) const {
180                 const XMLCh* ns=xmlObject->getElementQName().getNamespaceURI();
181                 if (XMLString::equals(ns,SAML20_NS) || !ns || !*ns) {
182                     throw ValidationException(
183                         "Object contains an illegal extension child element ($1).",
184                         params(1,xmlObject->getElementQName().toString().c_str())
185                         );
186                 }
187             }
188         };
189
190         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,Advice);
191             const vector<XMLObject*>& anys=ptr->getUnknownXMLObjects();
192             for_each(anys.begin(),anys.end(),checkWildcardNS());
193         END_XMLOBJECTVALIDATOR;
194
195     };
196 };
197
198 #define REGISTER_ELEMENT(cname) \
199     q=xmltooling::QName(SAML20_NS,cname::LOCAL_NAME); \
200     XMLObjectBuilder::registerBuilder(q,new cname##Builder()); \
201     SchemaValidators.registerValidator(q,new cname##SchemaValidator())
202
203 #define REGISTER_TYPE(cname) \
204     q=xmltooling::QName(SAML20_NS,cname::TYPE_NAME); \
205     XMLObjectBuilder::registerBuilder(q,new cname##Builder()); \
206     SchemaValidators.registerValidator(q,new cname##SchemaValidator())
207
208 #define REGISTER_ELEMENT_NOVAL(cname) \
209     q=xmltooling::QName(SAML20_NS,cname::LOCAL_NAME); \
210     XMLObjectBuilder::registerBuilder(q,new cname##Builder());
211
212 #define REGISTER_TYPE_NOVAL(cname) \
213     q=xmltooling::QName(SAML20_NS,cname::TYPE_NAME); \
214     XMLObjectBuilder::registerBuilder(q,new cname##Builder());
215
216 void opensaml::saml2::registerAssertionClasses() {
217     xmltooling::QName q;
218     REGISTER_ELEMENT(Action);
219     REGISTER_ELEMENT(Advice);
220     REGISTER_ELEMENT(Assertion);
221     REGISTER_ELEMENT(AssertionIDRef);
222     REGISTER_ELEMENT(AssertionURIRef);
223     REGISTER_ELEMENT(Attribute);
224     REGISTER_ELEMENT(AttributeStatement);
225     REGISTER_ELEMENT_NOVAL(AttributeValue);
226     REGISTER_ELEMENT(Audience);
227     REGISTER_ELEMENT(AudienceRestriction);
228     REGISTER_ELEMENT(AuthenticatingAuthority);
229     REGISTER_ELEMENT(AuthnContext);
230     REGISTER_ELEMENT(AuthnContextClassRef);
231     REGISTER_ELEMENT_NOVAL(AuthnContextDecl);
232     REGISTER_ELEMENT(AuthnContextDeclRef);
233     REGISTER_ELEMENT(AuthnStatement);
234     REGISTER_ELEMENT(AuthzDecisionStatement);
235     REGISTER_ELEMENT_NOVAL(Condition);
236     REGISTER_ELEMENT(Conditions);
237     REGISTER_ELEMENT(EncryptedAssertion);
238     REGISTER_ELEMENT(EncryptedAttribute);
239     REGISTER_ELEMENT(EncryptedID);
240     REGISTER_ELEMENT(Evidence);
241     REGISTER_ELEMENT(Issuer);
242     REGISTER_ELEMENT(NameID);
243     REGISTER_ELEMENT_NOVAL(OneTimeUse);
244     REGISTER_ELEMENT(ProxyRestriction);
245     REGISTER_ELEMENT_NOVAL(Statement);
246     REGISTER_ELEMENT(Subject);
247     REGISTER_ELEMENT(SubjectConfirmation);
248     REGISTER_ELEMENT_NOVAL(SubjectConfirmationData);
249     REGISTER_ELEMENT(SubjectLocality);
250     REGISTER_TYPE(Action);
251     REGISTER_TYPE(Advice);
252     REGISTER_TYPE(Assertion);
253     REGISTER_TYPE(Attribute);
254     REGISTER_TYPE(AttributeStatement);
255     REGISTER_TYPE(AudienceRestriction);
256     REGISTER_TYPE(AuthnContext);
257     REGISTER_TYPE(AuthnStatement);
258     REGISTER_TYPE(AuthzDecisionStatement);
259     REGISTER_TYPE(Conditions);
260     REGISTER_TYPE(Evidence);
261     REGISTER_TYPE(KeyInfoConfirmationDataType);
262     REGISTER_TYPE(NameIDType);
263     REGISTER_TYPE_NOVAL(OneTimeUse);
264     REGISTER_TYPE(ProxyRestriction);
265     REGISTER_TYPE(Subject);
266     REGISTER_TYPE(SubjectConfirmation);
267     REGISTER_TYPE(SubjectLocality);
268
269     q=xmltooling::QName(samlconstants::SAML20_DELEGATION_CONDITION_NS,Delegate::LOCAL_NAME);
270     XMLObjectBuilder::registerBuilder(q,new DelegateBuilder());
271     SchemaValidators.registerValidator(q,new DelegateSchemaValidator());
272     q=xmltooling::QName(samlconstants::SAML20_DELEGATION_CONDITION_NS,Delegate::TYPE_NAME);
273     XMLObjectBuilder::registerBuilder(q,new DelegateBuilder());
274     SchemaValidators.registerValidator(q,new DelegateSchemaValidator());
275
276     q=xmltooling::QName(samlconstants::SAML20_DELEGATION_CONDITION_NS,DelegationRestrictionType::TYPE_NAME);
277     XMLObjectBuilder::registerBuilder(q,new DelegationRestrictionTypeBuilder());
278     SchemaValidators.registerValidator(q,new DelegationRestrictionTypeSchemaValidator());
279 }