2 * Copyright 2001-2006 Internet2
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 * Protocols20SchemaValidators.cpp
20 * Schema-based validators for SAML 2.0 Protocols classes
24 #include "exceptions.h"
25 #include "saml2/core/Protocols.h"
27 using namespace opensaml::saml2p;
28 using namespace opensaml::saml2;
29 using namespace opensaml;
30 using namespace xmltooling;
33 //TODO add in rules from normative spec document
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);
45 class SAML_DLLLOCAL checkWildcardNS {
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())
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;
65 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,StatusCode);
66 XMLOBJECTVALIDATOR_REQUIRE(StatusCode,Value);
67 END_XMLOBJECTVALIDATOR;
69 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,Status);
70 XMLOBJECTVALIDATOR_REQUIRE(Status,StatusCode);
71 END_XMLOBJECTVALIDATOR;
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;
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;
92 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,AuthnQuery);
93 XMLOBJECTVALIDATOR_REQUIRE(AuthnQuery,Subject);
94 END_XMLOBJECTVALIDATOR;
96 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,AttributeQuery);
97 XMLOBJECTVALIDATOR_REQUIRE(AttributeQuery,Subject);
98 END_XMLOBJECTVALIDATOR;
100 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,AuthzDecisionQuery);
101 XMLOBJECTVALIDATOR_REQUIRE(AuthzDecisionQuery,Resource);
102 XMLOBJECTVALIDATOR_REQUIRE(AuthzDecisionQuery,Subject);
103 XMLOBJECTVALIDATOR_NONEMPTY(AuthzDecisionQuery,Action);
104 END_XMLOBJECTVALIDATOR;
106 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,IDPEntry);
107 XMLOBJECTVALIDATOR_REQUIRE(IDPEntry,ProviderID);
108 END_XMLOBJECTVALIDATOR;
110 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,IDPList);
111 XMLOBJECTVALIDATOR_NONEMPTY(IDPList,IDPEntry);
112 END_XMLOBJECTVALIDATOR;
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;
120 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,AuthnRequest);
121 //TODO no schema, but need spec constraints
122 END_XMLOBJECTVALIDATOR;
124 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,StatusResponse);
125 XMLOBJECTVALIDATOR_REQUIRE(StatusResponse,Status);
126 END_XMLOBJECTVALIDATOR;
128 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,Response);
129 XMLOBJECTVALIDATOR_REQUIRE(Response,Status);
130 END_XMLOBJECTVALIDATOR;
132 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,ArtifactResolve);
133 XMLOBJECTVALIDATOR_REQUIRE(ArtifactResolve,Artifact);
134 END_XMLOBJECTVALIDATOR;
136 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,ArtifactResponse);
137 XMLOBJECTVALIDATOR_REQUIRE(ArtifactResponse,Status);
138 END_XMLOBJECTVALIDATOR;
140 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,NewEncryptedID);
141 XMLOBJECTVALIDATOR_REQUIRE(NewEncryptedID,EncryptedData);
142 END_XMLOBJECTVALIDATOR;
144 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,ManageNameIDRequest);
145 XMLOBJECTVALIDATOR_ONLYONEOF(ManageNameIDRequest,NameID,EncryptedID);
146 XMLOBJECTVALIDATOR_ONLYONEOF3(ManageNameIDRequest,NewID,NewEncryptedID,Terminate);
147 END_XMLOBJECTVALIDATOR;
150 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,ManageNameIDResponse);
151 XMLOBJECTVALIDATOR_REQUIRE(ManageNameIDResponse,Status);
152 END_XMLOBJECTVALIDATOR;
154 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,LogoutRequest);
155 XMLOBJECTVALIDATOR_ONLYONEOF3(LogoutRequest,BaseID,NameID,EncryptedID);
156 END_XMLOBJECTVALIDATOR;
158 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,LogoutResponse);
159 XMLOBJECTVALIDATOR_REQUIRE(LogoutResponse,Status);
160 END_XMLOBJECTVALIDATOR;
162 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,NameIDMappingRequest);
163 XMLOBJECTVALIDATOR_ONLYONEOF3(NameIDMappingRequest,BaseID,NameID,EncryptedID);
164 XMLOBJECTVALIDATOR_REQUIRE(NameIDMappingRequest,NameIDPolicy);
165 END_XMLOBJECTVALIDATOR;
167 BEGIN_XMLOBJECTVALIDATOR(SAML_DLLLOCAL,NameIDMappingResponse);
168 XMLOBJECTVALIDATOR_REQUIRE(NameIDMappingResponse,Status);
169 XMLOBJECTVALIDATOR_ONLYONEOF(NameIDMappingResponse,NameID,EncryptedID);
170 END_XMLOBJECTVALIDATOR;
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())
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())
186 #define REGISTER_ELEMENT_NOVAL(cname) \
187 q=QName(SAMLConstants::SAML20P_NS,cname::LOCAL_NAME); \
188 XMLObjectBuilder::registerBuilder(q,new cname##Builder());
190 #define REGISTER_TYPE_NOVAL(cname) \
191 q=QName(SAMLConstants::SAML20P_NS,cname::TYPE_NAME); \
192 XMLObjectBuilder::registerBuilder(q,new cname##Builder());
194 ValidatorSuite opensaml::saml2p::ProtocolSchemaValidators("ProtocolSchemaValidators");
196 void opensaml::saml2p::registerProtocolClasses() {
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);