Multi-line svn commit, see body.
[shibboleth/cpp-opensaml.git] / saml / saml2 / core / impl / Protocols20SchemaValidators.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  * Protocols20SchemaValidators.cpp
19  * 
20  * Schema-based validators for SAML 2.0 Protocols classes
21  */
22
23 #include "internal.h"
24 #include "exceptions.h"
25 #include "saml2/core/Protocols.h"
26
27 using namespace opensaml::saml2p;
28 using namespace opensaml::saml2;
29 using namespace opensaml;
30 using namespace xmltooling;
31 using namespace std;
32
33 //TODO add in rules from normative spec document
34
35 namespace opensaml {
36     namespace saml2p {
37         
38         XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,Artifact);
39         XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,GetComplete);
40         XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,NewID);
41         XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,RequesterID);
42         XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,SessionIndex);
43         XMLOBJECTVALIDATOR_SIMPLE(SAML_DLLLOCAL,StatusMessage);
44
45         class SAML_DLLLOCAL checkWildcardNS {
46         public:
47             void operator()(const XMLObject* xmlObject) const {
48                 const XMLCh* ns=xmlObject->getElementQName().getNamespaceURI();
49                 if (XMLString::equals(ns,SAMLConstants::SAML20P_NS) || !ns || !*ns) {
50                     throw ValidationException(
51                         "Object contains an illegal extension child element ($1).",
52                         params(1,xmlObject->getElementQName().toString().c_str())
53                         );
54                 }
55             }
56         };
57
58         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,Extensions);
59             if (!ptr->hasChildren())
60                 throw ValidationException("Extensions must have at least one child element.");
61             const list<XMLObject*>& anys=ptr->getXMLObjects();
62             for_each(anys.begin(),anys.end(),checkWildcardNS());
63         END_XMLOBJECTVALIDATOR;
64
65         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,StatusCode);
66             XMLOBJECTVALIDATOR_REQUIRE(StatusCode,Value);
67         END_XMLOBJECTVALIDATOR;
68
69         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,Status);
70             XMLOBJECTVALIDATOR_REQUIRE(Status,StatusCode);
71         END_XMLOBJECTVALIDATOR;
72
73         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,AssertionIDRequest);
74             XMLOBJECTVALIDATOR_REQUIRE(AssertionIDRequest,ID);
75             XMLOBJECTVALIDATOR_REQUIRE(AssertionIDRequest,Version);
76             XMLOBJECTVALIDATOR_REQUIRE(AssertionIDRequest,IssueInstant);
77             XMLOBJECTVALIDATOR_NONEMPTY(AssertionIDRequest,AssertionIDRef);
78         END_XMLOBJECTVALIDATOR;
79
80         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,RequestedAuthnContext);
81             if (ptr->getAuthnContextClassRefs().empty() && ptr->getAuthnContextDeclRefs().empty())
82                 throw xmltooling::ValidationException("RequestedAuthnContext must have at least one AuthnContextClassRef or AuthnContextDeclRef"); 
83             if (!ptr->getAuthnContextClassRefs().empty() && !ptr->getAuthnContextDeclRefs().empty())
84                 throw xmltooling::ValidationException("RequestedAuthnContext may not have both AuthnContextClassRef and AuthnContextDeclRef"); 
85             if (!XMLString::equals(ptr->getComparison(),RequestedAuthnContext::COMPARISON_EXACT) &&
86                 !XMLString::equals(ptr->getComparison(),RequestedAuthnContext::COMPARISON_MINIMUM) &&
87                 !XMLString::equals(ptr->getComparison(),RequestedAuthnContext::COMPARISON_MAXIMUM) &&
88                 !XMLString::equals(ptr->getComparison(),RequestedAuthnContext::COMPARISON_BETTER))
89                 throw ValidationException("Comparison must be one of: 'exact', 'minimum', 'maximum', or 'better'.");
90         END_XMLOBJECTVALIDATOR;
91
92         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,AuthnQuery);
93             XMLOBJECTVALIDATOR_REQUIRE(AuthnQuery,Subject);
94         END_XMLOBJECTVALIDATOR;
95
96         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,AttributeQuery);
97             XMLOBJECTVALIDATOR_REQUIRE(AttributeQuery,Subject);
98         END_XMLOBJECTVALIDATOR;
99
100         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,AuthzDecisionQuery);
101             XMLOBJECTVALIDATOR_REQUIRE(AuthzDecisionQuery,Resource);
102             XMLOBJECTVALIDATOR_REQUIRE(AuthzDecisionQuery,Subject);
103             XMLOBJECTVALIDATOR_NONEMPTY(AuthzDecisionQuery,Action);
104         END_XMLOBJECTVALIDATOR;
105
106         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,IDPEntry);
107             XMLOBJECTVALIDATOR_REQUIRE(IDPEntry,ProviderID);
108         END_XMLOBJECTVALIDATOR;
109
110         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,IDPList);
111             XMLOBJECTVALIDATOR_NONEMPTY(IDPList,IDPEntry);
112         END_XMLOBJECTVALIDATOR;
113
114         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,Scoping);
115             pair<bool,int> pc = ptr->getProxyCount();
116             if (pc.first && pc.second < 0) 
117                 throw xmltooling::ValidationException("ProxyCount attribute on Scoping element must be non-negative"); 
118         END_XMLOBJECTVALIDATOR;
119
120         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,AuthnRequest);
121             //TODO no schema, but need spec constraints
122         END_XMLOBJECTVALIDATOR;
123
124         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,StatusResponse);
125             XMLOBJECTVALIDATOR_REQUIRE(StatusResponse,Status);
126         END_XMLOBJECTVALIDATOR;
127
128         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,Response);
129             XMLOBJECTVALIDATOR_REQUIRE(Response,Status);
130         END_XMLOBJECTVALIDATOR;
131
132         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,ArtifactResolve);
133             XMLOBJECTVALIDATOR_REQUIRE(ArtifactResolve,Artifact);
134         END_XMLOBJECTVALIDATOR;
135
136         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,ArtifactResponse);
137             XMLOBJECTVALIDATOR_REQUIRE(ArtifactResponse,Status);
138         END_XMLOBJECTVALIDATOR;
139
140         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,NewEncryptedID);
141             XMLOBJECTVALIDATOR_REQUIRE(NewEncryptedID,EncryptedData);
142         END_XMLOBJECTVALIDATOR;
143
144         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,ManageNameIDRequest);
145             XMLOBJECTVALIDATOR_ONLYONEOF(ManageNameIDRequest,NameID,EncryptedID);
146             XMLOBJECTVALIDATOR_ONLYONEOF3(ManageNameIDRequest,NewID,NewEncryptedID,Terminate);
147         END_XMLOBJECTVALIDATOR;
148
149
150         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,ManageNameIDResponse);
151             XMLOBJECTVALIDATOR_REQUIRE(ManageNameIDResponse,Status);
152         END_XMLOBJECTVALIDATOR;
153
154         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,LogoutRequest);
155             XMLOBJECTVALIDATOR_ONLYONEOF3(LogoutRequest,BaseID,NameID,EncryptedID);
156         END_XMLOBJECTVALIDATOR;
157
158         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,LogoutResponse);
159             XMLOBJECTVALIDATOR_REQUIRE(LogoutResponse,Status);
160         END_XMLOBJECTVALIDATOR;
161
162         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,NameIDMappingRequest);
163             XMLOBJECTVALIDATOR_ONLYONEOF3(NameIDMappingRequest,BaseID,NameID,EncryptedID);
164             XMLOBJECTVALIDATOR_REQUIRE(NameIDMappingRequest,NameIDPolicy);
165         END_XMLOBJECTVALIDATOR;
166
167         BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,NameIDMappingResponse);
168             XMLOBJECTVALIDATOR_REQUIRE(NameIDMappingResponse,Status);
169             XMLOBJECTVALIDATOR_ONLYONEOF(NameIDMappingResponse,NameID,EncryptedID);
170         END_XMLOBJECTVALIDATOR;
171
172
173     };
174 };
175
176 #define REGISTER_ELEMENT(cname) \
177     q=QName(SAMLConstants::SAML20P_NS,cname::LOCAL_NAME); \
178     XMLObjectBuilder::registerBuilder(q,new cname##Builder()); \
179     ProtocolSchemaValidators.registerValidator(q,new cname##SchemaValidator())
180     
181 #define REGISTER_TYPE(cname) \
182     q=QName(SAMLConstants::SAML20P_NS,cname::TYPE_NAME); \
183     XMLObjectBuilder::registerBuilder(q,new cname##Builder()); \
184     ProtocolSchemaValidators.registerValidator(q,new cname##SchemaValidator())
185
186 #define REGISTER_ELEMENT_NOVAL(cname) \
187     q=QName(SAMLConstants::SAML20P_NS,cname::LOCAL_NAME); \
188     XMLObjectBuilder::registerBuilder(q,new cname##Builder());
189     
190 #define REGISTER_TYPE_NOVAL(cname) \
191     q=QName(SAMLConstants::SAML20P_NS,cname::TYPE_NAME); \
192     XMLObjectBuilder::registerBuilder(q,new cname##Builder());
193
194 ValidatorSuite opensaml::saml2p::ProtocolSchemaValidators("ProtocolSchemaValidators");
195
196 void opensaml::saml2p::registerProtocolClasses() {
197     QName q;
198     REGISTER_ELEMENT(Artifact);
199     REGISTER_ELEMENT(ArtifactResolve);
200     REGISTER_ELEMENT(ArtifactResponse);
201     REGISTER_ELEMENT(AssertionIDRequest);
202     REGISTER_ELEMENT(AttributeQuery);
203     REGISTER_ELEMENT(AuthnQuery);
204     REGISTER_ELEMENT(AuthnRequest);
205     REGISTER_ELEMENT(AuthzDecisionQuery);
206     REGISTER_ELEMENT(Extensions);
207     REGISTER_ELEMENT(GetComplete);
208     REGISTER_ELEMENT(IDPEntry);
209     REGISTER_ELEMENT(IDPList);
210     REGISTER_ELEMENT(LogoutRequest);
211     REGISTER_ELEMENT(LogoutResponse);
212     REGISTER_ELEMENT(ManageNameIDRequest);
213     REGISTER_ELEMENT(ManageNameIDResponse);
214     REGISTER_ELEMENT(NameIDMappingRequest);
215     REGISTER_ELEMENT(NameIDMappingResponse);
216     REGISTER_ELEMENT_NOVAL(NameIDPolicy);
217     REGISTER_ELEMENT(NewEncryptedID);
218     REGISTER_ELEMENT(NewID);
219     REGISTER_ELEMENT(RequestedAuthnContext);
220     REGISTER_ELEMENT(RequesterID);
221     REGISTER_ELEMENT(Response);
222     REGISTER_ELEMENT(Scoping);
223     REGISTER_ELEMENT(SessionIndex);
224     REGISTER_ELEMENT(Status);
225     REGISTER_ELEMENT(StatusCode);
226     REGISTER_ELEMENT_NOVAL(StatusDetail);
227     REGISTER_ELEMENT(StatusMessage);
228     REGISTER_ELEMENT_NOVAL(Terminate);
229     REGISTER_TYPE(ArtifactResolve);
230     REGISTER_TYPE(ArtifactResponse);
231     REGISTER_TYPE(AssertionIDRequest);
232     REGISTER_TYPE(AttributeQuery);
233     REGISTER_TYPE(AuthnQuery);
234     REGISTER_TYPE(AuthnRequest);
235     REGISTER_TYPE(AuthzDecisionQuery);
236     REGISTER_TYPE(Extensions);
237     REGISTER_TYPE(IDPEntry);
238     REGISTER_TYPE(IDPList);
239     REGISTER_TYPE(LogoutRequest);
240     REGISTER_TYPE(ManageNameIDRequest);
241     REGISTER_TYPE(NameIDMappingRequest);
242     REGISTER_TYPE(NameIDMappingResponse);
243     REGISTER_TYPE_NOVAL(NameIDPolicy);
244     REGISTER_TYPE(RequestedAuthnContext);
245     REGISTER_TYPE(Response);
246     REGISTER_TYPE(Scoping);
247     REGISTER_TYPE(Status);
248     REGISTER_TYPE(StatusCode);
249     REGISTER_TYPE(StatusResponse);
250     REGISTER_TYPE_NOVAL(StatusDetail);
251     REGISTER_TYPE_NOVAL(Terminate);
252 }