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