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/ValidatorSuite.h>
29 using namespace opensaml::saml2;
30 using namespace opensaml;
31 using namespace xmltooling;
33 using samlconstants::SAML20_NS;
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);
49 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,EncryptedElementType);
50 XMLOBJECTVALIDATOR_REQUIRE(EncryptedElementType,EncryptedData);
51 END_XMLOBJECTVALIDATOR;
53 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,EncryptedID,EncryptedElementType);
54 EncryptedElementTypeSchemaValidator::validate(xmlObject);
55 END_XMLOBJECTVALIDATOR;
57 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,EncryptedAttribute,EncryptedElementType);
58 EncryptedElementTypeSchemaValidator::validate(xmlObject);
59 END_XMLOBJECTVALIDATOR;
61 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,EncryptedAssertion,EncryptedElementType);
62 EncryptedElementTypeSchemaValidator::validate(xmlObject);
63 END_XMLOBJECTVALIDATOR;
65 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,AudienceRestriction);
66 XMLOBJECTVALIDATOR_NONEMPTY(AudienceRestriction,Audience);
67 END_XMLOBJECTVALIDATOR;
69 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,ProxyRestriction);
70 if (ptr->getAudiences().empty()) {
71 XMLOBJECTVALIDATOR_REQUIRE_INTEGER(ProxyRestriction,Count);
73 END_XMLOBJECTVALIDATOR;
75 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,Delegate);
81 if (ptr->getEncryptedID())
84 throw ValidationException("Delegate must contain exactly one identifier element.");
85 END_XMLOBJECTVALIDATOR;
87 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,DelegationRestrictionType);
88 XMLOBJECTVALIDATOR_NONEMPTY(DelegationRestrictionType,Delegate);
89 END_XMLOBJECTVALIDATOR;
91 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,Conditions);
92 if (!ptr->hasChildren()) {
93 XMLOBJECTVALIDATOR_ONEOF(Conditions,NotBefore,NotOnOrAfter);
95 else if (ptr->getOneTimeUses().size() > 1) {
96 throw ValidationException("Multiple OneTimeUse condition elements are not permitted.");
98 else if (ptr->getProxyRestrictions().size() > 1) {
99 throw ValidationException("Multiple ProxyRestriction condition elements are not permitted.");
101 END_XMLOBJECTVALIDATOR;
103 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,KeyInfoConfirmationDataType);
104 XMLOBJECTVALIDATOR_NONEMPTY(KeyInfoConfirmationDataType,KeyInfo);
105 END_XMLOBJECTVALIDATOR;
107 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,SubjectConfirmation);
108 XMLOBJECTVALIDATOR_REQUIRE(SubjectConfirmation,Method);
110 if (ptr->getBaseID())
112 if (ptr->getNameID())
114 if (ptr->getEncryptedID())
117 throw ValidationException("SubjectConfirmation cannot contain multiple identifier elements.");
118 END_XMLOBJECTVALIDATOR;
120 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,Subject);
122 if (ptr->getBaseID())
124 if (ptr->getNameID())
126 if (ptr->getEncryptedID())
129 throw ValidationException("Subject cannot contain multiple identifier elements.");
130 END_XMLOBJECTVALIDATOR;
132 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,SubjectLocality);
133 XMLOBJECTVALIDATOR_ONEOF(SubjectLocality,Address,DNSName);
134 END_XMLOBJECTVALIDATOR;
136 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,AuthnContext);
137 if (!ptr->getAuthnContextClassRef()) {
138 XMLOBJECTVALIDATOR_ONLYONEOF(AuthnContext,AuthnContextDeclRef,AuthnContextDecl);
140 END_XMLOBJECTVALIDATOR;
142 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,AuthnStatement);
143 XMLOBJECTVALIDATOR_REQUIRE(AuthnStatement,AuthnInstant);
144 XMLOBJECTVALIDATOR_REQUIRE(AuthnStatement,AuthnContext);
145 END_XMLOBJECTVALIDATOR;
147 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,Evidence);
148 if (!ptr->hasChildren())
149 throw ValidationException("Evidence must have at least one child element.");
150 END_XMLOBJECTVALIDATOR;
152 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,AuthzDecisionStatement);
153 XMLOBJECTVALIDATOR_REQUIRE(AuthzDecisionStatement,Resource);
154 XMLOBJECTVALIDATOR_REQUIRE(AuthzDecisionStatement,Decision);
155 if (!XMLString::equals(ptr->getDecision(),AuthzDecisionStatement::DECISION_PERMIT) &&
156 !XMLString::equals(ptr->getDecision(),AuthzDecisionStatement::DECISION_DENY) &&
157 !XMLString::equals(ptr->getDecision(),AuthzDecisionStatement::DECISION_INDETERMINATE))
158 throw ValidationException("Decision must be one of Deny, Permit, or Indeterminate.");
159 XMLOBJECTVALIDATOR_NONEMPTY(AuthzDecisionStatement,Action);
160 END_XMLOBJECTVALIDATOR;
162 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,Attribute);
163 XMLOBJECTVALIDATOR_REQUIRE(Attribute,Name);
164 END_XMLOBJECTVALIDATOR;
166 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,AttributeStatement);
167 XMLOBJECTVALIDATOR_NONEMPTY(AttributeStatement,Attribute);
168 END_XMLOBJECTVALIDATOR;
170 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,Assertion);
171 XMLOBJECTVALIDATOR_REQUIRE(Assertion,Version);
172 if (!XMLString::equals(samlconstants::SAML20_VERSION, ptr->getVersion()))
173 throw ValidationException("Assertion has wrong SAML Version.");
174 XMLOBJECTVALIDATOR_REQUIRE(Assertion,ID);
175 XMLOBJECTVALIDATOR_REQUIRE(Assertion,IssueInstant);
176 XMLOBJECTVALIDATOR_REQUIRE(Assertion,Issuer);
177 if ((!ptr->getAuthnStatements().empty() ||
178 !ptr->getAttributeStatements().empty() ||
179 !ptr->getAuthzDecisionStatements().empty()) && !ptr->getSubject())
180 throw ValidationException("Assertion with standard statements must have a Subject.");
181 END_XMLOBJECTVALIDATOR;
183 class SAML_DLLLOCAL checkWildcardNS {
185 void operator()(const XMLObject* xmlObject) const {
186 const XMLCh* ns=xmlObject->getElementQName().getNamespaceURI();
187 if (XMLString::equals(ns,SAML20_NS) || !ns || !*ns) {
188 throw ValidationException(
189 "Object contains an illegal extension child element ($1).",
190 params(1,xmlObject->getElementQName().toString().c_str())
196 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,Advice);
197 const vector<XMLObject*>& anys=ptr->getUnknownXMLObjects();
198 for_each(anys.begin(),anys.end(),checkWildcardNS());
199 END_XMLOBJECTVALIDATOR;
204 #define REGISTER_ELEMENT(cname) \
205 q=xmltooling::QName(SAML20_NS,cname::LOCAL_NAME); \
206 XMLObjectBuilder::registerBuilder(q,new cname##Builder()); \
207 SchemaValidators.registerValidator(q,new cname##SchemaValidator())
209 #define REGISTER_TYPE(cname) \
210 q=xmltooling::QName(SAML20_NS,cname::TYPE_NAME); \
211 XMLObjectBuilder::registerBuilder(q,new cname##Builder()); \
212 SchemaValidators.registerValidator(q,new cname##SchemaValidator())
214 #define REGISTER_ELEMENT_NOVAL(cname) \
215 q=xmltooling::QName(SAML20_NS,cname::LOCAL_NAME); \
216 XMLObjectBuilder::registerBuilder(q,new cname##Builder());
218 #define REGISTER_TYPE_NOVAL(cname) \
219 q=xmltooling::QName(SAML20_NS,cname::TYPE_NAME); \
220 XMLObjectBuilder::registerBuilder(q,new cname##Builder());
222 void opensaml::saml2::registerAssertionClasses() {
224 REGISTER_ELEMENT(Action);
225 REGISTER_ELEMENT(Advice);
226 REGISTER_ELEMENT(Assertion);
227 REGISTER_ELEMENT(AssertionIDRef);
228 REGISTER_ELEMENT(AssertionURIRef);
229 REGISTER_ELEMENT(Attribute);
230 REGISTER_ELEMENT(AttributeStatement);
231 REGISTER_ELEMENT_NOVAL(AttributeValue);
232 REGISTER_ELEMENT(Audience);
233 REGISTER_ELEMENT(AudienceRestriction);
234 REGISTER_ELEMENT(AuthenticatingAuthority);
235 REGISTER_ELEMENT(AuthnContext);
236 REGISTER_ELEMENT(AuthnContextClassRef);
237 REGISTER_ELEMENT_NOVAL(AuthnContextDecl);
238 REGISTER_ELEMENT(AuthnContextDeclRef);
239 REGISTER_ELEMENT(AuthnStatement);
240 REGISTER_ELEMENT(AuthzDecisionStatement);
241 REGISTER_ELEMENT_NOVAL(Condition);
242 REGISTER_ELEMENT(Conditions);
243 REGISTER_ELEMENT(EncryptedAssertion);
244 REGISTER_ELEMENT(EncryptedAttribute);
245 REGISTER_ELEMENT(EncryptedID);
246 REGISTER_ELEMENT(Evidence);
247 REGISTER_ELEMENT(Issuer);
248 REGISTER_ELEMENT(NameID);
249 REGISTER_ELEMENT_NOVAL(OneTimeUse);
250 REGISTER_ELEMENT(ProxyRestriction);
251 REGISTER_ELEMENT_NOVAL(Statement);
252 REGISTER_ELEMENT(Subject);
253 REGISTER_ELEMENT(SubjectConfirmation);
254 REGISTER_ELEMENT_NOVAL(SubjectConfirmationData);
255 REGISTER_ELEMENT(SubjectLocality);
256 REGISTER_TYPE(Action);
257 REGISTER_TYPE(Advice);
258 REGISTER_TYPE(Assertion);
259 REGISTER_TYPE(Attribute);
260 REGISTER_TYPE(AttributeStatement);
261 REGISTER_TYPE(AudienceRestriction);
262 REGISTER_TYPE(AuthnContext);
263 REGISTER_TYPE(AuthnStatement);
264 REGISTER_TYPE(AuthzDecisionStatement);
265 REGISTER_TYPE(Conditions);
266 REGISTER_TYPE(Evidence);
267 REGISTER_TYPE(KeyInfoConfirmationDataType);
268 REGISTER_TYPE(NameIDType);
269 REGISTER_TYPE_NOVAL(OneTimeUse);
270 REGISTER_TYPE(ProxyRestriction);
271 REGISTER_TYPE(Subject);
272 REGISTER_TYPE(SubjectConfirmation);
273 REGISTER_TYPE(SubjectLocality);
275 q=xmltooling::QName(samlconstants::SAML20_DELEGATION_CONDITION_NS,Delegate::LOCAL_NAME);
276 XMLObjectBuilder::registerBuilder(q,new DelegateBuilder());
277 SchemaValidators.registerValidator(q,new DelegateSchemaValidator());
278 q=xmltooling::QName(samlconstants::SAML20_DELEGATION_CONDITION_NS,Delegate::TYPE_NAME);
279 XMLObjectBuilder::registerBuilder(q,new DelegateBuilder());
280 SchemaValidators.registerValidator(q,new DelegateSchemaValidator());
282 q=xmltooling::QName(samlconstants::SAML20_DELEGATION_CONDITION_NS,DelegationRestrictionType::TYPE_NAME);
283 XMLObjectBuilder::registerBuilder(q,new DelegationRestrictionTypeBuilder());
284 SchemaValidators.registerValidator(q,new DelegationRestrictionTypeSchemaValidator());