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.
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 * Assertions20SchemaValidators.cpp
24 * Schema-based validators for SAML 2.0 Assertions classes
28 #include "exceptions.h"
29 #include "saml2/core/Assertions.h"
31 #include <xmltooling/validation/Validator.h>
32 #include <xmltooling/validation/ValidatorSuite.h>
34 using namespace opensaml::saml2;
35 using namespace opensaml;
36 using namespace xmltooling;
38 using samlconstants::SAML20_NS;
43 XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,Action);
44 XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,AssertionIDRef);
45 XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,AssertionURIRef);
46 XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,Audience);
47 XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,AuthnContextClassRef);
48 XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,AuthnContextDeclRef);
49 XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,AuthenticatingAuthority);
50 XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,NameIDType);
51 XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,NameID);
52 XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,Issuer);
54 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,EncryptedElementType);
55 XMLOBJECTVALIDATOR_REQUIRE(EncryptedElementType,EncryptedData);
56 END_XMLOBJECTVALIDATOR;
58 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,EncryptedID,EncryptedElementType);
59 EncryptedElementTypeSchemaValidator::validate(xmlObject);
60 END_XMLOBJECTVALIDATOR;
62 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,EncryptedAttribute,EncryptedElementType);
63 EncryptedElementTypeSchemaValidator::validate(xmlObject);
64 END_XMLOBJECTVALIDATOR;
66 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,EncryptedAssertion,EncryptedElementType);
67 EncryptedElementTypeSchemaValidator::validate(xmlObject);
68 END_XMLOBJECTVALIDATOR;
70 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,AudienceRestriction);
71 XMLOBJECTVALIDATOR_NONEMPTY(AudienceRestriction,Audience);
72 END_XMLOBJECTVALIDATOR;
74 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,ProxyRestriction);
75 if (ptr->getAudiences().empty()) {
76 XMLOBJECTVALIDATOR_REQUIRE_INTEGER(ProxyRestriction,Count);
78 END_XMLOBJECTVALIDATOR;
80 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,Delegate);
86 if (ptr->getEncryptedID())
89 throw ValidationException("Delegate must contain exactly one identifier element.");
90 END_XMLOBJECTVALIDATOR;
92 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,DelegationRestrictionType);
93 XMLOBJECTVALIDATOR_NONEMPTY(DelegationRestrictionType,Delegate);
94 END_XMLOBJECTVALIDATOR;
96 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,Conditions);
97 if (!ptr->hasChildren()) {
98 XMLOBJECTVALIDATOR_ONEOF(Conditions,NotBefore,NotOnOrAfter);
100 else if (ptr->getOneTimeUses().size() > 1) {
101 throw ValidationException("Multiple OneTimeUse condition elements are not permitted.");
103 else if (ptr->getProxyRestrictions().size() > 1) {
104 throw ValidationException("Multiple ProxyRestriction condition elements are not permitted.");
106 END_XMLOBJECTVALIDATOR;
108 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,KeyInfoConfirmationDataType);
109 XMLOBJECTVALIDATOR_NONEMPTY(KeyInfoConfirmationDataType,KeyInfo);
110 END_XMLOBJECTVALIDATOR;
112 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,SubjectConfirmation);
113 XMLOBJECTVALIDATOR_REQUIRE(SubjectConfirmation,Method);
115 if (ptr->getBaseID())
117 if (ptr->getNameID())
119 if (ptr->getEncryptedID())
122 throw ValidationException("SubjectConfirmation cannot contain multiple identifier elements.");
123 END_XMLOBJECTVALIDATOR;
125 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,Subject);
127 if (ptr->getBaseID())
129 if (ptr->getNameID())
131 if (ptr->getEncryptedID())
134 throw ValidationException("Subject cannot contain multiple identifier elements.");
135 END_XMLOBJECTVALIDATOR;
137 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,SubjectLocality);
138 XMLOBJECTVALIDATOR_ONEOF(SubjectLocality,Address,DNSName);
139 END_XMLOBJECTVALIDATOR;
141 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,AuthnContext);
142 if (!ptr->getAuthnContextClassRef()) {
143 XMLOBJECTVALIDATOR_ONLYONEOF(AuthnContext,AuthnContextDeclRef,AuthnContextDecl);
145 END_XMLOBJECTVALIDATOR;
147 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,AuthnStatement);
148 XMLOBJECTVALIDATOR_REQUIRE(AuthnStatement,AuthnInstant);
149 XMLOBJECTVALIDATOR_REQUIRE(AuthnStatement,AuthnContext);
150 END_XMLOBJECTVALIDATOR;
152 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,Evidence);
153 if (!ptr->hasChildren())
154 throw ValidationException("Evidence must have at least one child element.");
155 END_XMLOBJECTVALIDATOR;
157 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,AuthzDecisionStatement);
158 XMLOBJECTVALIDATOR_REQUIRE(AuthzDecisionStatement,Resource);
159 XMLOBJECTVALIDATOR_REQUIRE(AuthzDecisionStatement,Decision);
160 if (!XMLString::equals(ptr->getDecision(),AuthzDecisionStatement::DECISION_PERMIT) &&
161 !XMLString::equals(ptr->getDecision(),AuthzDecisionStatement::DECISION_DENY) &&
162 !XMLString::equals(ptr->getDecision(),AuthzDecisionStatement::DECISION_INDETERMINATE))
163 throw ValidationException("Decision must be one of Deny, Permit, or Indeterminate.");
164 XMLOBJECTVALIDATOR_NONEMPTY(AuthzDecisionStatement,Action);
165 END_XMLOBJECTVALIDATOR;
167 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,Attribute);
168 XMLOBJECTVALIDATOR_REQUIRE(Attribute,Name);
169 END_XMLOBJECTVALIDATOR;
171 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,AttributeStatement);
172 XMLOBJECTVALIDATOR_NONEMPTY(AttributeStatement,Attribute);
173 END_XMLOBJECTVALIDATOR;
175 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,Assertion);
176 XMLOBJECTVALIDATOR_REQUIRE(Assertion,Version);
177 if (!XMLString::equals(samlconstants::SAML20_VERSION, ptr->getVersion()))
178 throw ValidationException("Assertion has wrong SAML Version.");
179 XMLOBJECTVALIDATOR_REQUIRE(Assertion,ID);
180 XMLOBJECTVALIDATOR_REQUIRE(Assertion,IssueInstant);
181 XMLOBJECTVALIDATOR_REQUIRE(Assertion,Issuer);
182 if ((!ptr->getAuthnStatements().empty() ||
183 !ptr->getAttributeStatements().empty() ||
184 !ptr->getAuthzDecisionStatements().empty()) && !ptr->getSubject())
185 throw ValidationException("Assertion with standard statements must have a Subject.");
186 END_XMLOBJECTVALIDATOR;
188 class SAML_DLLLOCAL checkWildcardNS {
190 void operator()(const XMLObject* xmlObject) const {
191 const XMLCh* ns=xmlObject->getElementQName().getNamespaceURI();
192 if (XMLString::equals(ns,SAML20_NS) || !ns || !*ns) {
193 throw ValidationException(
194 "Object contains an illegal extension child element ($1).",
195 params(1,xmlObject->getElementQName().toString().c_str())
201 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,Advice);
202 const vector<XMLObject*>& anys=ptr->getUnknownXMLObjects();
203 for_each(anys.begin(),anys.end(),checkWildcardNS());
204 END_XMLOBJECTVALIDATOR;
209 #define REGISTER_ELEMENT(cname) \
210 q=xmltooling::QName(SAML20_NS,cname::LOCAL_NAME); \
211 XMLObjectBuilder::registerBuilder(q,new cname##Builder()); \
212 SchemaValidators.registerValidator(q,new cname##SchemaValidator())
214 #define REGISTER_TYPE(cname) \
215 q=xmltooling::QName(SAML20_NS,cname::TYPE_NAME); \
216 XMLObjectBuilder::registerBuilder(q,new cname##Builder()); \
217 SchemaValidators.registerValidator(q,new cname##SchemaValidator())
219 #define REGISTER_ELEMENT_NOVAL(cname) \
220 q=xmltooling::QName(SAML20_NS,cname::LOCAL_NAME); \
221 XMLObjectBuilder::registerBuilder(q,new cname##Builder());
223 #define REGISTER_TYPE_NOVAL(cname) \
224 q=xmltooling::QName(SAML20_NS,cname::TYPE_NAME); \
225 XMLObjectBuilder::registerBuilder(q,new cname##Builder());
227 void opensaml::saml2::registerAssertionClasses() {
229 REGISTER_ELEMENT(Action);
230 REGISTER_ELEMENT(Advice);
231 REGISTER_ELEMENT(Assertion);
232 REGISTER_ELEMENT(AssertionIDRef);
233 REGISTER_ELEMENT(AssertionURIRef);
234 REGISTER_ELEMENT(Attribute);
235 REGISTER_ELEMENT(AttributeStatement);
236 REGISTER_ELEMENT_NOVAL(AttributeValue);
237 REGISTER_ELEMENT(Audience);
238 REGISTER_ELEMENT(AudienceRestriction);
239 REGISTER_ELEMENT(AuthenticatingAuthority);
240 REGISTER_ELEMENT(AuthnContext);
241 REGISTER_ELEMENT(AuthnContextClassRef);
242 REGISTER_ELEMENT_NOVAL(AuthnContextDecl);
243 REGISTER_ELEMENT(AuthnContextDeclRef);
244 REGISTER_ELEMENT(AuthnStatement);
245 REGISTER_ELEMENT(AuthzDecisionStatement);
246 REGISTER_ELEMENT_NOVAL(Condition);
247 REGISTER_ELEMENT(Conditions);
248 REGISTER_ELEMENT(EncryptedAssertion);
249 REGISTER_ELEMENT(EncryptedAttribute);
250 REGISTER_ELEMENT(EncryptedID);
251 REGISTER_ELEMENT(Evidence);
252 REGISTER_ELEMENT(Issuer);
253 REGISTER_ELEMENT(NameID);
254 REGISTER_ELEMENT_NOVAL(OneTimeUse);
255 REGISTER_ELEMENT(ProxyRestriction);
256 REGISTER_ELEMENT_NOVAL(Statement);
257 REGISTER_ELEMENT(Subject);
258 REGISTER_ELEMENT(SubjectConfirmation);
259 REGISTER_ELEMENT_NOVAL(SubjectConfirmationData);
260 REGISTER_ELEMENT(SubjectLocality);
261 REGISTER_TYPE(Action);
262 REGISTER_TYPE(Advice);
263 REGISTER_TYPE(Assertion);
264 REGISTER_TYPE(Attribute);
265 REGISTER_TYPE(AttributeStatement);
266 REGISTER_TYPE(AudienceRestriction);
267 REGISTER_TYPE(AuthnContext);
268 REGISTER_TYPE(AuthnStatement);
269 REGISTER_TYPE(AuthzDecisionStatement);
270 REGISTER_TYPE(Conditions);
271 REGISTER_TYPE(Evidence);
272 REGISTER_TYPE(KeyInfoConfirmationDataType);
273 REGISTER_TYPE(NameIDType);
274 REGISTER_TYPE_NOVAL(OneTimeUse);
275 REGISTER_TYPE(ProxyRestriction);
276 REGISTER_TYPE(Subject);
277 REGISTER_TYPE(SubjectConfirmation);
278 REGISTER_TYPE(SubjectLocality);
280 q=xmltooling::QName(samlconstants::SAML20_DELEGATION_CONDITION_NS,Delegate::LOCAL_NAME);
281 XMLObjectBuilder::registerBuilder(q,new DelegateBuilder());
282 SchemaValidators.registerValidator(q,new DelegateSchemaValidator());
283 q=xmltooling::QName(samlconstants::SAML20_DELEGATION_CONDITION_NS,Delegate::TYPE_NAME);
284 XMLObjectBuilder::registerBuilder(q,new DelegateBuilder());
285 SchemaValidators.registerValidator(q,new DelegateSchemaValidator());
287 q=xmltooling::QName(samlconstants::SAML20_DELEGATION_CONDITION_NS,DelegationRestrictionType::TYPE_NAME);
288 XMLObjectBuilder::registerBuilder(q,new DelegationRestrictionTypeBuilder());
289 SchemaValidators.registerValidator(q,new DelegationRestrictionTypeSchemaValidator());