2 * Copyright 2001-2006 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;
38 XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,ActionNamespace);
39 XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,AffiliateMember);
40 XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,AttributeProfile);
41 XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,Company);
42 XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,EmailAddress);
43 XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,GivenName);
44 XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,NameIDFormat);
45 XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,SourceID);
46 XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,SurName);
47 XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,TelephoneNumber);
49 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,localizedNameType);
50 XMLOBJECTVALIDATOR_REQUIRE(localizedNameType,TextContent);
51 XMLOBJECTVALIDATOR_REQUIRE(localizedNameType,Lang);
52 END_XMLOBJECTVALIDATOR;
54 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,localizedURIType);
55 XMLOBJECTVALIDATOR_REQUIRE(localizedNameType,TextContent);
56 XMLOBJECTVALIDATOR_REQUIRE(localizedURIType,Lang);
57 END_XMLOBJECTVALIDATOR;
59 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,OrganizationName,localizedNameType);
60 localizedNameTypeSchemaValidator::validate(xmlObject);
61 END_XMLOBJECTVALIDATOR;
63 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,OrganizationDisplayName,localizedNameType);
64 localizedNameTypeSchemaValidator::validate(xmlObject);
65 END_XMLOBJECTVALIDATOR;
67 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,OrganizationURL,localizedURIType);
68 localizedURITypeSchemaValidator::validate(xmlObject);
69 END_XMLOBJECTVALIDATOR;
71 class SAML_DLLLOCAL checkWildcardNS {
73 void operator()(const XMLObject* xmlObject) const {
74 const XMLCh* ns=xmlObject->getElementQName().getNamespaceURI();
75 if (XMLString::equals(ns,SAMLConstants::SAML20MD_NS) || !ns || !*ns) {
76 throw ValidationException(
77 "Object contains an illegal extension child element ($1).",
78 params(1,xmlObject->getElementQName().toString().c_str())
84 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,Extensions);
85 if (!ptr->hasChildren())
86 throw ValidationException("Extensions must have at least one child element.");
87 const list<XMLObject*>& anys=ptr->getXMLObjects();
88 for_each(anys.begin(),anys.end(),checkWildcardNS());
89 END_XMLOBJECTVALIDATOR;
91 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,Organization);
92 XMLOBJECTVALIDATOR_NONEMPTY(Organization,OrganizationName);
93 XMLOBJECTVALIDATOR_NONEMPTY(Organization,OrganizationDisplayName);
94 XMLOBJECTVALIDATOR_NONEMPTY(Organization,OrganizationURL);
95 END_XMLOBJECTVALIDATOR;
97 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,ContactPerson);
98 if (!ptr->hasChildren())
99 throw ValidationException("ContactPerson must have at least one child element.");
100 if (!XMLString::equals(ptr->getContactType(),ContactPerson::CONTACT_TECHNICAL) &&
101 !XMLString::equals(ptr->getContactType(),ContactPerson::CONTACT_SUPPORT) &&
102 !XMLString::equals(ptr->getContactType(),ContactPerson::CONTACT_ADMINISTRATIVE) &&
103 !XMLString::equals(ptr->getContactType(),ContactPerson::CONTACT_BILLING) &&
104 !XMLString::equals(ptr->getContactType(),ContactPerson::CONTACT_OTHER))
105 throw ValidationException("ContactPerson contactType must be one of the defined values.");
106 END_XMLOBJECTVALIDATOR;
108 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,AdditionalMetadataLocation);
109 XMLOBJECTVALIDATOR_REQUIRE(AdditionalMetadataLocation,Namespace);
110 XMLOBJECTVALIDATOR_REQUIRE(AdditionalMetadataLocation,Location);
111 END_XMLOBJECTVALIDATOR;
113 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,KeyDescriptor);
114 XMLOBJECTVALIDATOR_REQUIRE(KeyDescriptor,KeyInfo);
116 !XMLString::equals(ptr->getUse(),KeyDescriptor::KEYTYPE_ENCRYPTION) &&
117 !XMLString::equals(ptr->getUse(),KeyDescriptor::KEYTYPE_SIGNING))
118 throw ValidationException("KeyDescriptor use must be empty or one of the defined values.");
119 END_XMLOBJECTVALIDATOR;
121 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,RoleDescriptor);
122 XMLOBJECTVALIDATOR_REQUIRE(RoleDescriptor,ProtocolSupportEnumeration);
123 END_XMLOBJECTVALIDATOR;
125 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,EndpointType);
126 XMLOBJECTVALIDATOR_REQUIRE(EndpointType,Binding);
127 XMLOBJECTVALIDATOR_REQUIRE(EndpointType,Location);
128 const list<XMLObject*>& anys=ptr->getXMLObjects();
129 for_each(anys.begin(),anys.end(),checkWildcardNS());
130 END_XMLOBJECTVALIDATOR;
132 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,IndexedEndpointType,EndpointType);
133 EndpointTypeSchemaValidator::validate(xmlObject);
134 XMLOBJECTVALIDATOR_REQUIRE_INTEGER(IndexedEndpointType,Index);
135 END_XMLOBJECTVALIDATOR;
137 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,ArtifactResolutionService,IndexedEndpointType);
138 IndexedEndpointTypeSchemaValidator::validate(xmlObject);
139 END_XMLOBJECTVALIDATOR;
141 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,SingleLogoutService,EndpointType);
142 EndpointTypeSchemaValidator::validate(xmlObject);
143 END_XMLOBJECTVALIDATOR;
145 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,ManageNameIDService,EndpointType);
146 EndpointTypeSchemaValidator::validate(xmlObject);
147 END_XMLOBJECTVALIDATOR;
149 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,SingleSignOnService,EndpointType);
150 EndpointTypeSchemaValidator::validate(xmlObject);
151 END_XMLOBJECTVALIDATOR;
153 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,NameIDMappingService,EndpointType);
154 EndpointTypeSchemaValidator::validate(xmlObject);
155 END_XMLOBJECTVALIDATOR;
157 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,AssertionIDRequestService,EndpointType);
158 EndpointTypeSchemaValidator::validate(xmlObject);
159 END_XMLOBJECTVALIDATOR;
161 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,IDPSSODescriptor,RoleDescriptor);
162 RoleDescriptorSchemaValidator::validate(xmlObject);
163 XMLOBJECTVALIDATOR_NONEMPTY(IDPSSODescriptor,SingleSignOnService);
164 END_XMLOBJECTVALIDATOR;
166 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,ServiceName,localizedNameType);
167 localizedNameTypeSchemaValidator::validate(xmlObject);
168 END_XMLOBJECTVALIDATOR;
170 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,ServiceDescription,localizedNameType);
171 localizedNameTypeSchemaValidator::validate(xmlObject);
172 END_XMLOBJECTVALIDATOR;
174 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,RequestedAttribute);
175 XMLOBJECTVALIDATOR_REQUIRE(RequestedAttribute,Name);
176 END_XMLOBJECTVALIDATOR;
178 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,AttributeConsumingService);
179 XMLOBJECTVALIDATOR_REQUIRE_INTEGER(AttributeConsumingService,Index);
180 XMLOBJECTVALIDATOR_NONEMPTY(AttributeConsumingService,ServiceName);
181 XMLOBJECTVALIDATOR_NONEMPTY(AttributeConsumingService,RequestedAttribute);
182 END_XMLOBJECTVALIDATOR;
184 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,AssertionConsumerService,IndexedEndpointType);
185 IndexedEndpointTypeSchemaValidator::validate(xmlObject);
186 END_XMLOBJECTVALIDATOR;
188 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,SPSSODescriptor,RoleDescriptor);
189 RoleDescriptorSchemaValidator::validate(xmlObject);
190 XMLOBJECTVALIDATOR_NONEMPTY(SPSSODescriptor,AssertionConsumerService);
191 END_XMLOBJECTVALIDATOR;
193 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,AuthnQueryService,EndpointType);
194 EndpointTypeSchemaValidator::validate(xmlObject);
195 END_XMLOBJECTVALIDATOR;
197 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,AuthnAuthorityDescriptor,RoleDescriptor);
198 RoleDescriptorSchemaValidator::validate(xmlObject);
199 XMLOBJECTVALIDATOR_NONEMPTY(AuthnAuthorityDescriptor,AuthnQueryService);
200 END_XMLOBJECTVALIDATOR;
202 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,AuthzService,EndpointType);
203 EndpointTypeSchemaValidator::validate(xmlObject);
204 END_XMLOBJECTVALIDATOR;
206 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,PDPDescriptor,RoleDescriptor);
207 RoleDescriptorSchemaValidator::validate(xmlObject);
208 XMLOBJECTVALIDATOR_NONEMPTY(PDPDescriptor,AuthzService);
209 END_XMLOBJECTVALIDATOR;
211 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,AttributeService,EndpointType);
212 EndpointTypeSchemaValidator::validate(xmlObject);
213 END_XMLOBJECTVALIDATOR;
215 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,AttributeAuthorityDescriptor,RoleDescriptor);
216 RoleDescriptorSchemaValidator::validate(xmlObject);
217 XMLOBJECTVALIDATOR_NONEMPTY(AttributeAuthorityDescriptor,AttributeService);
218 END_XMLOBJECTVALIDATOR;
220 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,AffiliationDescriptor);
221 XMLOBJECTVALIDATOR_REQUIRE(AffiliationDescriptor,AffiliationOwnerID);
222 XMLOBJECTVALIDATOR_NONEMPTY(AffiliationDescriptor,AffiliateMember);
223 END_XMLOBJECTVALIDATOR;
225 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,EntityDescriptor);
226 XMLOBJECTVALIDATOR_REQUIRE(EntityDescriptor,EntityID);
227 if (ptr->getRoleDescriptors().empty() &&
228 ptr->getIDPSSODescriptors().empty() &&
229 ptr->getSPSSODescriptors().empty() &&
230 ptr->getAuthnAuthorityDescriptors().empty() &&
231 ptr->getAttributeAuthorityDescriptors().empty() &&
232 ptr->getPDPDescriptors().empty()) {
234 if (!ptr->getAffiliationDescriptor())
235 throw ValidationException("EntityDescriptor must have at least one child role or affiliation descriptor.");
237 else if (ptr->getAffiliationDescriptor()) {
238 throw ValidationException("EntityDescriptor cannot have both an AffiliationDescriptor and role descriptors.");
240 END_XMLOBJECTVALIDATOR;
242 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,EntitiesDescriptor);
243 if (ptr->getEntityDescriptors().empty() && ptr->getEntitiesDescriptors().empty())
244 throw ValidationException("EntitiesDescriptor must contain at least one child descriptor.");
245 END_XMLOBJECTVALIDATOR;
249 #define REGISTER_ELEMENT(cname) \
250 q=QName(SAMLConstants::SAML20MD_NS,cname::LOCAL_NAME); \
251 XMLObjectBuilder::registerBuilder(q,new cname##Builder()); \
252 SchemaValidators.registerValidator(q,new cname##SchemaValidator())
254 #define REGISTER_TYPE(cname) \
255 q=QName(SAMLConstants::SAML20MD_NS,cname::TYPE_NAME); \
256 XMLObjectBuilder::registerBuilder(q,new cname##Builder()); \
257 SchemaValidators.registerValidator(q,new cname##SchemaValidator())
259 #define REGISTER_ELEMENT_NOVAL(cname) \
260 q=QName(SAMLConstants::SAML20MD_NS,cname::LOCAL_NAME); \
261 XMLObjectBuilder::registerBuilder(q,new cname##Builder());
263 #define REGISTER_TYPE_NOVAL(cname) \
264 q=QName(SAMLConstants::SAML20MD_NS,cname::TYPE_NAME); \
265 XMLObjectBuilder::registerBuilder(q,new cname##Builder());
267 void opensaml::saml2md::registerMetadataClasses() {
269 REGISTER_ELEMENT(AdditionalMetadataLocation);
270 REGISTER_ELEMENT(AffiliateMember);
271 REGISTER_ELEMENT(AffiliationDescriptor);
272 REGISTER_ELEMENT(ArtifactResolutionService);
273 REGISTER_ELEMENT(AssertionConsumerService);
274 REGISTER_ELEMENT(AssertionIDRequestService);
275 REGISTER_ELEMENT(AttributeAuthorityDescriptor);;
276 REGISTER_ELEMENT(AttributeConsumingService);
277 REGISTER_ELEMENT(AttributeProfile);
278 REGISTER_ELEMENT(AttributeService);
279 REGISTER_ELEMENT(AuthnAuthorityDescriptor);
280 REGISTER_ELEMENT(AuthnQueryService);
281 REGISTER_ELEMENT(AuthzService);
282 REGISTER_ELEMENT(Company);
283 REGISTER_ELEMENT(ContactPerson);
284 REGISTER_ELEMENT(EmailAddress);
285 REGISTER_ELEMENT(EntitiesDescriptor);
286 REGISTER_ELEMENT(EntityDescriptor);
287 REGISTER_ELEMENT(Extensions);
288 REGISTER_ELEMENT(GivenName);
289 REGISTER_ELEMENT(IDPSSODescriptor);
290 REGISTER_ELEMENT(KeyDescriptor);
291 REGISTER_ELEMENT(ManageNameIDService);
292 REGISTER_ELEMENT(NameIDFormat);
293 REGISTER_ELEMENT(NameIDMappingService);
294 REGISTER_ELEMENT(Organization);
295 REGISTER_ELEMENT(OrganizationDisplayName);
296 REGISTER_ELEMENT(OrganizationName);
297 REGISTER_ELEMENT(OrganizationURL);
298 REGISTER_ELEMENT(PDPDescriptor);
299 REGISTER_ELEMENT(RequestedAttribute);
300 REGISTER_ELEMENT(ServiceDescription);
301 REGISTER_ELEMENT(ServiceName);
302 REGISTER_ELEMENT(SingleLogoutService);
303 REGISTER_ELEMENT(SingleSignOnService);
304 REGISTER_ELEMENT(SPSSODescriptor);
305 REGISTER_ELEMENT(SurName);
306 REGISTER_ELEMENT(TelephoneNumber);
307 REGISTER_TYPE(AdditionalMetadataLocation);
308 REGISTER_TYPE(AffiliationDescriptor);
309 REGISTER_TYPE(AttributeAuthorityDescriptor);;
310 REGISTER_TYPE(AttributeConsumingService);
311 REGISTER_TYPE(AuthnAuthorityDescriptor);
312 REGISTER_TYPE(ContactPerson);
313 REGISTER_TYPE(EndpointType);
314 REGISTER_TYPE(EntitiesDescriptor);
315 REGISTER_TYPE(EntityDescriptor);
316 REGISTER_TYPE(Extensions);
317 REGISTER_TYPE(IDPSSODescriptor);
318 REGISTER_TYPE(IndexedEndpointType);
319 REGISTER_TYPE(KeyDescriptor);
320 REGISTER_TYPE(localizedNameType);
321 REGISTER_TYPE(localizedURIType);
322 REGISTER_TYPE(Organization);
323 REGISTER_TYPE(PDPDescriptor);
324 REGISTER_TYPE(RequestedAttribute);
325 REGISTER_TYPE(SPSSODescriptor);
327 q=QName(SAMLConstants::SAML1MD_NS,SourceID::LOCAL_NAME);
328 XMLObjectBuilder::registerBuilder(q,new SourceIDBuilder());
329 SchemaValidators.registerValidator(q,new SourceIDSchemaValidator());
331 q=QName(SAMLConstants::SAML20MD_QUERY_EXT_NS,ActionNamespace::LOCAL_NAME);
332 XMLObjectBuilder::registerBuilder(q,new ActionNamespaceBuilder());
333 SchemaValidators.registerValidator(q,new ActionNamespaceSchemaValidator());
335 q=QName(SAMLConstants::SAML20MD_QUERY_EXT_NS,AuthnQueryDescriptorType::TYPE_NAME);
336 XMLObjectBuilder::registerBuilder(q,new AuthnQueryDescriptorTypeBuilder());
337 SchemaValidators.registerValidator(q,new RoleDescriptorSchemaValidator());
339 q=QName(SAMLConstants::SAML20MD_QUERY_EXT_NS,AttributeQueryDescriptorType::TYPE_NAME);
340 XMLObjectBuilder::registerBuilder(q,new AttributeQueryDescriptorTypeBuilder());
341 SchemaValidators.registerValidator(q,new RoleDescriptorSchemaValidator());
343 q=QName(SAMLConstants::SAML20MD_QUERY_EXT_NS,AuthzDecisionQueryDescriptorType::TYPE_NAME);
344 XMLObjectBuilder::registerBuilder(q,new AuthzDecisionQueryDescriptorTypeBuilder());
345 SchemaValidators.registerValidator(q,new RoleDescriptorSchemaValidator());