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