Reducing header overuse, non-inlining selected methods (CPPOST-35).
[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/encryption/Encryption.h>
28 #include <xmltooling/validation/Validator.h>
29 #include <xmltooling/validation/ValidatorSuite.h>
30
31 using namespace opensaml::saml2md;
32 using namespace opensaml::saml2;
33 using namespace opensaml;
34 using namespace xmltooling;
35 using namespace std;
36 using samlconstants::SAML20MD_NS;
37 using samlconstants::SAML20MD_QUERY_EXT_NS;
38 using samlconstants::SAML20MD_ENTITY_ATTRIBUTE_NS;
39
40 namespace opensaml {
41     namespace saml2md {
42
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);
53
54         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,localizedNameType);
55             XMLOBJECTVALIDATOR_REQUIRE(localizedNameType,TextContent);
56             XMLOBJECTVALIDATOR_REQUIRE(localizedNameType,Lang);
57         END_XMLOBJECTVALIDATOR;
58
59         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,localizedURIType);
60             XMLOBJECTVALIDATOR_REQUIRE(localizedURIType,TextContent);
61             XMLOBJECTVALIDATOR_REQUIRE(localizedURIType,Lang);
62         END_XMLOBJECTVALIDATOR;
63
64         BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,OrganizationName,localizedNameType);
65             localizedNameTypeSchemaValidator::validate(xmlObject);
66         END_XMLOBJECTVALIDATOR;
67
68         BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,OrganizationDisplayName,localizedNameType);
69             localizedNameTypeSchemaValidator::validate(xmlObject);
70         END_XMLOBJECTVALIDATOR;
71
72         BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,OrganizationURL,localizedURIType);
73             localizedURITypeSchemaValidator::validate(xmlObject);
74         END_XMLOBJECTVALIDATOR;
75
76         class SAML_DLLLOCAL checkWildcardNS {
77         public:
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())
84                         );
85                 }
86             }
87         };
88
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;
95
96         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,Organization);
97             XMLOBJECTVALIDATOR_NONEMPTY(Organization,OrganizationName);
98             XMLOBJECTVALIDATOR_NONEMPTY(Organization,OrganizationDisplayName);
99             XMLOBJECTVALIDATOR_NONEMPTY(Organization,OrganizationURL);
100         END_XMLOBJECTVALIDATOR;
101
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.");
106                 */
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;
114
115         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,AdditionalMetadataLocation);
116             XMLOBJECTVALIDATOR_REQUIRE(AdditionalMetadataLocation,Namespace);
117             XMLOBJECTVALIDATOR_REQUIRE(AdditionalMetadataLocation,Location);
118         END_XMLOBJECTVALIDATOR;
119
120         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,KeyDescriptor);
121             XMLOBJECTVALIDATOR_REQUIRE(KeyDescriptor,KeyInfo);
122             if (ptr->getUse() &&
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;
127
128         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,RoleDescriptor);
129             XMLOBJECTVALIDATOR_REQUIRE(RoleDescriptor,ProtocolSupportEnumeration);
130         END_XMLOBJECTVALIDATOR;
131
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;
138
139         BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,IndexedEndpointType,EndpointType);
140             EndpointTypeSchemaValidator::validate(xmlObject);
141             XMLOBJECTVALIDATOR_REQUIRE_INTEGER(IndexedEndpointType,Index);
142         END_XMLOBJECTVALIDATOR;
143
144         BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,ArtifactResolutionService,IndexedEndpointType);
145             IndexedEndpointTypeSchemaValidator::validate(xmlObject);
146         END_XMLOBJECTVALIDATOR;
147
148         BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,SingleLogoutService,EndpointType);
149             EndpointTypeSchemaValidator::validate(xmlObject);
150         END_XMLOBJECTVALIDATOR;
151
152         BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,ManageNameIDService,EndpointType);
153             EndpointTypeSchemaValidator::validate(xmlObject);
154         END_XMLOBJECTVALIDATOR;
155
156         BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,SingleSignOnService,EndpointType);
157             EndpointTypeSchemaValidator::validate(xmlObject);
158         END_XMLOBJECTVALIDATOR;
159
160         BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,NameIDMappingService,EndpointType);
161             EndpointTypeSchemaValidator::validate(xmlObject);
162         END_XMLOBJECTVALIDATOR;
163
164         BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,AssertionIDRequestService,EndpointType);
165             EndpointTypeSchemaValidator::validate(xmlObject);
166         END_XMLOBJECTVALIDATOR;
167
168         BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,IDPSSODescriptor,RoleDescriptor);
169             RoleDescriptorSchemaValidator::validate(xmlObject);
170             XMLOBJECTVALIDATOR_NONEMPTY(IDPSSODescriptor,SingleSignOnService);
171         END_XMLOBJECTVALIDATOR;
172
173         BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,ServiceName,localizedNameType);
174             localizedNameTypeSchemaValidator::validate(xmlObject);
175         END_XMLOBJECTVALIDATOR;
176
177         BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,ServiceDescription,localizedNameType);
178             localizedNameTypeSchemaValidator::validate(xmlObject);
179         END_XMLOBJECTVALIDATOR;
180
181         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,RequestedAttribute);
182             XMLOBJECTVALIDATOR_REQUIRE(RequestedAttribute,Name);
183         END_XMLOBJECTVALIDATOR;
184
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;
190
191         BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,AssertionConsumerService,IndexedEndpointType);
192             IndexedEndpointTypeSchemaValidator::validate(xmlObject);
193         END_XMLOBJECTVALIDATOR;
194
195         BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,SPSSODescriptor,RoleDescriptor);
196             RoleDescriptorSchemaValidator::validate(xmlObject);
197             XMLOBJECTVALIDATOR_NONEMPTY(SPSSODescriptor,AssertionConsumerService);
198         END_XMLOBJECTVALIDATOR;
199
200         BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,AuthnQueryService,EndpointType);
201             EndpointTypeSchemaValidator::validate(xmlObject);
202         END_XMLOBJECTVALIDATOR;
203
204         BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,AuthnAuthorityDescriptor,RoleDescriptor);
205             RoleDescriptorSchemaValidator::validate(xmlObject);
206             XMLOBJECTVALIDATOR_NONEMPTY(AuthnAuthorityDescriptor,AuthnQueryService);
207         END_XMLOBJECTVALIDATOR;
208
209         BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,AuthzService,EndpointType);
210             EndpointTypeSchemaValidator::validate(xmlObject);
211         END_XMLOBJECTVALIDATOR;
212
213         BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,PDPDescriptor,RoleDescriptor);
214             RoleDescriptorSchemaValidator::validate(xmlObject);
215             XMLOBJECTVALIDATOR_NONEMPTY(PDPDescriptor,AuthzService);
216         END_XMLOBJECTVALIDATOR;
217
218         BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,AttributeService,EndpointType);
219             EndpointTypeSchemaValidator::validate(xmlObject);
220         END_XMLOBJECTVALIDATOR;
221
222         BEGIN_XMLOBJECTVALIDATOR_SUB(SAML_DLLLOCAL,AttributeAuthorityDescriptor,RoleDescriptor);
223             RoleDescriptorSchemaValidator::validate(xmlObject);
224             XMLOBJECTVALIDATOR_NONEMPTY(AttributeAuthorityDescriptor,AttributeService);
225         END_XMLOBJECTVALIDATOR;
226
227         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,AffiliationDescriptor);
228             XMLOBJECTVALIDATOR_REQUIRE(AffiliationDescriptor,AffiliationOwnerID);
229             XMLOBJECTVALIDATOR_NONEMPTY(AffiliationDescriptor,AffiliateMember);
230         END_XMLOBJECTVALIDATOR;
231
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()) {
240
241                 if (!ptr->getAffiliationDescriptor())
242                     throw ValidationException("EntityDescriptor must have at least one child role or affiliation descriptor.");
243             }
244             else if (ptr->getAffiliationDescriptor()) {
245                 throw ValidationException("EntityDescriptor cannot have both an AffiliationDescriptor and role descriptors.");
246             }
247         END_XMLOBJECTVALIDATOR;
248
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;
253
254         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,EntityAttributes);
255             if (!ptr->hasChildren())
256                 throw ValidationException("EntityAttributes must contain at least one child element.");
257         END_XMLOBJECTVALIDATOR;
258
259     };
260 };
261
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())
266
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())
271
272 #define REGISTER_ELEMENT_NOVAL(cname) \
273     q=xmltooling::QName(SAML20MD_NS,cname::LOCAL_NAME); \
274     XMLObjectBuilder::registerBuilder(q,new cname##Builder());
275
276 #define REGISTER_TYPE_NOVAL(cname) \
277     q=xmltooling::QName(SAML20MD_NS,cname::TYPE_NAME); \
278     XMLObjectBuilder::registerBuilder(q,new cname##Builder());
279
280 void opensaml::saml2md::registerMetadataClasses() {
281     xmltooling::QName q;
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);
340
341     q=xmltooling::QName(SAML20MD_NS,xmlencryption::EncryptionMethod::LOCAL_NAME);
342     XMLObjectBuilder::registerBuilder(q,new xmlencryption::EncryptionMethodBuilder());
343
344     q=xmltooling::QName(samlconstants::SAML1MD_NS,SourceID::LOCAL_NAME);
345     XMLObjectBuilder::registerBuilder(q,new SourceIDBuilder());
346     SchemaValidators.registerValidator(q,new SourceIDSchemaValidator());
347
348     q=xmltooling::QName(SAML20MD_QUERY_EXT_NS,ActionNamespace::LOCAL_NAME);
349     XMLObjectBuilder::registerBuilder(q,new ActionNamespaceBuilder());
350     SchemaValidators.registerValidator(q,new ActionNamespaceSchemaValidator());
351
352     q=xmltooling::QName(SAML20MD_QUERY_EXT_NS,AuthnQueryDescriptorType::TYPE_NAME);
353     XMLObjectBuilder::registerBuilder(q,new AuthnQueryDescriptorTypeBuilder());
354     SchemaValidators.registerValidator(q,new RoleDescriptorSchemaValidator());
355
356     q=xmltooling::QName(SAML20MD_QUERY_EXT_NS,AttributeQueryDescriptorType::TYPE_NAME);
357     XMLObjectBuilder::registerBuilder(q,new AttributeQueryDescriptorTypeBuilder());
358     SchemaValidators.registerValidator(q,new RoleDescriptorSchemaValidator());
359
360     q=xmltooling::QName(SAML20MD_QUERY_EXT_NS,AuthzDecisionQueryDescriptorType::TYPE_NAME);
361     XMLObjectBuilder::registerBuilder(q,new AuthzDecisionQueryDescriptorTypeBuilder());
362     SchemaValidators.registerValidator(q,new RoleDescriptorSchemaValidator());
363
364     q=xmltooling::QName(SAML20MD_ENTITY_ATTRIBUTE_NS,EntityAttributes::LOCAL_NAME);
365     XMLObjectBuilder::registerBuilder(q,new EntityAttributesBuilder());
366     SchemaValidators.registerValidator(q,new EntityAttributesSchemaValidator());
367
368     q=xmltooling::QName(SAML20MD_ENTITY_ATTRIBUTE_NS,EntityAttributes::TYPE_NAME);
369     XMLObjectBuilder::registerBuilder(q,new EntityAttributesBuilder());
370     SchemaValidators.registerValidator(q,new EntityAttributesSchemaValidator());
371 }