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