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