Add XML objects for DelegationRestriction and EntityAttributes extensions.
[shibboleth/cpp-opensaml.git] / saml / saml2 / metadata / impl / MetadataSchemaValidators.cpp
1 /*
2 *  Copyright 2001-2009 Internet2
3  *
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
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 /**
18  * MetadataSchemaValidators.cpp
19  *
20  * Schema-based validators for SAML 2.0 Metadata classes
21  */
22
23 #include "internal.h"
24 #include "exceptions.h"
25 #include "saml2/metadata/Metadata.h"
26
27 #include <xmltooling/validation/ValidatorSuite.h>
28
29 using namespace opensaml::saml2md;
30 using namespace opensaml::saml2;
31 using namespace opensaml;
32 using namespace xmltooling;
33 using namespace std;
34 using samlconstants::SAML20MD_NS;
35 using samlconstants::SAML20MD_QUERY_EXT_NS;
36 using samlconstants::SAML20MD_ENTITY_ATTRIBUTE_NS;
37
38 namespace opensaml {
39     namespace saml2md {
40
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);
51
52         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,localizedNameType);
53             XMLOBJECTVALIDATOR_REQUIRE(localizedNameType,TextContent);
54             XMLOBJECTVALIDATOR_REQUIRE(localizedNameType,Lang);
55         END_XMLOBJECTVALIDATOR;
56
57         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,localizedURIType);
58             XMLOBJECTVALIDATOR_REQUIRE(localizedURIType,TextContent);
59             XMLOBJECTVALIDATOR_REQUIRE(localizedURIType,Lang);
60         END_XMLOBJECTVALIDATOR;
61
62         BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,OrganizationName,localizedNameType);
63             localizedNameTypeSchemaValidator::validate(xmlObject);
64         END_XMLOBJECTVALIDATOR;
65
66         BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,OrganizationDisplayName,localizedNameType);
67             localizedNameTypeSchemaValidator::validate(xmlObject);
68         END_XMLOBJECTVALIDATOR;
69
70         BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,OrganizationURL,localizedURIType);
71             localizedURITypeSchemaValidator::validate(xmlObject);
72         END_XMLOBJECTVALIDATOR;
73
74         class SAML_DLLLOCAL checkWildcardNS {
75         public:
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())
82                         );
83                 }
84             }
85         };
86
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;
93
94         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,Organization);
95             XMLOBJECTVALIDATOR_NONEMPTY(Organization,OrganizationName);
96             XMLOBJECTVALIDATOR_NONEMPTY(Organization,OrganizationDisplayName);
97             XMLOBJECTVALIDATOR_NONEMPTY(Organization,OrganizationURL);
98         END_XMLOBJECTVALIDATOR;
99
100         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,ContactPerson);
101             if (!ptr->hasChildren())
102                 throw ValidationException("ContactPerson must have at least one child element.");
103             if (!XMLString::equals(ptr->getContactType(),ContactPerson::CONTACT_TECHNICAL) &&
104                 !XMLString::equals(ptr->getContactType(),ContactPerson::CONTACT_SUPPORT) &&
105                 !XMLString::equals(ptr->getContactType(),ContactPerson::CONTACT_ADMINISTRATIVE) &&
106                 !XMLString::equals(ptr->getContactType(),ContactPerson::CONTACT_BILLING) &&
107                 !XMLString::equals(ptr->getContactType(),ContactPerson::CONTACT_OTHER))
108                 throw ValidationException("ContactPerson contactType must be one of the defined values.");
109         END_XMLOBJECTVALIDATOR;
110
111         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,AdditionalMetadataLocation);
112             XMLOBJECTVALIDATOR_REQUIRE(AdditionalMetadataLocation,Namespace);
113             XMLOBJECTVALIDATOR_REQUIRE(AdditionalMetadataLocation,Location);
114         END_XMLOBJECTVALIDATOR;
115
116         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,KeyDescriptor);
117             XMLOBJECTVALIDATOR_REQUIRE(KeyDescriptor,KeyInfo);
118             if (ptr->getUse() &&
119                 !XMLString::equals(ptr->getUse(),KeyDescriptor::KEYTYPE_ENCRYPTION) &&
120                 !XMLString::equals(ptr->getUse(),KeyDescriptor::KEYTYPE_SIGNING))
121                 throw ValidationException("KeyDescriptor use must be empty or one of the defined values.");
122         END_XMLOBJECTVALIDATOR;
123
124         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,RoleDescriptor);
125             XMLOBJECTVALIDATOR_REQUIRE(RoleDescriptor,ProtocolSupportEnumeration);
126         END_XMLOBJECTVALIDATOR;
127
128         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,EndpointType);
129             XMLOBJECTVALIDATOR_REQUIRE(EndpointType,Binding);
130             XMLOBJECTVALIDATOR_REQUIRE(EndpointType,Location);
131             const vector<XMLObject*>& anys=ptr->getUnknownXMLObjects();
132             for_each(anys.begin(),anys.end(),checkWildcardNS());
133         END_XMLOBJECTVALIDATOR;
134
135         BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,IndexedEndpointType,EndpointType);
136             EndpointTypeSchemaValidator::validate(xmlObject);
137             XMLOBJECTVALIDATOR_REQUIRE_INTEGER(IndexedEndpointType,Index);
138         END_XMLOBJECTVALIDATOR;
139
140         BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,ArtifactResolutionService,IndexedEndpointType);
141             IndexedEndpointTypeSchemaValidator::validate(xmlObject);
142         END_XMLOBJECTVALIDATOR;
143
144         BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,SingleLogoutService,EndpointType);
145             EndpointTypeSchemaValidator::validate(xmlObject);
146         END_XMLOBJECTVALIDATOR;
147
148         BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,ManageNameIDService,EndpointType);
149             EndpointTypeSchemaValidator::validate(xmlObject);
150         END_XMLOBJECTVALIDATOR;
151
152         BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,SingleSignOnService,EndpointType);
153             EndpointTypeSchemaValidator::validate(xmlObject);
154         END_XMLOBJECTVALIDATOR;
155
156         BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,NameIDMappingService,EndpointType);
157             EndpointTypeSchemaValidator::validate(xmlObject);
158         END_XMLOBJECTVALIDATOR;
159
160         BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,AssertionIDRequestService,EndpointType);
161             EndpointTypeSchemaValidator::validate(xmlObject);
162         END_XMLOBJECTVALIDATOR;
163
164         BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,IDPSSODescriptor,RoleDescriptor);
165             RoleDescriptorSchemaValidator::validate(xmlObject);
166             XMLOBJECTVALIDATOR_NONEMPTY(IDPSSODescriptor,SingleSignOnService);
167         END_XMLOBJECTVALIDATOR;
168
169         BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,ServiceName,localizedNameType);
170             localizedNameTypeSchemaValidator::validate(xmlObject);
171         END_XMLOBJECTVALIDATOR;
172
173         BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,ServiceDescription,localizedNameType);
174             localizedNameTypeSchemaValidator::validate(xmlObject);
175         END_XMLOBJECTVALIDATOR;
176
177         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,RequestedAttribute);
178             XMLOBJECTVALIDATOR_REQUIRE(RequestedAttribute,Name);
179         END_XMLOBJECTVALIDATOR;
180
181         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,AttributeConsumingService);
182             XMLOBJECTVALIDATOR_REQUIRE_INTEGER(AttributeConsumingService,Index);
183             XMLOBJECTVALIDATOR_NONEMPTY(AttributeConsumingService,ServiceName);
184             XMLOBJECTVALIDATOR_NONEMPTY(AttributeConsumingService,RequestedAttribute);
185         END_XMLOBJECTVALIDATOR;
186
187         BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,AssertionConsumerService,IndexedEndpointType);
188             IndexedEndpointTypeSchemaValidator::validate(xmlObject);
189         END_XMLOBJECTVALIDATOR;
190
191         BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,SPSSODescriptor,RoleDescriptor);
192             RoleDescriptorSchemaValidator::validate(xmlObject);
193             XMLOBJECTVALIDATOR_NONEMPTY(SPSSODescriptor,AssertionConsumerService);
194         END_XMLOBJECTVALIDATOR;
195
196         BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,AuthnQueryService,EndpointType);
197             EndpointTypeSchemaValidator::validate(xmlObject);
198         END_XMLOBJECTVALIDATOR;
199
200         BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,AuthnAuthorityDescriptor,RoleDescriptor);
201             RoleDescriptorSchemaValidator::validate(xmlObject);
202             XMLOBJECTVALIDATOR_NONEMPTY(AuthnAuthorityDescriptor,AuthnQueryService);
203         END_XMLOBJECTVALIDATOR;
204
205         BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,AuthzService,EndpointType);
206             EndpointTypeSchemaValidator::validate(xmlObject);
207         END_XMLOBJECTVALIDATOR;
208
209         BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,PDPDescriptor,RoleDescriptor);
210             RoleDescriptorSchemaValidator::validate(xmlObject);
211             XMLOBJECTVALIDATOR_NONEMPTY(PDPDescriptor,AuthzService);
212         END_XMLOBJECTVALIDATOR;
213
214         BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,AttributeService,EndpointType);
215             EndpointTypeSchemaValidator::validate(xmlObject);
216         END_XMLOBJECTVALIDATOR;
217
218         BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,AttributeAuthorityDescriptor,RoleDescriptor);
219             RoleDescriptorSchemaValidator::validate(xmlObject);
220             XMLOBJECTVALIDATOR_NONEMPTY(AttributeAuthorityDescriptor,AttributeService);
221         END_XMLOBJECTVALIDATOR;
222
223         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,AffiliationDescriptor);
224             XMLOBJECTVALIDATOR_REQUIRE(AffiliationDescriptor,AffiliationOwnerID);
225             XMLOBJECTVALIDATOR_NONEMPTY(AffiliationDescriptor,AffiliateMember);
226         END_XMLOBJECTVALIDATOR;
227
228         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,EntityDescriptor);
229             XMLOBJECTVALIDATOR_REQUIRE(EntityDescriptor,EntityID);
230             if (ptr->getRoleDescriptors().empty() &&
231                 ptr->getIDPSSODescriptors().empty() &&
232                 ptr->getSPSSODescriptors().empty() &&
233                 ptr->getAuthnAuthorityDescriptors().empty() &&
234                 ptr->getAttributeAuthorityDescriptors().empty() &&
235                 ptr->getPDPDescriptors().empty()) {
236
237                 if (!ptr->getAffiliationDescriptor())
238                     throw ValidationException("EntityDescriptor must have at least one child role or affiliation descriptor.");
239             }
240             else if (ptr->getAffiliationDescriptor()) {
241                 throw ValidationException("EntityDescriptor cannot have both an AffiliationDescriptor and role descriptors.");
242             }
243         END_XMLOBJECTVALIDATOR;
244
245         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,EntitiesDescriptor);
246             if (ptr->getEntityDescriptors().empty() && ptr->getEntitiesDescriptors().empty())
247                 throw ValidationException("EntitiesDescriptor must contain at least one child descriptor.");
248         END_XMLOBJECTVALIDATOR;
249
250         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,EntityAttributes);
251             if (!ptr->hasChildren())
252                 throw ValidationException("EntityAttributes must contain at least one child element.");
253         END_XMLOBJECTVALIDATOR;
254
255     };
256 };
257
258 #define REGISTER_ELEMENT(cname) \
259     q=xmltooling::QName(SAML20MD_NS,cname::LOCAL_NAME); \
260     XMLObjectBuilder::registerBuilder(q,new cname##Builder()); \
261     SchemaValidators.registerValidator(q,new cname##SchemaValidator())
262
263 #define REGISTER_TYPE(cname) \
264     q=xmltooling::QName(SAML20MD_NS,cname::TYPE_NAME); \
265     XMLObjectBuilder::registerBuilder(q,new cname##Builder()); \
266     SchemaValidators.registerValidator(q,new cname##SchemaValidator())
267
268 #define REGISTER_ELEMENT_NOVAL(cname) \
269     q=xmltooling::QName(SAML20MD_NS,cname::LOCAL_NAME); \
270     XMLObjectBuilder::registerBuilder(q,new cname##Builder());
271
272 #define REGISTER_TYPE_NOVAL(cname) \
273     q=xmltooling::QName(SAML20MD_NS,cname::TYPE_NAME); \
274     XMLObjectBuilder::registerBuilder(q,new cname##Builder());
275
276 void opensaml::saml2md::registerMetadataClasses() {
277     xmltooling::QName q;
278     REGISTER_ELEMENT(AdditionalMetadataLocation);
279     REGISTER_ELEMENT(AffiliateMember);
280     REGISTER_ELEMENT(AffiliationDescriptor);
281     REGISTER_ELEMENT(ArtifactResolutionService);
282     REGISTER_ELEMENT(AssertionConsumerService);
283     REGISTER_ELEMENT(AssertionIDRequestService);
284     REGISTER_ELEMENT(AttributeAuthorityDescriptor);;
285     REGISTER_ELEMENT(AttributeConsumingService);
286     REGISTER_ELEMENT(AttributeProfile);
287     REGISTER_ELEMENT(AttributeService);
288     REGISTER_ELEMENT(AuthnAuthorityDescriptor);
289     REGISTER_ELEMENT(AuthnQueryService);
290     REGISTER_ELEMENT(AuthzService);
291     REGISTER_ELEMENT(Company);
292     REGISTER_ELEMENT(ContactPerson);
293     REGISTER_ELEMENT(EmailAddress);
294     REGISTER_ELEMENT(EntitiesDescriptor);
295     REGISTER_ELEMENT(EntityDescriptor);
296     REGISTER_ELEMENT(Extensions);
297     REGISTER_ELEMENT(GivenName);
298     REGISTER_ELEMENT(IDPSSODescriptor);
299     REGISTER_ELEMENT(KeyDescriptor);
300     REGISTER_ELEMENT(ManageNameIDService);
301     REGISTER_ELEMENT(NameIDFormat);
302     REGISTER_ELEMENT(NameIDMappingService);
303     REGISTER_ELEMENT(Organization);
304     REGISTER_ELEMENT(OrganizationDisplayName);
305     REGISTER_ELEMENT(OrganizationName);
306     REGISTER_ELEMENT(OrganizationURL);
307     REGISTER_ELEMENT(PDPDescriptor);
308     REGISTER_ELEMENT(RequestedAttribute);
309     REGISTER_ELEMENT(RoleDescriptor);
310     REGISTER_ELEMENT(ServiceDescription);
311     REGISTER_ELEMENT(ServiceName);
312     REGISTER_ELEMENT(SingleLogoutService);
313     REGISTER_ELEMENT(SingleSignOnService);
314     REGISTER_ELEMENT(SPSSODescriptor);
315     REGISTER_ELEMENT(SurName);
316     REGISTER_ELEMENT(TelephoneNumber);
317     REGISTER_TYPE(AdditionalMetadataLocation);
318     REGISTER_TYPE(AffiliationDescriptor);
319     REGISTER_TYPE(AttributeAuthorityDescriptor);;
320     REGISTER_TYPE(AttributeConsumingService);
321     REGISTER_TYPE(AuthnAuthorityDescriptor);
322     REGISTER_TYPE(ContactPerson);
323     REGISTER_TYPE(EndpointType);
324     REGISTER_TYPE(EntitiesDescriptor);
325     REGISTER_TYPE(EntityDescriptor);
326     REGISTER_TYPE(Extensions);
327     REGISTER_TYPE(IDPSSODescriptor);
328     REGISTER_TYPE(IndexedEndpointType);
329     REGISTER_TYPE(KeyDescriptor);
330     REGISTER_TYPE(localizedNameType);
331     REGISTER_TYPE(localizedURIType);
332     REGISTER_TYPE(Organization);
333     REGISTER_TYPE(PDPDescriptor);
334     REGISTER_TYPE(RequestedAttribute);
335     REGISTER_TYPE(SPSSODescriptor);
336
337     q=xmltooling::QName(SAML20MD_NS,xmlencryption::EncryptionMethod::LOCAL_NAME);
338     XMLObjectBuilder::registerBuilder(q,new xmlencryption::EncryptionMethodBuilder());
339
340     q=xmltooling::QName(samlconstants::SAML1MD_NS,SourceID::LOCAL_NAME);
341     XMLObjectBuilder::registerBuilder(q,new SourceIDBuilder());
342     SchemaValidators.registerValidator(q,new SourceIDSchemaValidator());
343
344     q=xmltooling::QName(SAML20MD_QUERY_EXT_NS,ActionNamespace::LOCAL_NAME);
345     XMLObjectBuilder::registerBuilder(q,new ActionNamespaceBuilder());
346     SchemaValidators.registerValidator(q,new ActionNamespaceSchemaValidator());
347
348     q=xmltooling::QName(SAML20MD_QUERY_EXT_NS,AuthnQueryDescriptorType::TYPE_NAME);
349     XMLObjectBuilder::registerBuilder(q,new AuthnQueryDescriptorTypeBuilder());
350     SchemaValidators.registerValidator(q,new RoleDescriptorSchemaValidator());
351
352     q=xmltooling::QName(SAML20MD_QUERY_EXT_NS,AttributeQueryDescriptorType::TYPE_NAME);
353     XMLObjectBuilder::registerBuilder(q,new AttributeQueryDescriptorTypeBuilder());
354     SchemaValidators.registerValidator(q,new RoleDescriptorSchemaValidator());
355
356     q=xmltooling::QName(SAML20MD_QUERY_EXT_NS,AuthzDecisionQueryDescriptorType::TYPE_NAME);
357     XMLObjectBuilder::registerBuilder(q,new AuthzDecisionQueryDescriptorTypeBuilder());
358     SchemaValidators.registerValidator(q,new RoleDescriptorSchemaValidator());
359
360     q=xmltooling::QName(SAML20MD_ENTITY_ATTRIBUTE_NS,EntityAttributes::LOCAL_NAME);
361     XMLObjectBuilder::registerBuilder(q,new EntityAttributesBuilder());
362     SchemaValidators.registerValidator(q,new EntityAttributesSchemaValidator());
363
364     q=xmltooling::QName(SAML20MD_ENTITY_ATTRIBUTE_NS,EntityAttributes::TYPE_NAME);
365     XMLObjectBuilder::registerBuilder(q,new EntityAttributesBuilder());
366     SchemaValidators.registerValidator(q,new EntityAttributesSchemaValidator());
367 }