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 using namespace opensaml::saml2md;
28 using namespace opensaml::saml2;
29 using namespace opensaml;
30 using namespace xmltooling;
36 XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,ActionNamespace);
37 XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,AffiliateMember);
38 XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,AttributeProfile);
39 XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,Company);
40 XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,EmailAddress);
41 XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,GivenName);
42 XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,NameIDFormat);
43 XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,SourceID);
44 XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,SurName);
45 XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,TelephoneNumber);
47 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,localizedNameType);
48 XMLOBJECTVALIDATOR_REQUIRE(localizedNameType,TextContent);
49 XMLOBJECTVALIDATOR_REQUIRE(localizedNameType,Lang);
50 END_XMLOBJECTVALIDATOR;
52 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,localizedURIType);
53 XMLOBJECTVALIDATOR_REQUIRE(localizedNameType,TextContent);
54 XMLOBJECTVALIDATOR_REQUIRE(localizedURIType,Lang);
55 END_XMLOBJECTVALIDATOR;
57 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,OrganizationName,localizedNameType);
58 localizedNameTypeSchemaValidator::validate(xmlObject);
59 END_XMLOBJECTVALIDATOR;
61 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,OrganizationDisplayName,localizedNameType);
62 localizedNameTypeSchemaValidator::validate(xmlObject);
63 END_XMLOBJECTVALIDATOR;
65 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,OrganizationURL,localizedURIType);
66 localizedURITypeSchemaValidator::validate(xmlObject);
67 END_XMLOBJECTVALIDATOR;
69 class SAML_DLLLOCAL checkWildcardNS {
71 void operator()(const XMLObject* xmlObject) const {
72 const XMLCh* ns=xmlObject->getElementQName().getNamespaceURI();
73 if (XMLString::equals(ns,SAMLConstants::SAML20MD_NS) || !ns || !*ns) {
74 throw ValidationException(
75 "Object contains an illegal extension child element ($1).",
76 params(1,xmlObject->getElementQName().toString().c_str())
82 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,Extensions);
83 if (!ptr->hasChildren())
84 throw ValidationException("Extensions must have at least one child element.");
85 const list<XMLObject*>& anys=ptr->getXMLObjects();
86 for_each(anys.begin(),anys.end(),checkWildcardNS());
87 END_XMLOBJECTVALIDATOR;
89 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,Organization);
90 XMLOBJECTVALIDATOR_NONEMPTY(Organization,OrganizationName);
91 XMLOBJECTVALIDATOR_NONEMPTY(Organization,OrganizationDisplayName);
92 XMLOBJECTVALIDATOR_NONEMPTY(Organization,OrganizationURL);
93 END_XMLOBJECTVALIDATOR;
95 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,ContactPerson);
96 if (!ptr->hasChildren())
97 throw ValidationException("ContactPerson must have at least one child element.");
98 if (!XMLString::equals(ptr->getContactType(),ContactPerson::CONTACT_TECHNICAL) &&
99 !XMLString::equals(ptr->getContactType(),ContactPerson::CONTACT_SUPPORT) &&
100 !XMLString::equals(ptr->getContactType(),ContactPerson::CONTACT_ADMINISTRATIVE) &&
101 !XMLString::equals(ptr->getContactType(),ContactPerson::CONTACT_BILLING) &&
102 !XMLString::equals(ptr->getContactType(),ContactPerson::CONTACT_OTHER))
103 throw ValidationException("ContactPerson contactType must be one of the defined values.");
104 END_XMLOBJECTVALIDATOR;
106 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,AdditionalMetadataLocation);
107 XMLOBJECTVALIDATOR_REQUIRE(AdditionalMetadataLocation,Namespace);
108 XMLOBJECTVALIDATOR_REQUIRE(AdditionalMetadataLocation,Location);
109 END_XMLOBJECTVALIDATOR;
111 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,KeyDescriptor);
112 XMLOBJECTVALIDATOR_REQUIRE(KeyDescriptor,KeyInfo);
114 !XMLString::equals(ptr->getUse(),KeyDescriptor::KEYTYPE_ENCRYPTION) &&
115 !XMLString::equals(ptr->getUse(),KeyDescriptor::KEYTYPE_SIGNING))
116 throw ValidationException("KeyDescriptor use must be empty or one of the defined values.");
117 END_XMLOBJECTVALIDATOR;
119 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,RoleDescriptor);
120 XMLOBJECTVALIDATOR_REQUIRE(RoleDescriptor,ProtocolSupportEnumeration);
121 END_XMLOBJECTVALIDATOR;
123 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,EndpointType);
124 XMLOBJECTVALIDATOR_REQUIRE(EndpointType,Binding);
125 XMLOBJECTVALIDATOR_REQUIRE(EndpointType,Location);
126 const list<XMLObject*>& anys=ptr->getXMLObjects();
127 for_each(anys.begin(),anys.end(),checkWildcardNS());
128 END_XMLOBJECTVALIDATOR;
130 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,IndexedEndpointType,EndpointType);
131 EndpointTypeSchemaValidator::validate(xmlObject);
132 XMLOBJECTVALIDATOR_REQUIRE_INTEGER(IndexedEndpointType,Index);
133 END_XMLOBJECTVALIDATOR;
135 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,ArtifactResolutionService,IndexedEndpointType);
136 IndexedEndpointTypeSchemaValidator::validate(xmlObject);
137 END_XMLOBJECTVALIDATOR;
139 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,SingleLogoutService,EndpointType);
140 EndpointTypeSchemaValidator::validate(xmlObject);
141 END_XMLOBJECTVALIDATOR;
143 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,ManageNameIDService,EndpointType);
144 EndpointTypeSchemaValidator::validate(xmlObject);
145 END_XMLOBJECTVALIDATOR;
147 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,SingleSignOnService,EndpointType);
148 EndpointTypeSchemaValidator::validate(xmlObject);
149 END_XMLOBJECTVALIDATOR;
151 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,NameIDMappingService,EndpointType);
152 EndpointTypeSchemaValidator::validate(xmlObject);
153 END_XMLOBJECTVALIDATOR;
155 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,AssertionIDRequestService,EndpointType);
156 EndpointTypeSchemaValidator::validate(xmlObject);
157 END_XMLOBJECTVALIDATOR;
159 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,IDPSSODescriptor,RoleDescriptor);
160 RoleDescriptorSchemaValidator::validate(xmlObject);
161 XMLOBJECTVALIDATOR_NONEMPTY(IDPSSODescriptor,SingleSignOnService);
162 END_XMLOBJECTVALIDATOR;
164 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,ServiceName,localizedNameType);
165 localizedNameTypeSchemaValidator::validate(xmlObject);
166 END_XMLOBJECTVALIDATOR;
168 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,ServiceDescription,localizedNameType);
169 localizedNameTypeSchemaValidator::validate(xmlObject);
170 END_XMLOBJECTVALIDATOR;
172 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,RequestedAttribute);
173 XMLOBJECTVALIDATOR_REQUIRE(RequestedAttribute,Name);
174 END_XMLOBJECTVALIDATOR;
176 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,AttributeConsumingService);
177 XMLOBJECTVALIDATOR_REQUIRE_INTEGER(AttributeConsumingService,Index);
178 XMLOBJECTVALIDATOR_NONEMPTY(AttributeConsumingService,ServiceName);
179 XMLOBJECTVALIDATOR_NONEMPTY(AttributeConsumingService,RequestedAttribute);
180 END_XMLOBJECTVALIDATOR;
182 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,AssertionConsumerService,IndexedEndpointType);
183 IndexedEndpointTypeSchemaValidator::validate(xmlObject);
184 END_XMLOBJECTVALIDATOR;
186 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,SPSSODescriptor,RoleDescriptor);
187 RoleDescriptorSchemaValidator::validate(xmlObject);
188 XMLOBJECTVALIDATOR_NONEMPTY(SPSSODescriptor,AssertionConsumerService);
189 END_XMLOBJECTVALIDATOR;
191 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,AuthnQueryService,EndpointType);
192 EndpointTypeSchemaValidator::validate(xmlObject);
193 END_XMLOBJECTVALIDATOR;
195 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,AuthnAuthorityDescriptor,RoleDescriptor);
196 RoleDescriptorSchemaValidator::validate(xmlObject);
197 XMLOBJECTVALIDATOR_NONEMPTY(AuthnAuthorityDescriptor,AuthnQueryService);
198 END_XMLOBJECTVALIDATOR;
200 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,AuthzService,EndpointType);
201 EndpointTypeSchemaValidator::validate(xmlObject);
202 END_XMLOBJECTVALIDATOR;
204 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,PDPDescriptor,RoleDescriptor);
205 RoleDescriptorSchemaValidator::validate(xmlObject);
206 XMLOBJECTVALIDATOR_NONEMPTY(PDPDescriptor,AuthzService);
207 END_XMLOBJECTVALIDATOR;
209 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,AttributeService,EndpointType);
210 EndpointTypeSchemaValidator::validate(xmlObject);
211 END_XMLOBJECTVALIDATOR;
213 BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,AttributeAuthorityDescriptor,RoleDescriptor);
214 RoleDescriptorSchemaValidator::validate(xmlObject);
215 XMLOBJECTVALIDATOR_NONEMPTY(AttributeAuthorityDescriptor,AttributeService);
216 END_XMLOBJECTVALIDATOR;
218 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,AffiliationDescriptor);
219 XMLOBJECTVALIDATOR_REQUIRE(AffiliationDescriptor,AffiliationOwnerID);
220 XMLOBJECTVALIDATOR_NONEMPTY(AffiliationDescriptor,AffiliateMember);
221 END_XMLOBJECTVALIDATOR;
223 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,EntityDescriptor);
224 XMLOBJECTVALIDATOR_REQUIRE(EntityDescriptor,EntityID);
225 if (ptr->getRoleDescriptors().empty() &&
226 ptr->getIDPSSODescriptors().empty() &&
227 ptr->getSPSSODescriptors().empty() &&
228 ptr->getAuthnAuthorityDescriptors().empty() &&
229 ptr->getAttributeAuthorityDescriptors().empty() &&
230 ptr->getPDPDescriptors().empty()) {
232 if (!ptr->getAffiliationDescriptor())
233 throw ValidationException("EntityDescriptor must have at least one child role or affiliation descriptor.");
235 else if (ptr->getAffiliationDescriptor()) {
236 throw ValidationException("EntityDescriptor cannot have both an AffiliationDescriptor and role descriptors.");
238 END_XMLOBJECTVALIDATOR;
240 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,EntitiesDescriptor);
241 if (ptr->getEntityDescriptors().empty() && ptr->getEntitiesDescriptors().empty())
242 throw ValidationException("EntitiesDescriptor must contain at least one child descriptor.");
243 END_XMLOBJECTVALIDATOR;
247 #define REGISTER_ELEMENT(cname) \
248 q=QName(SAMLConstants::SAML20MD_NS,cname::LOCAL_NAME); \
249 XMLObjectBuilder::registerBuilder(q,new cname##Builder()); \
250 SchemaValidators.registerValidator(q,new cname##SchemaValidator())
252 #define REGISTER_TYPE(cname) \
253 q=QName(SAMLConstants::SAML20MD_NS,cname::TYPE_NAME); \
254 XMLObjectBuilder::registerBuilder(q,new cname##Builder()); \
255 SchemaValidators.registerValidator(q,new cname##SchemaValidator())
257 #define REGISTER_ELEMENT_NOVAL(cname) \
258 q=QName(SAMLConstants::SAML20MD_NS,cname::LOCAL_NAME); \
259 XMLObjectBuilder::registerBuilder(q,new cname##Builder());
261 #define REGISTER_TYPE_NOVAL(cname) \
262 q=QName(SAMLConstants::SAML20MD_NS,cname::TYPE_NAME); \
263 XMLObjectBuilder::registerBuilder(q,new cname##Builder());
265 void opensaml::saml2md::registerMetadataClasses() {
267 REGISTER_ELEMENT(AdditionalMetadataLocation);
268 REGISTER_ELEMENT(AffiliateMember);
269 REGISTER_ELEMENT(AffiliationDescriptor);
270 REGISTER_ELEMENT(ArtifactResolutionService);
271 REGISTER_ELEMENT(AssertionConsumerService);
272 REGISTER_ELEMENT(AssertionIDRequestService);
273 REGISTER_ELEMENT(AttributeAuthorityDescriptor);;
274 REGISTER_ELEMENT(AttributeConsumingService);
275 REGISTER_ELEMENT(AttributeProfile);
276 REGISTER_ELEMENT(AttributeService);
277 REGISTER_ELEMENT(AuthnAuthorityDescriptor);
278 REGISTER_ELEMENT(AuthnQueryService);
279 REGISTER_ELEMENT(AuthzService);
280 REGISTER_ELEMENT(Company);
281 REGISTER_ELEMENT(ContactPerson);
282 REGISTER_ELEMENT(EmailAddress);
283 REGISTER_ELEMENT(EntitiesDescriptor);
284 REGISTER_ELEMENT(EntityDescriptor);
285 REGISTER_ELEMENT(Extensions);
286 REGISTER_ELEMENT(GivenName);
287 REGISTER_ELEMENT(IDPSSODescriptor);
288 REGISTER_ELEMENT(KeyDescriptor);
289 REGISTER_ELEMENT(ManageNameIDService);
290 REGISTER_ELEMENT(NameIDFormat);
291 REGISTER_ELEMENT(NameIDMappingService);
292 REGISTER_ELEMENT(Organization);
293 REGISTER_ELEMENT(OrganizationDisplayName);
294 REGISTER_ELEMENT(OrganizationName);
295 REGISTER_ELEMENT(OrganizationURL);
296 REGISTER_ELEMENT(PDPDescriptor);
297 REGISTER_ELEMENT(RequestedAttribute);
298 REGISTER_ELEMENT(ServiceDescription);
299 REGISTER_ELEMENT(ServiceName);
300 REGISTER_ELEMENT(SingleLogoutService);
301 REGISTER_ELEMENT(SingleSignOnService);
302 REGISTER_ELEMENT(SPSSODescriptor);
303 REGISTER_ELEMENT(SurName);
304 REGISTER_ELEMENT(TelephoneNumber);
305 REGISTER_TYPE(AdditionalMetadataLocation);
306 REGISTER_TYPE(AffiliationDescriptor);
307 REGISTER_TYPE(AttributeAuthorityDescriptor);;
308 REGISTER_TYPE(AttributeConsumingService);
309 REGISTER_TYPE(AuthnAuthorityDescriptor);
310 REGISTER_TYPE(ContactPerson);
311 REGISTER_TYPE(EndpointType);
312 REGISTER_TYPE(EntitiesDescriptor);
313 REGISTER_TYPE(EntityDescriptor);
314 REGISTER_TYPE(Extensions);
315 REGISTER_TYPE(IDPSSODescriptor);
316 REGISTER_TYPE(IndexedEndpointType);
317 REGISTER_TYPE(KeyDescriptor);
318 REGISTER_TYPE(localizedNameType);
319 REGISTER_TYPE(localizedURIType);
320 REGISTER_TYPE(Organization);
321 REGISTER_TYPE(PDPDescriptor);
322 REGISTER_TYPE(RequestedAttribute);
323 REGISTER_TYPE(SPSSODescriptor);
325 q=QName(SAMLConstants::SAML1MD_NS,SourceID::LOCAL_NAME);
326 XMLObjectBuilder::registerBuilder(q,new SourceIDBuilder());
327 SchemaValidators.registerValidator(q,new SourceIDSchemaValidator());
329 q=QName(SAMLConstants::SAML20MD_QUERY_EXT_NS,ActionNamespace::LOCAL_NAME);
330 XMLObjectBuilder::registerBuilder(q,new ActionNamespaceBuilder());
331 SchemaValidators.registerValidator(q,new ActionNamespaceSchemaValidator());
333 q=QName(SAMLConstants::SAML20MD_QUERY_EXT_NS,AuthnQueryDescriptorType::TYPE_NAME);
334 XMLObjectBuilder::registerBuilder(q,new AuthnQueryDescriptorTypeBuilder());
335 SchemaValidators.registerValidator(q,new RoleDescriptorSchemaValidator());
337 q=QName(SAMLConstants::SAML20MD_QUERY_EXT_NS,AttributeQueryDescriptorType::TYPE_NAME);
338 XMLObjectBuilder::registerBuilder(q,new AttributeQueryDescriptorTypeBuilder());
339 SchemaValidators.registerValidator(q,new RoleDescriptorSchemaValidator());
341 q=QName(SAMLConstants::SAML20MD_QUERY_EXT_NS,AuthzDecisionQueryDescriptorType::TYPE_NAME);
342 XMLObjectBuilder::registerBuilder(q,new AuthzDecisionQueryDescriptorTypeBuilder());
343 SchemaValidators.registerValidator(q,new RoleDescriptorSchemaValidator());