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 * MetadataSchemaValidators.cpp
20 * Schema-based validators for SAML 2.0 Metadata classes.
24 #include "exceptions.h"
25 #include "saml2/metadata/Metadata.h"
27 #include <xmltooling/encryption/Encryption.h>
28 #include <xmltooling/validation/Validator.h>
29 #include <xmltooling/validation/ValidatorSuite.h>
31 using namespace opensaml::saml2md;
32 using namespace opensaml::saml2;
33 using namespace opensaml;
34 using namespace xmltooling;
36 using samlconstants::SAML20MD_NS;
37 using samlconstants::SAML20MD_QUERY_EXT_NS;
38 using samlconstants::SAML20MD_ALGSUPPORT_NS;
39 using samlconstants::SAML20MD_ENTITY_ATTRIBUTE_NS;
44 XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,ActionNamespace);
45 XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,AffiliateMember);
46 XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,AttributeProfile);
47 XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,Company);
48 XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,EmailAddress);
49 XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,GivenName);
50 XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,NameIDFormat);
51 XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,SourceID);
52 XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,SurName);
53 XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,TelephoneNumber);
55 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,localizedNameType);
56 XMLOBJECTVALIDATOR_REQUIRE(localizedNameType,TextContent);
57 XMLOBJECTVALIDATOR_REQUIRE(localizedNameType,Lang);
58 END_XMLOBJECTVALIDATOR;
60 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,localizedURIType);
61 XMLOBJECTVALIDATOR_REQUIRE(localizedURIType,TextContent);
62 XMLOBJECTVALIDATOR_REQUIRE(localizedURIType,Lang);
63 END_XMLOBJECTVALIDATOR;
65 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,OrganizationName,localizedNameType);
66 localizedNameTypeSchemaValidator::validate(xmlObject);
67 END_XMLOBJECTVALIDATOR;
69 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,OrganizationDisplayName,localizedNameType);
70 localizedNameTypeSchemaValidator::validate(xmlObject);
71 END_XMLOBJECTVALIDATOR;
73 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,OrganizationURL,localizedURIType);
74 localizedURITypeSchemaValidator::validate(xmlObject);
75 END_XMLOBJECTVALIDATOR;
77 class SAML_DLLLOCAL checkWildcardNS {
79 void operator()(const XMLObject* xmlObject) const {
80 const XMLCh* ns=xmlObject->getElementQName().getNamespaceURI();
81 if (XMLString::equals(ns,SAML20MD_NS) || !ns || !*ns) {
82 throw ValidationException(
83 "Object contains an illegal extension child element ($1).",
84 params(1,xmlObject->getElementQName().toString().c_str())
90 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,Extensions);
91 if (!ptr->hasChildren())
92 throw ValidationException("Extensions must have at least one child element.");
93 const vector<XMLObject*>& anys=ptr->getUnknownXMLObjects();
94 for_each(anys.begin(),anys.end(),checkWildcardNS());
95 END_XMLOBJECTVALIDATOR;
97 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,Organization);
98 XMLOBJECTVALIDATOR_NONEMPTY(Organization,OrganizationName);
99 XMLOBJECTVALIDATOR_NONEMPTY(Organization,OrganizationDisplayName);
100 XMLOBJECTVALIDATOR_NONEMPTY(Organization,OrganizationURL);
101 END_XMLOBJECTVALIDATOR;
103 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,ContactPerson);
104 /* Pending errata decision.
105 if (!ptr->hasChildren())
106 throw ValidationException("ContactPerson must have at least one child element.");
108 if (!XMLString::equals(ptr->getContactType(),ContactPerson::CONTACT_TECHNICAL) &&
109 !XMLString::equals(ptr->getContactType(),ContactPerson::CONTACT_SUPPORT) &&
110 !XMLString::equals(ptr->getContactType(),ContactPerson::CONTACT_ADMINISTRATIVE) &&
111 !XMLString::equals(ptr->getContactType(),ContactPerson::CONTACT_BILLING) &&
112 !XMLString::equals(ptr->getContactType(),ContactPerson::CONTACT_OTHER))
113 throw ValidationException("ContactPerson contactType must be one of the defined values.");
114 END_XMLOBJECTVALIDATOR;
116 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,AdditionalMetadataLocation);
117 XMLOBJECTVALIDATOR_REQUIRE(AdditionalMetadataLocation,Namespace);
118 XMLOBJECTVALIDATOR_REQUIRE(AdditionalMetadataLocation,Location);
119 END_XMLOBJECTVALIDATOR;
121 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,KeyDescriptor);
122 XMLOBJECTVALIDATOR_REQUIRE(KeyDescriptor,KeyInfo);
124 !XMLString::equals(ptr->getUse(),KeyDescriptor::KEYTYPE_ENCRYPTION) &&
125 !XMLString::equals(ptr->getUse(),KeyDescriptor::KEYTYPE_SIGNING))
126 throw ValidationException("KeyDescriptor use must be empty or one of the defined values.");
127 END_XMLOBJECTVALIDATOR;
129 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,RoleDescriptor);
130 XMLOBJECTVALIDATOR_REQUIRE(RoleDescriptor,ProtocolSupportEnumeration);
131 END_XMLOBJECTVALIDATOR;
133 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,EndpointType);
134 XMLOBJECTVALIDATOR_REQUIRE(EndpointType,Binding);
135 XMLOBJECTVALIDATOR_REQUIRE(EndpointType,Location);
136 const vector<XMLObject*>& anys=ptr->getUnknownXMLObjects();
137 for_each(anys.begin(),anys.end(),checkWildcardNS());
138 END_XMLOBJECTVALIDATOR;
140 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,IndexedEndpointType,EndpointType);
141 EndpointTypeSchemaValidator::validate(xmlObject);
142 XMLOBJECTVALIDATOR_REQUIRE_INTEGER(IndexedEndpointType,Index);
143 END_XMLOBJECTVALIDATOR;
145 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,ArtifactResolutionService,IndexedEndpointType);
146 IndexedEndpointTypeSchemaValidator::validate(xmlObject);
147 END_XMLOBJECTVALIDATOR;
149 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,SingleLogoutService,EndpointType);
150 EndpointTypeSchemaValidator::validate(xmlObject);
151 END_XMLOBJECTVALIDATOR;
153 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,ManageNameIDService,EndpointType);
154 EndpointTypeSchemaValidator::validate(xmlObject);
155 END_XMLOBJECTVALIDATOR;
157 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,SingleSignOnService,EndpointType);
158 EndpointTypeSchemaValidator::validate(xmlObject);
159 END_XMLOBJECTVALIDATOR;
161 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,NameIDMappingService,EndpointType);
162 EndpointTypeSchemaValidator::validate(xmlObject);
163 END_XMLOBJECTVALIDATOR;
165 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,AssertionIDRequestService,EndpointType);
166 EndpointTypeSchemaValidator::validate(xmlObject);
167 END_XMLOBJECTVALIDATOR;
169 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,IDPSSODescriptor,RoleDescriptor);
170 RoleDescriptorSchemaValidator::validate(xmlObject);
171 XMLOBJECTVALIDATOR_NONEMPTY(IDPSSODescriptor,SingleSignOnService);
172 END_XMLOBJECTVALIDATOR;
174 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,ServiceName,localizedNameType);
175 localizedNameTypeSchemaValidator::validate(xmlObject);
176 END_XMLOBJECTVALIDATOR;
178 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,ServiceDescription,localizedNameType);
179 localizedNameTypeSchemaValidator::validate(xmlObject);
180 END_XMLOBJECTVALIDATOR;
182 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,RequestedAttribute);
183 XMLOBJECTVALIDATOR_REQUIRE(RequestedAttribute,Name);
184 END_XMLOBJECTVALIDATOR;
186 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,AttributeConsumingService);
187 XMLOBJECTVALIDATOR_REQUIRE_INTEGER(AttributeConsumingService,Index);
188 XMLOBJECTVALIDATOR_NONEMPTY(AttributeConsumingService,ServiceName);
189 XMLOBJECTVALIDATOR_NONEMPTY(AttributeConsumingService,RequestedAttribute);
190 END_XMLOBJECTVALIDATOR;
192 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,AssertionConsumerService,IndexedEndpointType);
193 IndexedEndpointTypeSchemaValidator::validate(xmlObject);
194 END_XMLOBJECTVALIDATOR;
196 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,SPSSODescriptor,RoleDescriptor);
197 RoleDescriptorSchemaValidator::validate(xmlObject);
198 XMLOBJECTVALIDATOR_NONEMPTY(SPSSODescriptor,AssertionConsumerService);
199 END_XMLOBJECTVALIDATOR;
201 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,AuthnQueryService,EndpointType);
202 EndpointTypeSchemaValidator::validate(xmlObject);
203 END_XMLOBJECTVALIDATOR;
205 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,AuthnAuthorityDescriptor,RoleDescriptor);
206 RoleDescriptorSchemaValidator::validate(xmlObject);
207 XMLOBJECTVALIDATOR_NONEMPTY(AuthnAuthorityDescriptor,AuthnQueryService);
208 END_XMLOBJECTVALIDATOR;
210 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,AuthzService,EndpointType);
211 EndpointTypeSchemaValidator::validate(xmlObject);
212 END_XMLOBJECTVALIDATOR;
214 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,PDPDescriptor,RoleDescriptor);
215 RoleDescriptorSchemaValidator::validate(xmlObject);
216 XMLOBJECTVALIDATOR_NONEMPTY(PDPDescriptor,AuthzService);
217 END_XMLOBJECTVALIDATOR;
219 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,AttributeService,EndpointType);
220 EndpointTypeSchemaValidator::validate(xmlObject);
221 END_XMLOBJECTVALIDATOR;
223 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,AttributeAuthorityDescriptor,RoleDescriptor);
224 RoleDescriptorSchemaValidator::validate(xmlObject);
225 XMLOBJECTVALIDATOR_NONEMPTY(AttributeAuthorityDescriptor,AttributeService);
226 END_XMLOBJECTVALIDATOR;
228 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,AffiliationDescriptor);
229 XMLOBJECTVALIDATOR_REQUIRE(AffiliationDescriptor,AffiliationOwnerID);
230 XMLOBJECTVALIDATOR_NONEMPTY(AffiliationDescriptor,AffiliateMember);
231 END_XMLOBJECTVALIDATOR;
233 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,EntityDescriptor);
234 XMLOBJECTVALIDATOR_REQUIRE(EntityDescriptor,EntityID);
235 if (ptr->getRoleDescriptors().empty() &&
236 ptr->getIDPSSODescriptors().empty() &&
237 ptr->getSPSSODescriptors().empty() &&
238 ptr->getAuthnAuthorityDescriptors().empty() &&
239 ptr->getAttributeAuthorityDescriptors().empty() &&
240 ptr->getPDPDescriptors().empty()) {
242 if (!ptr->getAffiliationDescriptor())
243 throw ValidationException("EntityDescriptor must have at least one child role or affiliation descriptor.");
245 else if (ptr->getAffiliationDescriptor()) {
246 throw ValidationException("EntityDescriptor cannot have both an AffiliationDescriptor and role descriptors.");
248 END_XMLOBJECTVALIDATOR;
250 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,EntitiesDescriptor);
251 if (ptr->getEntityDescriptors().empty() && ptr->getEntitiesDescriptors().empty())
252 throw ValidationException("EntitiesDescriptor must contain at least one child descriptor.");
253 END_XMLOBJECTVALIDATOR;
255 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,EntityAttributes);
256 if (!ptr->hasChildren())
257 throw ValidationException("EntityAttributes must contain at least one child element.");
258 END_XMLOBJECTVALIDATOR;
260 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,DigestMethod);
261 XMLOBJECTVALIDATOR_REQUIRE(DigestMethod,Algorithm);
262 END_XMLOBJECTVALIDATOR;
264 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,SigningMethod);
265 XMLOBJECTVALIDATOR_REQUIRE(SigningMethod,Algorithm);
266 END_XMLOBJECTVALIDATOR;
270 #define REGISTER_ELEMENT(cname) \
271 q=xmltooling::QName(SAML20MD_NS,cname::LOCAL_NAME); \
272 XMLObjectBuilder::registerBuilder(q,new cname##Builder()); \
273 SchemaValidators.registerValidator(q,new cname##SchemaValidator())
275 #define REGISTER_TYPE(cname) \
276 q=xmltooling::QName(SAML20MD_NS,cname::TYPE_NAME); \
277 XMLObjectBuilder::registerBuilder(q,new cname##Builder()); \
278 SchemaValidators.registerValidator(q,new cname##SchemaValidator())
280 #define REGISTER_ELEMENT_NOVAL(cname) \
281 q=xmltooling::QName(SAML20MD_NS,cname::LOCAL_NAME); \
282 XMLObjectBuilder::registerBuilder(q,new cname##Builder());
284 #define REGISTER_TYPE_NOVAL(cname) \
285 q=xmltooling::QName(SAML20MD_NS,cname::TYPE_NAME); \
286 XMLObjectBuilder::registerBuilder(q,new cname##Builder());
288 void opensaml::saml2md::registerMetadataClasses() {
290 REGISTER_ELEMENT(AdditionalMetadataLocation);
291 REGISTER_ELEMENT(AffiliateMember);
292 REGISTER_ELEMENT(AffiliationDescriptor);
293 REGISTER_ELEMENT(ArtifactResolutionService);
294 REGISTER_ELEMENT(AssertionConsumerService);
295 REGISTER_ELEMENT(AssertionIDRequestService);
296 REGISTER_ELEMENT(AttributeAuthorityDescriptor);;
297 REGISTER_ELEMENT(AttributeConsumingService);
298 REGISTER_ELEMENT(AttributeProfile);
299 REGISTER_ELEMENT(AttributeService);
300 REGISTER_ELEMENT(AuthnAuthorityDescriptor);
301 REGISTER_ELEMENT(AuthnQueryService);
302 REGISTER_ELEMENT(AuthzService);
303 REGISTER_ELEMENT(Company);
304 REGISTER_ELEMENT(ContactPerson);
305 REGISTER_ELEMENT(EmailAddress);
306 REGISTER_ELEMENT(EntitiesDescriptor);
307 REGISTER_ELEMENT(EntityDescriptor);
308 REGISTER_ELEMENT(Extensions);
309 REGISTER_ELEMENT(GivenName);
310 REGISTER_ELEMENT(IDPSSODescriptor);
311 REGISTER_ELEMENT(KeyDescriptor);
312 REGISTER_ELEMENT(ManageNameIDService);
313 REGISTER_ELEMENT(NameIDFormat);
314 REGISTER_ELEMENT(NameIDMappingService);
315 REGISTER_ELEMENT(Organization);
316 REGISTER_ELEMENT(OrganizationDisplayName);
317 REGISTER_ELEMENT(OrganizationName);
318 REGISTER_ELEMENT(OrganizationURL);
319 REGISTER_ELEMENT(PDPDescriptor);
320 REGISTER_ELEMENT(RequestedAttribute);
321 REGISTER_ELEMENT(RoleDescriptor);
322 REGISTER_ELEMENT(ServiceDescription);
323 REGISTER_ELEMENT(ServiceName);
324 REGISTER_ELEMENT(SingleLogoutService);
325 REGISTER_ELEMENT(SingleSignOnService);
326 REGISTER_ELEMENT(SPSSODescriptor);
327 REGISTER_ELEMENT(SurName);
328 REGISTER_ELEMENT(TelephoneNumber);
329 REGISTER_TYPE(AdditionalMetadataLocation);
330 REGISTER_TYPE(AffiliationDescriptor);
331 REGISTER_TYPE(AttributeAuthorityDescriptor);;
332 REGISTER_TYPE(AttributeConsumingService);
333 REGISTER_TYPE(AuthnAuthorityDescriptor);
334 REGISTER_TYPE(ContactPerson);
335 REGISTER_TYPE(EndpointType);
336 REGISTER_TYPE(EntitiesDescriptor);
337 REGISTER_TYPE(EntityDescriptor);
338 REGISTER_TYPE(Extensions);
339 REGISTER_TYPE(IDPSSODescriptor);
340 REGISTER_TYPE(IndexedEndpointType);
341 REGISTER_TYPE(KeyDescriptor);
342 REGISTER_TYPE(localizedNameType);
343 REGISTER_TYPE(localizedURIType);
344 REGISTER_TYPE(Organization);
345 REGISTER_TYPE(PDPDescriptor);
346 REGISTER_TYPE(RequestedAttribute);
347 REGISTER_TYPE(SPSSODescriptor);
349 q=xmltooling::QName(SAML20MD_NS,xmlencryption::EncryptionMethod::LOCAL_NAME);
350 XMLObjectBuilder::registerBuilder(q,new xmlencryption::EncryptionMethodBuilder());
352 q=xmltooling::QName(samlconstants::SAML1MD_NS,SourceID::LOCAL_NAME);
353 XMLObjectBuilder::registerBuilder(q,new SourceIDBuilder());
354 SchemaValidators.registerValidator(q,new SourceIDSchemaValidator());
356 q=xmltooling::QName(SAML20MD_QUERY_EXT_NS,ActionNamespace::LOCAL_NAME);
357 XMLObjectBuilder::registerBuilder(q,new ActionNamespaceBuilder());
358 SchemaValidators.registerValidator(q,new ActionNamespaceSchemaValidator());
360 q=xmltooling::QName(SAML20MD_QUERY_EXT_NS,AuthnQueryDescriptorType::TYPE_NAME);
361 XMLObjectBuilder::registerBuilder(q,new AuthnQueryDescriptorTypeBuilder());
362 SchemaValidators.registerValidator(q,new RoleDescriptorSchemaValidator());
364 q=xmltooling::QName(SAML20MD_QUERY_EXT_NS,AttributeQueryDescriptorType::TYPE_NAME);
365 XMLObjectBuilder::registerBuilder(q,new AttributeQueryDescriptorTypeBuilder());
366 SchemaValidators.registerValidator(q,new RoleDescriptorSchemaValidator());
368 q=xmltooling::QName(SAML20MD_QUERY_EXT_NS,AuthzDecisionQueryDescriptorType::TYPE_NAME);
369 XMLObjectBuilder::registerBuilder(q,new AuthzDecisionQueryDescriptorTypeBuilder());
370 SchemaValidators.registerValidator(q,new RoleDescriptorSchemaValidator());
372 q=xmltooling::QName(SAML20MD_ENTITY_ATTRIBUTE_NS,EntityAttributes::LOCAL_NAME);
373 XMLObjectBuilder::registerBuilder(q,new EntityAttributesBuilder());
374 SchemaValidators.registerValidator(q,new EntityAttributesSchemaValidator());
376 q=xmltooling::QName(SAML20MD_ENTITY_ATTRIBUTE_NS,EntityAttributes::TYPE_NAME);
377 XMLObjectBuilder::registerBuilder(q,new EntityAttributesBuilder());
378 SchemaValidators.registerValidator(q,new EntityAttributesSchemaValidator());
380 q=xmltooling::QName(SAML20MD_ALGSUPPORT_NS,DigestMethod::LOCAL_NAME);
381 XMLObjectBuilder::registerBuilder(q,new DigestMethodBuilder());
382 SchemaValidators.registerValidator(q,new DigestMethodSchemaValidator());
384 q=xmltooling::QName(SAML20MD_ALGSUPPORT_NS,DigestMethod::TYPE_NAME);
385 XMLObjectBuilder::registerBuilder(q,new DigestMethodBuilder());
386 SchemaValidators.registerValidator(q,new DigestMethodSchemaValidator());
388 q=xmltooling::QName(SAML20MD_ALGSUPPORT_NS,SigningMethod::LOCAL_NAME);
389 XMLObjectBuilder::registerBuilder(q,new SigningMethodBuilder());
390 SchemaValidators.registerValidator(q,new SigningMethodSchemaValidator());
392 q=xmltooling::QName(SAML20MD_ALGSUPPORT_NS,SigningMethod::TYPE_NAME);
393 XMLObjectBuilder::registerBuilder(q,new SigningMethodBuilder());
394 SchemaValidators.registerValidator(q,new SigningMethodSchemaValidator());