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->getOneTimeUses().size() > 1) {
98 throw ValidationException("Multiple OneTimeUse condition elements are not permitted.");
100 else if (ptr->getProxyRestrictions().size() > 1) {
101 throw ValidationException("Multiple ProxyRestriction condition elements are not permitted.");
103 END_XMLOBJECTVALIDATOR;
105 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,KeyInfoConfirmationDataType);
106 XMLOBJECTVALIDATOR_NONEMPTY(KeyInfoConfirmationDataType,KeyInfo);
107 END_XMLOBJECTVALIDATOR;
109 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,SubjectConfirmation);
110 XMLOBJECTVALIDATOR_REQUIRE(SubjectConfirmation,Method);
112 if (ptr->getBaseID())
114 if (ptr->getNameID())
116 if (ptr->getEncryptedID())
119 throw ValidationException("SubjectConfirmation cannot contain multiple identifier elements.");
120 END_XMLOBJECTVALIDATOR;
122 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,Subject);
124 if (ptr->getBaseID())
126 if (ptr->getNameID())
128 if (ptr->getEncryptedID())
131 throw ValidationException("Subject cannot contain multiple identifier elements.");
132 END_XMLOBJECTVALIDATOR;
134 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,SubjectLocality);
135 XMLOBJECTVALIDATOR_ONEOF(SubjectLocality,Address,DNSName);
136 END_XMLOBJECTVALIDATOR;
138 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,AuthnContext);
139 if (!ptr->getAuthnContextClassRef()) {
140 XMLOBJECTVALIDATOR_ONLYONEOF(AuthnContext,AuthnContextDeclRef,AuthnContextDecl);
142 END_XMLOBJECTVALIDATOR;
144 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,AuthnStatement);
145 XMLOBJECTVALIDATOR_REQUIRE(AuthnStatement,AuthnInstant);
146 XMLOBJECTVALIDATOR_REQUIRE(AuthnStatement,AuthnContext);
147 END_XMLOBJECTVALIDATOR;
149 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,Evidence);
150 if (!ptr->hasChildren())
151 throw ValidationException("Evidence must have at least one child element.");
152 END_XMLOBJECTVALIDATOR;
154 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,AuthzDecisionStatement);
155 XMLOBJECTVALIDATOR_REQUIRE(AuthzDecisionStatement,Resource);
156 XMLOBJECTVALIDATOR_REQUIRE(AuthzDecisionStatement,Decision);
157 if (!XMLString::equals(ptr->getDecision(),AuthzDecisionStatement::DECISION_PERMIT) &&
158 !XMLString::equals(ptr->getDecision(),AuthzDecisionStatement::DECISION_DENY) &&
159 !XMLString::equals(ptr->getDecision(),AuthzDecisionStatement::DECISION_INDETERMINATE))
160 throw ValidationException("Decision must be one of Deny, Permit, or Indeterminate.");
161 XMLOBJECTVALIDATOR_NONEMPTY(AuthzDecisionStatement,Action);
162 END_XMLOBJECTVALIDATOR;
164 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,Attribute);
165 XMLOBJECTVALIDATOR_REQUIRE(Attribute,Name);
166 END_XMLOBJECTVALIDATOR;
168 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,AttributeStatement);
169 XMLOBJECTVALIDATOR_NONEMPTY(AttributeStatement,Attribute);
170 END_XMLOBJECTVALIDATOR;
172 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,Assertion);
173 XMLOBJECTVALIDATOR_REQUIRE(Assertion,Version);
174 if (!XMLString::equals(samlconstants::SAML20_VERSION, ptr->getVersion()))
175 throw ValidationException("Assertion has wrong SAML Version.");
176 XMLOBJECTVALIDATOR_REQUIRE(Assertion,ID);
177 XMLOBJECTVALIDATOR_REQUIRE(Assertion,IssueInstant);
178 XMLOBJECTVALIDATOR_REQUIRE(Assertion,Issuer);
179 if ((!ptr->getAuthnStatements().empty() ||
180 !ptr->getAttributeStatements().empty() ||
181 !ptr->getAuthzDecisionStatements().empty()) && !ptr->getSubject())
182 throw ValidationException("Assertion with standard statements must have a Subject.");
183 END_XMLOBJECTVALIDATOR;
185 class SAML_DLLLOCAL checkWildcardNS {
187 void operator()(const XMLObject* xmlObject) const {
188 const XMLCh* ns=xmlObject->getElementQName().getNamespaceURI();
189 if (XMLString::equals(ns,SAML20_NS) || !ns || !*ns) {
190 throw ValidationException(
191 "Object contains an illegal extension child element ($1).",
192 params(1,xmlObject->getElementQName().toString().c_str())
198 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,Advice);
199 const vector<XMLObject*>& anys=ptr->getUnknownXMLObjects();
200 for_each(anys.begin(),anys.end(),checkWildcardNS());
201 END_XMLOBJECTVALIDATOR;
206 #define REGISTER_ELEMENT(cname) \
207 q=xmltooling::QName(SAML20_NS,cname::LOCAL_NAME); \
208 XMLObjectBuilder::registerBuilder(q,new cname##Builder()); \
209 SchemaValidators.registerValidator(q,new cname##SchemaValidator())
211 #define REGISTER_TYPE(cname) \
212 q=xmltooling::QName(SAML20_NS,cname::TYPE_NAME); \
213 XMLObjectBuilder::registerBuilder(q,new cname##Builder()); \
214 SchemaValidators.registerValidator(q,new cname##SchemaValidator())
216 #define REGISTER_ELEMENT_NOVAL(cname) \
217 q=xmltooling::QName(SAML20_NS,cname::LOCAL_NAME); \
218 XMLObjectBuilder::registerBuilder(q,new cname##Builder());
220 #define REGISTER_TYPE_NOVAL(cname) \
221 q=xmltooling::QName(SAML20_NS,cname::TYPE_NAME); \
222 XMLObjectBuilder::registerBuilder(q,new cname##Builder());
224 void opensaml::saml2::registerAssertionClasses() {
226 REGISTER_ELEMENT(Action);
227 REGISTER_ELEMENT(Advice);
228 REGISTER_ELEMENT(Assertion);
229 REGISTER_ELEMENT(AssertionIDRef);
230 REGISTER_ELEMENT(AssertionURIRef);
231 REGISTER_ELEMENT(Attribute);
232 REGISTER_ELEMENT(AttributeStatement);
233 REGISTER_ELEMENT_NOVAL(AttributeValue);
234 REGISTER_ELEMENT(Audience);
235 REGISTER_ELEMENT(AudienceRestriction);
236 REGISTER_ELEMENT(AuthenticatingAuthority);
237 REGISTER_ELEMENT(AuthnContext);
238 REGISTER_ELEMENT(AuthnContextClassRef);
239 REGISTER_ELEMENT_NOVAL(AuthnContextDecl);
240 REGISTER_ELEMENT(AuthnContextDeclRef);
241 REGISTER_ELEMENT(AuthnStatement);
242 REGISTER_ELEMENT(AuthzDecisionStatement);
243 REGISTER_ELEMENT_NOVAL(Condition);
244 REGISTER_ELEMENT(Conditions);
245 REGISTER_ELEMENT(EncryptedAssertion);
246 REGISTER_ELEMENT(EncryptedAttribute);
247 REGISTER_ELEMENT(EncryptedID);
248 REGISTER_ELEMENT(Evidence);
249 REGISTER_ELEMENT(Issuer);
250 REGISTER_ELEMENT(NameID);
251 REGISTER_ELEMENT_NOVAL(OneTimeUse);
252 REGISTER_ELEMENT(ProxyRestriction);
253 REGISTER_ELEMENT_NOVAL(Statement);
254 REGISTER_ELEMENT(Subject);
255 REGISTER_ELEMENT(SubjectConfirmation);
256 REGISTER_ELEMENT_NOVAL(SubjectConfirmationData);
257 REGISTER_ELEMENT(SubjectLocality);
258 REGISTER_TYPE(Action);
259 REGISTER_TYPE(Advice);
260 REGISTER_TYPE(Assertion);
261 REGISTER_TYPE(Attribute);
262 REGISTER_TYPE(AttributeStatement);
263 REGISTER_TYPE(AudienceRestriction);
264 REGISTER_TYPE(AuthnContext);
265 REGISTER_TYPE(AuthnStatement);
266 REGISTER_TYPE(AuthzDecisionStatement);
267 REGISTER_TYPE(Conditions);
268 REGISTER_TYPE(Evidence);
269 REGISTER_TYPE(KeyInfoConfirmationDataType);
270 REGISTER_TYPE(NameIDType);
271 REGISTER_TYPE_NOVAL(OneTimeUse);
272 REGISTER_TYPE(ProxyRestriction);
273 REGISTER_TYPE(Subject);
274 REGISTER_TYPE(SubjectConfirmation);
275 REGISTER_TYPE(SubjectLocality);
277 q=xmltooling::QName(samlconstants::SAML20_DELEGATION_CONDITION_NS,Delegate::LOCAL_NAME);
278 XMLObjectBuilder::registerBuilder(q,new DelegateBuilder());
279 SchemaValidators.registerValidator(q,new DelegateSchemaValidator());
280 q=xmltooling::QName(samlconstants::SAML20_DELEGATION_CONDITION_NS,Delegate::TYPE_NAME);
281 XMLObjectBuilder::registerBuilder(q,new DelegateBuilder());
282 SchemaValidators.registerValidator(q,new DelegateSchemaValidator());
284 q=xmltooling::QName(samlconstants::SAML20_DELEGATION_CONDITION_NS,DelegationRestrictionType::TYPE_NAME);
285 XMLObjectBuilder::registerBuilder(q,new DelegationRestrictionTypeBuilder());
286 SchemaValidators.registerValidator(q,new DelegationRestrictionTypeSchemaValidator());