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_ENTITY_ATTRIBUTE_NS;
43 XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,ActionNamespace);
44 XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,AffiliateMember);
45 XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,AttributeProfile);
46 XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,Company);
47 XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,EmailAddress);
48 XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,GivenName);
49 XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,NameIDFormat);
50 XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,SourceID);
51 XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,SurName);
52 XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,TelephoneNumber);
54 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,localizedNameType);
55 XMLOBJECTVALIDATOR_REQUIRE(localizedNameType,TextContent);
56 XMLOBJECTVALIDATOR_REQUIRE(localizedNameType,Lang);
57 END_XMLOBJECTVALIDATOR;
59 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,localizedURIType);
60 XMLOBJECTVALIDATOR_REQUIRE(localizedURIType,TextContent);
61 XMLOBJECTVALIDATOR_REQUIRE(localizedURIType,Lang);
62 END_XMLOBJECTVALIDATOR;
64 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,OrganizationName,localizedNameType);
65 localizedNameTypeSchemaValidator::validate(xmlObject);
66 END_XMLOBJECTVALIDATOR;
68 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,OrganizationDisplayName,localizedNameType);
69 localizedNameTypeSchemaValidator::validate(xmlObject);
70 END_XMLOBJECTVALIDATOR;
72 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,OrganizationURL,localizedURIType);
73 localizedURITypeSchemaValidator::validate(xmlObject);
74 END_XMLOBJECTVALIDATOR;
76 class SAML_DLLLOCAL checkWildcardNS {
78 void operator()(const XMLObject* xmlObject) const {
79 const XMLCh* ns=xmlObject->getElementQName().getNamespaceURI();
80 if (XMLString::equals(ns,SAML20MD_NS) || !ns || !*ns) {
81 throw ValidationException(
82 "Object contains an illegal extension child element ($1).",
83 params(1,xmlObject->getElementQName().toString().c_str())
89 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,Extensions);
90 if (!ptr->hasChildren())
91 throw ValidationException("Extensions must have at least one child element.");
92 const vector<XMLObject*>& anys=ptr->getUnknownXMLObjects();
93 for_each(anys.begin(),anys.end(),checkWildcardNS());
94 END_XMLOBJECTVALIDATOR;
96 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,Organization);
97 XMLOBJECTVALIDATOR_NONEMPTY(Organization,OrganizationName);
98 XMLOBJECTVALIDATOR_NONEMPTY(Organization,OrganizationDisplayName);
99 XMLOBJECTVALIDATOR_NONEMPTY(Organization,OrganizationURL);
100 END_XMLOBJECTVALIDATOR;
102 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,ContactPerson);
103 /* Pending errata decision.
104 if (!ptr->hasChildren())
105 throw ValidationException("ContactPerson must have at least one child element.");
107 if (!XMLString::equals(ptr->getContactType(),ContactPerson::CONTACT_TECHNICAL) &&
108 !XMLString::equals(ptr->getContactType(),ContactPerson::CONTACT_SUPPORT) &&
109 !XMLString::equals(ptr->getContactType(),ContactPerson::CONTACT_ADMINISTRATIVE) &&
110 !XMLString::equals(ptr->getContactType(),ContactPerson::CONTACT_BILLING) &&
111 !XMLString::equals(ptr->getContactType(),ContactPerson::CONTACT_OTHER))
112 throw ValidationException("ContactPerson contactType must be one of the defined values.");
113 END_XMLOBJECTVALIDATOR;
115 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,AdditionalMetadataLocation);
116 XMLOBJECTVALIDATOR_REQUIRE(AdditionalMetadataLocation,Namespace);
117 XMLOBJECTVALIDATOR_REQUIRE(AdditionalMetadataLocation,Location);
118 END_XMLOBJECTVALIDATOR;
120 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,KeyDescriptor);
121 XMLOBJECTVALIDATOR_REQUIRE(KeyDescriptor,KeyInfo);
123 !XMLString::equals(ptr->getUse(),KeyDescriptor::KEYTYPE_ENCRYPTION) &&
124 !XMLString::equals(ptr->getUse(),KeyDescriptor::KEYTYPE_SIGNING))
125 throw ValidationException("KeyDescriptor use must be empty or one of the defined values.");
126 END_XMLOBJECTVALIDATOR;
128 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,RoleDescriptor);
129 XMLOBJECTVALIDATOR_REQUIRE(RoleDescriptor,ProtocolSupportEnumeration);
130 END_XMLOBJECTVALIDATOR;
132 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,EndpointType);
133 XMLOBJECTVALIDATOR_REQUIRE(EndpointType,Binding);
134 XMLOBJECTVALIDATOR_REQUIRE(EndpointType,Location);
135 const vector<XMLObject*>& anys=ptr->getUnknownXMLObjects();
136 for_each(anys.begin(),anys.end(),checkWildcardNS());
137 END_XMLOBJECTVALIDATOR;
139 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,IndexedEndpointType,EndpointType);
140 EndpointTypeSchemaValidator::validate(xmlObject);
141 XMLOBJECTVALIDATOR_REQUIRE_INTEGER(IndexedEndpointType,Index);
142 END_XMLOBJECTVALIDATOR;
144 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,ArtifactResolutionService,IndexedEndpointType);
145 IndexedEndpointTypeSchemaValidator::validate(xmlObject);
146 END_XMLOBJECTVALIDATOR;
148 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,SingleLogoutService,EndpointType);
149 EndpointTypeSchemaValidator::validate(xmlObject);
150 END_XMLOBJECTVALIDATOR;
152 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,ManageNameIDService,EndpointType);
153 EndpointTypeSchemaValidator::validate(xmlObject);
154 END_XMLOBJECTVALIDATOR;
156 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,SingleSignOnService,EndpointType);
157 EndpointTypeSchemaValidator::validate(xmlObject);
158 END_XMLOBJECTVALIDATOR;
160 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,NameIDMappingService,EndpointType);
161 EndpointTypeSchemaValidator::validate(xmlObject);
162 END_XMLOBJECTVALIDATOR;
164 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,AssertionIDRequestService,EndpointType);
165 EndpointTypeSchemaValidator::validate(xmlObject);
166 END_XMLOBJECTVALIDATOR;
168 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,IDPSSODescriptor,RoleDescriptor);
169 RoleDescriptorSchemaValidator::validate(xmlObject);
170 XMLOBJECTVALIDATOR_NONEMPTY(IDPSSODescriptor,SingleSignOnService);
171 END_XMLOBJECTVALIDATOR;
173 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,ServiceName,localizedNameType);
174 localizedNameTypeSchemaValidator::validate(xmlObject);
175 END_XMLOBJECTVALIDATOR;
177 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,ServiceDescription,localizedNameType);
178 localizedNameTypeSchemaValidator::validate(xmlObject);
179 END_XMLOBJECTVALIDATOR;
181 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,RequestedAttribute);
182 XMLOBJECTVALIDATOR_REQUIRE(RequestedAttribute,Name);
183 END_XMLOBJECTVALIDATOR;
185 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,AttributeConsumingService);
186 XMLOBJECTVALIDATOR_REQUIRE_INTEGER(AttributeConsumingService,Index);
187 XMLOBJECTVALIDATOR_NONEMPTY(AttributeConsumingService,ServiceName);
188 XMLOBJECTVALIDATOR_NONEMPTY(AttributeConsumingService,RequestedAttribute);
189 END_XMLOBJECTVALIDATOR;
191 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,AssertionConsumerService,IndexedEndpointType);
192 IndexedEndpointTypeSchemaValidator::validate(xmlObject);
193 END_XMLOBJECTVALIDATOR;
195 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,SPSSODescriptor,RoleDescriptor);
196 RoleDescriptorSchemaValidator::validate(xmlObject);
197 XMLOBJECTVALIDATOR_NONEMPTY(SPSSODescriptor,AssertionConsumerService);
198 END_XMLOBJECTVALIDATOR;
200 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,AuthnQueryService,EndpointType);
201 EndpointTypeSchemaValidator::validate(xmlObject);
202 END_XMLOBJECTVALIDATOR;
204 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,AuthnAuthorityDescriptor,RoleDescriptor);
205 RoleDescriptorSchemaValidator::validate(xmlObject);
206 XMLOBJECTVALIDATOR_NONEMPTY(AuthnAuthorityDescriptor,AuthnQueryService);
207 END_XMLOBJECTVALIDATOR;
209 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,AuthzService,EndpointType);
210 EndpointTypeSchemaValidator::validate(xmlObject);
211 END_XMLOBJECTVALIDATOR;
213 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,PDPDescriptor,RoleDescriptor);
214 RoleDescriptorSchemaValidator::validate(xmlObject);
215 XMLOBJECTVALIDATOR_NONEMPTY(PDPDescriptor,AuthzService);
216 END_XMLOBJECTVALIDATOR;
218 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,AttributeService,EndpointType);
219 EndpointTypeSchemaValidator::validate(xmlObject);
220 END_XMLOBJECTVALIDATOR;
222 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,AttributeAuthorityDescriptor,RoleDescriptor);
223 RoleDescriptorSchemaValidator::validate(xmlObject);
224 XMLOBJECTVALIDATOR_NONEMPTY(AttributeAuthorityDescriptor,AttributeService);
225 END_XMLOBJECTVALIDATOR;
227 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,AffiliationDescriptor);
228 XMLOBJECTVALIDATOR_REQUIRE(AffiliationDescriptor,AffiliationOwnerID);
229 XMLOBJECTVALIDATOR_NONEMPTY(AffiliationDescriptor,AffiliateMember);
230 END_XMLOBJECTVALIDATOR;
232 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,EntityDescriptor);
233 XMLOBJECTVALIDATOR_REQUIRE(EntityDescriptor,EntityID);
234 if (ptr->getRoleDescriptors().empty() &&
235 ptr->getIDPSSODescriptors().empty() &&
236 ptr->getSPSSODescriptors().empty() &&
237 ptr->getAuthnAuthorityDescriptors().empty() &&
238 ptr->getAttributeAuthorityDescriptors().empty() &&
239 ptr->getPDPDescriptors().empty()) {
241 if (!ptr->getAffiliationDescriptor())
242 throw ValidationException("EntityDescriptor must have at least one child role or affiliation descriptor.");
244 else if (ptr->getAffiliationDescriptor()) {
245 throw ValidationException("EntityDescriptor cannot have both an AffiliationDescriptor and role descriptors.");
247 END_XMLOBJECTVALIDATOR;
249 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,EntitiesDescriptor);
250 if (ptr->getEntityDescriptors().empty() && ptr->getEntitiesDescriptors().empty())
251 throw ValidationException("EntitiesDescriptor must contain at least one child descriptor.");
252 END_XMLOBJECTVALIDATOR;
254 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,EntityAttributes);
255 if (!ptr->hasChildren())
256 throw ValidationException("EntityAttributes must contain at least one child element.");
257 END_XMLOBJECTVALIDATOR;
262 #define REGISTER_ELEMENT(cname) \
263 q=xmltooling::QName(SAML20MD_NS,cname::LOCAL_NAME); \
264 XMLObjectBuilder::registerBuilder(q,new cname##Builder()); \
265 SchemaValidators.registerValidator(q,new cname##SchemaValidator())
267 #define REGISTER_TYPE(cname) \
268 q=xmltooling::QName(SAML20MD_NS,cname::TYPE_NAME); \
269 XMLObjectBuilder::registerBuilder(q,new cname##Builder()); \
270 SchemaValidators.registerValidator(q,new cname##SchemaValidator())
272 #define REGISTER_ELEMENT_NOVAL(cname) \
273 q=xmltooling::QName(SAML20MD_NS,cname::LOCAL_NAME); \
274 XMLObjectBuilder::registerBuilder(q,new cname##Builder());
276 #define REGISTER_TYPE_NOVAL(cname) \
277 q=xmltooling::QName(SAML20MD_NS,cname::TYPE_NAME); \
278 XMLObjectBuilder::registerBuilder(q,new cname##Builder());
280 void opensaml::saml2md::registerMetadataClasses() {
282 REGISTER_ELEMENT(AdditionalMetadataLocation);
283 REGISTER_ELEMENT(AffiliateMember);
284 REGISTER_ELEMENT(AffiliationDescriptor);
285 REGISTER_ELEMENT(ArtifactResolutionService);
286 REGISTER_ELEMENT(AssertionConsumerService);
287 REGISTER_ELEMENT(AssertionIDRequestService);
288 REGISTER_ELEMENT(AttributeAuthorityDescriptor);;
289 REGISTER_ELEMENT(AttributeConsumingService);
290 REGISTER_ELEMENT(AttributeProfile);
291 REGISTER_ELEMENT(AttributeService);
292 REGISTER_ELEMENT(AuthnAuthorityDescriptor);
293 REGISTER_ELEMENT(AuthnQueryService);
294 REGISTER_ELEMENT(AuthzService);
295 REGISTER_ELEMENT(Company);
296 REGISTER_ELEMENT(ContactPerson);
297 REGISTER_ELEMENT(EmailAddress);
298 REGISTER_ELEMENT(EntitiesDescriptor);
299 REGISTER_ELEMENT(EntityDescriptor);
300 REGISTER_ELEMENT(Extensions);
301 REGISTER_ELEMENT(GivenName);
302 REGISTER_ELEMENT(IDPSSODescriptor);
303 REGISTER_ELEMENT(KeyDescriptor);
304 REGISTER_ELEMENT(ManageNameIDService);
305 REGISTER_ELEMENT(NameIDFormat);
306 REGISTER_ELEMENT(NameIDMappingService);
307 REGISTER_ELEMENT(Organization);
308 REGISTER_ELEMENT(OrganizationDisplayName);
309 REGISTER_ELEMENT(OrganizationName);
310 REGISTER_ELEMENT(OrganizationURL);
311 REGISTER_ELEMENT(PDPDescriptor);
312 REGISTER_ELEMENT(RequestedAttribute);
313 REGISTER_ELEMENT(RoleDescriptor);
314 REGISTER_ELEMENT(ServiceDescription);
315 REGISTER_ELEMENT(ServiceName);
316 REGISTER_ELEMENT(SingleLogoutService);
317 REGISTER_ELEMENT(SingleSignOnService);
318 REGISTER_ELEMENT(SPSSODescriptor);
319 REGISTER_ELEMENT(SurName);
320 REGISTER_ELEMENT(TelephoneNumber);
321 REGISTER_TYPE(AdditionalMetadataLocation);
322 REGISTER_TYPE(AffiliationDescriptor);
323 REGISTER_TYPE(AttributeAuthorityDescriptor);;
324 REGISTER_TYPE(AttributeConsumingService);
325 REGISTER_TYPE(AuthnAuthorityDescriptor);
326 REGISTER_TYPE(ContactPerson);
327 REGISTER_TYPE(EndpointType);
328 REGISTER_TYPE(EntitiesDescriptor);
329 REGISTER_TYPE(EntityDescriptor);
330 REGISTER_TYPE(Extensions);
331 REGISTER_TYPE(IDPSSODescriptor);
332 REGISTER_TYPE(IndexedEndpointType);
333 REGISTER_TYPE(KeyDescriptor);
334 REGISTER_TYPE(localizedNameType);
335 REGISTER_TYPE(localizedURIType);
336 REGISTER_TYPE(Organization);
337 REGISTER_TYPE(PDPDescriptor);
338 REGISTER_TYPE(RequestedAttribute);
339 REGISTER_TYPE(SPSSODescriptor);
341 q=xmltooling::QName(SAML20MD_NS,xmlencryption::EncryptionMethod::LOCAL_NAME);
342 XMLObjectBuilder::registerBuilder(q,new xmlencryption::EncryptionMethodBuilder());
344 q=xmltooling::QName(samlconstants::SAML1MD_NS,SourceID::LOCAL_NAME);
345 XMLObjectBuilder::registerBuilder(q,new SourceIDBuilder());
346 SchemaValidators.registerValidator(q,new SourceIDSchemaValidator());
348 q=xmltooling::QName(SAML20MD_QUERY_EXT_NS,ActionNamespace::LOCAL_NAME);
349 XMLObjectBuilder::registerBuilder(q,new ActionNamespaceBuilder());
350 SchemaValidators.registerValidator(q,new ActionNamespaceSchemaValidator());
352 q=xmltooling::QName(SAML20MD_QUERY_EXT_NS,AuthnQueryDescriptorType::TYPE_NAME);
353 XMLObjectBuilder::registerBuilder(q,new AuthnQueryDescriptorTypeBuilder());
354 SchemaValidators.registerValidator(q,new RoleDescriptorSchemaValidator());
356 q=xmltooling::QName(SAML20MD_QUERY_EXT_NS,AttributeQueryDescriptorType::TYPE_NAME);
357 XMLObjectBuilder::registerBuilder(q,new AttributeQueryDescriptorTypeBuilder());
358 SchemaValidators.registerValidator(q,new RoleDescriptorSchemaValidator());
360 q=xmltooling::QName(SAML20MD_QUERY_EXT_NS,AuthzDecisionQueryDescriptorType::TYPE_NAME);
361 XMLObjectBuilder::registerBuilder(q,new AuthzDecisionQueryDescriptorTypeBuilder());
362 SchemaValidators.registerValidator(q,new RoleDescriptorSchemaValidator());
364 q=xmltooling::QName(SAML20MD_ENTITY_ATTRIBUTE_NS,EntityAttributes::LOCAL_NAME);
365 XMLObjectBuilder::registerBuilder(q,new EntityAttributesBuilder());
366 SchemaValidators.registerValidator(q,new EntityAttributesSchemaValidator());
368 q=xmltooling::QName(SAML20MD_ENTITY_ATTRIBUTE_NS,EntityAttributes::TYPE_NAME);
369 XMLObjectBuilder::registerBuilder(q,new EntityAttributesBuilder());
370 SchemaValidators.registerValidator(q,new EntityAttributesSchemaValidator());