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/validation/ValidatorSuite.h>
29 using namespace opensaml::saml2md;
30 using namespace opensaml::saml2;
31 using namespace opensaml;
32 using namespace xmltooling;
34 using samlconstants::SAML20MD_NS;
35 using samlconstants::SAML20MD_QUERY_EXT_NS;
36 using samlconstants::SAML20MD_ENTITY_ATTRIBUTE_NS;
41 XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,ActionNamespace);
42 XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,AffiliateMember);
43 XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,AttributeProfile);
44 XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,Company);
45 XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,EmailAddress);
46 XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,GivenName);
47 XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,NameIDFormat);
48 XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,SourceID);
49 XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,SurName);
50 XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,TelephoneNumber);
52 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,localizedNameType);
53 XMLOBJECTVALIDATOR_REQUIRE(localizedNameType,TextContent);
54 XMLOBJECTVALIDATOR_REQUIRE(localizedNameType,Lang);
55 END_XMLOBJECTVALIDATOR;
57 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,localizedURIType);
58 XMLOBJECTVALIDATOR_REQUIRE(localizedURIType,TextContent);
59 XMLOBJECTVALIDATOR_REQUIRE(localizedURIType,Lang);
60 END_XMLOBJECTVALIDATOR;
62 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,OrganizationName,localizedNameType);
63 localizedNameTypeSchemaValidator::validate(xmlObject);
64 END_XMLOBJECTVALIDATOR;
66 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,OrganizationDisplayName,localizedNameType);
67 localizedNameTypeSchemaValidator::validate(xmlObject);
68 END_XMLOBJECTVALIDATOR;
70 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,OrganizationURL,localizedURIType);
71 localizedURITypeSchemaValidator::validate(xmlObject);
72 END_XMLOBJECTVALIDATOR;
74 class SAML_DLLLOCAL checkWildcardNS {
76 void operator()(const XMLObject* xmlObject) const {
77 const XMLCh* ns=xmlObject->getElementQName().getNamespaceURI();
78 if (XMLString::equals(ns,SAML20MD_NS) || !ns || !*ns) {
79 throw ValidationException(
80 "Object contains an illegal extension child element ($1).",
81 params(1,xmlObject->getElementQName().toString().c_str())
87 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,Extensions);
88 if (!ptr->hasChildren())
89 throw ValidationException("Extensions must have at least one child element.");
90 const vector<XMLObject*>& anys=ptr->getUnknownXMLObjects();
91 for_each(anys.begin(),anys.end(),checkWildcardNS());
92 END_XMLOBJECTVALIDATOR;
94 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,Organization);
95 XMLOBJECTVALIDATOR_NONEMPTY(Organization,OrganizationName);
96 XMLOBJECTVALIDATOR_NONEMPTY(Organization,OrganizationDisplayName);
97 XMLOBJECTVALIDATOR_NONEMPTY(Organization,OrganizationURL);
98 END_XMLOBJECTVALIDATOR;
100 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,ContactPerson);
101 /* Pending errata decision.
102 if (!ptr->hasChildren())
103 throw ValidationException("ContactPerson must have at least one child element.");
105 if (!XMLString::equals(ptr->getContactType(),ContactPerson::CONTACT_TECHNICAL) &&
106 !XMLString::equals(ptr->getContactType(),ContactPerson::CONTACT_SUPPORT) &&
107 !XMLString::equals(ptr->getContactType(),ContactPerson::CONTACT_ADMINISTRATIVE) &&
108 !XMLString::equals(ptr->getContactType(),ContactPerson::CONTACT_BILLING) &&
109 !XMLString::equals(ptr->getContactType(),ContactPerson::CONTACT_OTHER))
110 throw ValidationException("ContactPerson contactType must be one of the defined values.");
111 END_XMLOBJECTVALIDATOR;
113 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,AdditionalMetadataLocation);
114 XMLOBJECTVALIDATOR_REQUIRE(AdditionalMetadataLocation,Namespace);
115 XMLOBJECTVALIDATOR_REQUIRE(AdditionalMetadataLocation,Location);
116 END_XMLOBJECTVALIDATOR;
118 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,KeyDescriptor);
119 XMLOBJECTVALIDATOR_REQUIRE(KeyDescriptor,KeyInfo);
121 !XMLString::equals(ptr->getUse(),KeyDescriptor::KEYTYPE_ENCRYPTION) &&
122 !XMLString::equals(ptr->getUse(),KeyDescriptor::KEYTYPE_SIGNING))
123 throw ValidationException("KeyDescriptor use must be empty or one of the defined values.");
124 END_XMLOBJECTVALIDATOR;
126 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,RoleDescriptor);
127 XMLOBJECTVALIDATOR_REQUIRE(RoleDescriptor,ProtocolSupportEnumeration);
128 END_XMLOBJECTVALIDATOR;
130 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,EndpointType);
131 XMLOBJECTVALIDATOR_REQUIRE(EndpointType,Binding);
132 XMLOBJECTVALIDATOR_REQUIRE(EndpointType,Location);
133 const vector<XMLObject*>& anys=ptr->getUnknownXMLObjects();
134 for_each(anys.begin(),anys.end(),checkWildcardNS());
135 END_XMLOBJECTVALIDATOR;
137 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,IndexedEndpointType,EndpointType);
138 EndpointTypeSchemaValidator::validate(xmlObject);
139 XMLOBJECTVALIDATOR_REQUIRE_INTEGER(IndexedEndpointType,Index);
140 END_XMLOBJECTVALIDATOR;
142 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,ArtifactResolutionService,IndexedEndpointType);
143 IndexedEndpointTypeSchemaValidator::validate(xmlObject);
144 END_XMLOBJECTVALIDATOR;
146 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,SingleLogoutService,EndpointType);
147 EndpointTypeSchemaValidator::validate(xmlObject);
148 END_XMLOBJECTVALIDATOR;
150 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,ManageNameIDService,EndpointType);
151 EndpointTypeSchemaValidator::validate(xmlObject);
152 END_XMLOBJECTVALIDATOR;
154 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,SingleSignOnService,EndpointType);
155 EndpointTypeSchemaValidator::validate(xmlObject);
156 END_XMLOBJECTVALIDATOR;
158 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,NameIDMappingService,EndpointType);
159 EndpointTypeSchemaValidator::validate(xmlObject);
160 END_XMLOBJECTVALIDATOR;
162 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,AssertionIDRequestService,EndpointType);
163 EndpointTypeSchemaValidator::validate(xmlObject);
164 END_XMLOBJECTVALIDATOR;
166 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,IDPSSODescriptor,RoleDescriptor);
167 RoleDescriptorSchemaValidator::validate(xmlObject);
168 XMLOBJECTVALIDATOR_NONEMPTY(IDPSSODescriptor,SingleSignOnService);
169 END_XMLOBJECTVALIDATOR;
171 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,ServiceName,localizedNameType);
172 localizedNameTypeSchemaValidator::validate(xmlObject);
173 END_XMLOBJECTVALIDATOR;
175 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,ServiceDescription,localizedNameType);
176 localizedNameTypeSchemaValidator::validate(xmlObject);
177 END_XMLOBJECTVALIDATOR;
179 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,RequestedAttribute);
180 XMLOBJECTVALIDATOR_REQUIRE(RequestedAttribute,Name);
181 END_XMLOBJECTVALIDATOR;
183 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,AttributeConsumingService);
184 XMLOBJECTVALIDATOR_REQUIRE_INTEGER(AttributeConsumingService,Index);
185 XMLOBJECTVALIDATOR_NONEMPTY(AttributeConsumingService,ServiceName);
186 XMLOBJECTVALIDATOR_NONEMPTY(AttributeConsumingService,RequestedAttribute);
187 END_XMLOBJECTVALIDATOR;
189 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,AssertionConsumerService,IndexedEndpointType);
190 IndexedEndpointTypeSchemaValidator::validate(xmlObject);
191 END_XMLOBJECTVALIDATOR;
193 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,SPSSODescriptor,RoleDescriptor);
194 RoleDescriptorSchemaValidator::validate(xmlObject);
195 XMLOBJECTVALIDATOR_NONEMPTY(SPSSODescriptor,AssertionConsumerService);
196 END_XMLOBJECTVALIDATOR;
198 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,AuthnQueryService,EndpointType);
199 EndpointTypeSchemaValidator::validate(xmlObject);
200 END_XMLOBJECTVALIDATOR;
202 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,AuthnAuthorityDescriptor,RoleDescriptor);
203 RoleDescriptorSchemaValidator::validate(xmlObject);
204 XMLOBJECTVALIDATOR_NONEMPTY(AuthnAuthorityDescriptor,AuthnQueryService);
205 END_XMLOBJECTVALIDATOR;
207 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,AuthzService,EndpointType);
208 EndpointTypeSchemaValidator::validate(xmlObject);
209 END_XMLOBJECTVALIDATOR;
211 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,PDPDescriptor,RoleDescriptor);
212 RoleDescriptorSchemaValidator::validate(xmlObject);
213 XMLOBJECTVALIDATOR_NONEMPTY(PDPDescriptor,AuthzService);
214 END_XMLOBJECTVALIDATOR;
216 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,AttributeService,EndpointType);
217 EndpointTypeSchemaValidator::validate(xmlObject);
218 END_XMLOBJECTVALIDATOR;
220 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,AttributeAuthorityDescriptor,RoleDescriptor);
221 RoleDescriptorSchemaValidator::validate(xmlObject);
222 XMLOBJECTVALIDATOR_NONEMPTY(AttributeAuthorityDescriptor,AttributeService);
223 END_XMLOBJECTVALIDATOR;
225 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,AffiliationDescriptor);
226 XMLOBJECTVALIDATOR_REQUIRE(AffiliationDescriptor,AffiliationOwnerID);
227 XMLOBJECTVALIDATOR_NONEMPTY(AffiliationDescriptor,AffiliateMember);
228 END_XMLOBJECTVALIDATOR;
230 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,EntityDescriptor);
231 XMLOBJECTVALIDATOR_REQUIRE(EntityDescriptor,EntityID);
232 if (ptr->getRoleDescriptors().empty() &&
233 ptr->getIDPSSODescriptors().empty() &&
234 ptr->getSPSSODescriptors().empty() &&
235 ptr->getAuthnAuthorityDescriptors().empty() &&
236 ptr->getAttributeAuthorityDescriptors().empty() &&
237 ptr->getPDPDescriptors().empty()) {
239 if (!ptr->getAffiliationDescriptor())
240 throw ValidationException("EntityDescriptor must have at least one child role or affiliation descriptor.");
242 else if (ptr->getAffiliationDescriptor()) {
243 throw ValidationException("EntityDescriptor cannot have both an AffiliationDescriptor and role descriptors.");
245 END_XMLOBJECTVALIDATOR;
247 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,EntitiesDescriptor);
248 if (ptr->getEntityDescriptors().empty() && ptr->getEntitiesDescriptors().empty())
249 throw ValidationException("EntitiesDescriptor must contain at least one child descriptor.");
250 END_XMLOBJECTVALIDATOR;
252 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,EntityAttributes);
253 if (!ptr->hasChildren())
254 throw ValidationException("EntityAttributes must contain at least one child element.");
255 END_XMLOBJECTVALIDATOR;
260 #define REGISTER_ELEMENT(cname) \
261 q=xmltooling::QName(SAML20MD_NS,cname::LOCAL_NAME); \
262 XMLObjectBuilder::registerBuilder(q,new cname##Builder()); \
263 SchemaValidators.registerValidator(q,new cname##SchemaValidator())
265 #define REGISTER_TYPE(cname) \
266 q=xmltooling::QName(SAML20MD_NS,cname::TYPE_NAME); \
267 XMLObjectBuilder::registerBuilder(q,new cname##Builder()); \
268 SchemaValidators.registerValidator(q,new cname##SchemaValidator())
270 #define REGISTER_ELEMENT_NOVAL(cname) \
271 q=xmltooling::QName(SAML20MD_NS,cname::LOCAL_NAME); \
272 XMLObjectBuilder::registerBuilder(q,new cname##Builder());
274 #define REGISTER_TYPE_NOVAL(cname) \
275 q=xmltooling::QName(SAML20MD_NS,cname::TYPE_NAME); \
276 XMLObjectBuilder::registerBuilder(q,new cname##Builder());
278 void opensaml::saml2md::registerMetadataClasses() {
280 REGISTER_ELEMENT(AdditionalMetadataLocation);
281 REGISTER_ELEMENT(AffiliateMember);
282 REGISTER_ELEMENT(AffiliationDescriptor);
283 REGISTER_ELEMENT(ArtifactResolutionService);
284 REGISTER_ELEMENT(AssertionConsumerService);
285 REGISTER_ELEMENT(AssertionIDRequestService);
286 REGISTER_ELEMENT(AttributeAuthorityDescriptor);;
287 REGISTER_ELEMENT(AttributeConsumingService);
288 REGISTER_ELEMENT(AttributeProfile);
289 REGISTER_ELEMENT(AttributeService);
290 REGISTER_ELEMENT(AuthnAuthorityDescriptor);
291 REGISTER_ELEMENT(AuthnQueryService);
292 REGISTER_ELEMENT(AuthzService);
293 REGISTER_ELEMENT(Company);
294 REGISTER_ELEMENT(ContactPerson);
295 REGISTER_ELEMENT(EmailAddress);
296 REGISTER_ELEMENT(EntitiesDescriptor);
297 REGISTER_ELEMENT(EntityDescriptor);
298 REGISTER_ELEMENT(Extensions);
299 REGISTER_ELEMENT(GivenName);
300 REGISTER_ELEMENT(IDPSSODescriptor);
301 REGISTER_ELEMENT(KeyDescriptor);
302 REGISTER_ELEMENT(ManageNameIDService);
303 REGISTER_ELEMENT(NameIDFormat);
304 REGISTER_ELEMENT(NameIDMappingService);
305 REGISTER_ELEMENT(Organization);
306 REGISTER_ELEMENT(OrganizationDisplayName);
307 REGISTER_ELEMENT(OrganizationName);
308 REGISTER_ELEMENT(OrganizationURL);
309 REGISTER_ELEMENT(PDPDescriptor);
310 REGISTER_ELEMENT(RequestedAttribute);
311 REGISTER_ELEMENT(RoleDescriptor);
312 REGISTER_ELEMENT(ServiceDescription);
313 REGISTER_ELEMENT(ServiceName);
314 REGISTER_ELEMENT(SingleLogoutService);
315 REGISTER_ELEMENT(SingleSignOnService);
316 REGISTER_ELEMENT(SPSSODescriptor);
317 REGISTER_ELEMENT(SurName);
318 REGISTER_ELEMENT(TelephoneNumber);
319 REGISTER_TYPE(AdditionalMetadataLocation);
320 REGISTER_TYPE(AffiliationDescriptor);
321 REGISTER_TYPE(AttributeAuthorityDescriptor);;
322 REGISTER_TYPE(AttributeConsumingService);
323 REGISTER_TYPE(AuthnAuthorityDescriptor);
324 REGISTER_TYPE(ContactPerson);
325 REGISTER_TYPE(EndpointType);
326 REGISTER_TYPE(EntitiesDescriptor);
327 REGISTER_TYPE(EntityDescriptor);
328 REGISTER_TYPE(Extensions);
329 REGISTER_TYPE(IDPSSODescriptor);
330 REGISTER_TYPE(IndexedEndpointType);
331 REGISTER_TYPE(KeyDescriptor);
332 REGISTER_TYPE(localizedNameType);
333 REGISTER_TYPE(localizedURIType);
334 REGISTER_TYPE(Organization);
335 REGISTER_TYPE(PDPDescriptor);
336 REGISTER_TYPE(RequestedAttribute);
337 REGISTER_TYPE(SPSSODescriptor);
339 q=xmltooling::QName(SAML20MD_NS,xmlencryption::EncryptionMethod::LOCAL_NAME);
340 XMLObjectBuilder::registerBuilder(q,new xmlencryption::EncryptionMethodBuilder());
342 q=xmltooling::QName(samlconstants::SAML1MD_NS,SourceID::LOCAL_NAME);
343 XMLObjectBuilder::registerBuilder(q,new SourceIDBuilder());
344 SchemaValidators.registerValidator(q,new SourceIDSchemaValidator());
346 q=xmltooling::QName(SAML20MD_QUERY_EXT_NS,ActionNamespace::LOCAL_NAME);
347 XMLObjectBuilder::registerBuilder(q,new ActionNamespaceBuilder());
348 SchemaValidators.registerValidator(q,new ActionNamespaceSchemaValidator());
350 q=xmltooling::QName(SAML20MD_QUERY_EXT_NS,AuthnQueryDescriptorType::TYPE_NAME);
351 XMLObjectBuilder::registerBuilder(q,new AuthnQueryDescriptorTypeBuilder());
352 SchemaValidators.registerValidator(q,new RoleDescriptorSchemaValidator());
354 q=xmltooling::QName(SAML20MD_QUERY_EXT_NS,AttributeQueryDescriptorType::TYPE_NAME);
355 XMLObjectBuilder::registerBuilder(q,new AttributeQueryDescriptorTypeBuilder());
356 SchemaValidators.registerValidator(q,new RoleDescriptorSchemaValidator());
358 q=xmltooling::QName(SAML20MD_QUERY_EXT_NS,AuthzDecisionQueryDescriptorType::TYPE_NAME);
359 XMLObjectBuilder::registerBuilder(q,new AuthzDecisionQueryDescriptorTypeBuilder());
360 SchemaValidators.registerValidator(q,new RoleDescriptorSchemaValidator());
362 q=xmltooling::QName(SAML20MD_ENTITY_ATTRIBUTE_NS,EntityAttributes::LOCAL_NAME);
363 XMLObjectBuilder::registerBuilder(q,new EntityAttributesBuilder());
364 SchemaValidators.registerValidator(q,new EntityAttributesSchemaValidator());
366 q=xmltooling::QName(SAML20MD_ENTITY_ATTRIBUTE_NS,EntityAttributes::TYPE_NAME);
367 XMLObjectBuilder::registerBuilder(q,new EntityAttributesBuilder());
368 SchemaValidators.registerValidator(q,new EntityAttributesSchemaValidator());