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