e79a07656592638b99f91eb0eee33edf31c4b095
[shibboleth/cpp-xmltooling.git] / xmltooling / signature / impl / KeyInfoSchemaValidators.cpp
1 /*
2 *  Copyright 2001-2010 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  * KeyInfoSchemaValidators.cpp
19  * 
20  * Schema validators for KeyInfo schema.
21  */
22
23 #include "internal.h"
24 #include "exceptions.h"
25 #include "signature/KeyInfo.h"
26 #include "validation/Validator.h"
27 #include "validation/ValidatorSuite.h"
28
29 using namespace xmlsignature;
30 using namespace xmltooling;
31 using namespace std;
32 using xmlconstants::XMLSIG_NS;
33 using xmlconstants::XMLSIG11_NS;
34
35 #define XMLOBJECTVALIDATOR_ONLYONEOF4(cname,proper1,proper2,proper3,proper4) \
36     int c##proper1##proper2##proper3##proper4=0; \
37     if (ptr->get##proper1()!=nullptr) \
38         c##proper1##proper2##proper3##proper4++; \
39     if (ptr->get##proper2()!=nullptr) \
40         c##proper1##proper2##proper3##proper4++; \
41     if (ptr->get##proper3()!=nullptr) \
42         c##proper1##proper2##proper3##proper4++; \
43     if (ptr->get##proper4()!=nullptr) \
44         c##proper1##proper2##proper3##proper4++; \
45     if (c##proper1##proper2##proper3##proper4 != 1) \
46         throw xmltooling::ValidationException(#cname" must have only one of "#proper1", "#proper2", "#proper3", or "#proper4".")
47
48 namespace xmlsignature {
49
50     XMLOBJECTVALIDATOR_SIMPLE(XMLTOOL_DLLLOCAL,KeyName);
51     XMLOBJECTVALIDATOR_SIMPLE(XMLTOOL_DLLLOCAL,MgmtData);
52     XMLOBJECTVALIDATOR_SIMPLE(XMLTOOL_DLLLOCAL,Modulus);
53     XMLOBJECTVALIDATOR_SIMPLE(XMLTOOL_DLLLOCAL,Exponent);
54     XMLOBJECTVALIDATOR_SIMPLE(XMLTOOL_DLLLOCAL,Seed);
55     XMLOBJECTVALIDATOR_SIMPLE(XMLTOOL_DLLLOCAL,PgenCounter);
56     XMLOBJECTVALIDATOR_SIMPLE(XMLTOOL_DLLLOCAL,P);
57     XMLOBJECTVALIDATOR_SIMPLE(XMLTOOL_DLLLOCAL,Q);
58     XMLOBJECTVALIDATOR_SIMPLE(XMLTOOL_DLLLOCAL,G);
59     XMLOBJECTVALIDATOR_SIMPLE(XMLTOOL_DLLLOCAL,Y);
60     XMLOBJECTVALIDATOR_SIMPLE(XMLTOOL_DLLLOCAL,J);
61     XMLOBJECTVALIDATOR_SIMPLE(XMLTOOL_DLLLOCAL,XPath);
62     XMLOBJECTVALIDATOR_SIMPLE(XMLTOOL_DLLLOCAL,X509IssuerName);
63     XMLOBJECTVALIDATOR_SIMPLE(XMLTOOL_DLLLOCAL,X509SerialNumber);
64     XMLOBJECTVALIDATOR_SIMPLE(XMLTOOL_DLLLOCAL,X509SKI);
65     XMLOBJECTVALIDATOR_SIMPLE(XMLTOOL_DLLLOCAL,X509SubjectName);
66     XMLOBJECTVALIDATOR_SIMPLE(XMLTOOL_DLLLOCAL,X509Certificate);
67     XMLOBJECTVALIDATOR_SIMPLE(XMLTOOL_DLLLOCAL,X509CRL);
68     XMLOBJECTVALIDATOR_SIMPLE(XMLTOOL_DLLLOCAL,SPKISexp);
69     XMLOBJECTVALIDATOR_SIMPLE(XMLTOOL_DLLLOCAL,PGPKeyID);
70     XMLOBJECTVALIDATOR_SIMPLE(XMLTOOL_DLLLOCAL,PGPKeyPacket);
71
72     XMLOBJECTVALIDATOR_SIMPLE(XMLTOOL_DLLLOCAL,DEREncodedKeyValue);
73     XMLOBJECTVALIDATOR_SIMPLE(XMLTOOL_DLLLOCAL,OCSPResponse);
74     XMLOBJECTVALIDATOR_SIMPLE(XMLTOOL_DLLLOCAL,PublicKey);
75     
76     BEGIN_XMLOBJECTVALIDATOR(XMLTOOL_DLLLOCAL,RSAKeyValue);
77         XMLOBJECTVALIDATOR_REQUIRE(RSAKeyValue,Modulus);
78         XMLOBJECTVALIDATOR_REQUIRE(RSAKeyValue,Exponent);
79     END_XMLOBJECTVALIDATOR;
80
81     BEGIN_XMLOBJECTVALIDATOR(XMLTOOL_DLLLOCAL,DSAKeyValue);
82         XMLOBJECTVALIDATOR_REQUIRE(DSAKeyValue,Y);
83         XMLOBJECTVALIDATOR_NONEORBOTH(DSKeyValue,P,Q);
84         XMLOBJECTVALIDATOR_NONEORBOTH(DSKeyValue,Seed,PgenCounter);
85     END_XMLOBJECTVALIDATOR;
86
87     BEGIN_XMLOBJECTVALIDATOR(XMLTOOL_DLLLOCAL,KeyValue);
88         XMLOBJECTVALIDATOR_ONLYONEOF4(KeyValue,DSAKeyValue,RSAKeyValue,ECKeyValue,UnknownXMLObject);
89     END_XMLOBJECTVALIDATOR;
90
91     BEGIN_XMLOBJECTVALIDATOR(XMLTOOL_DLLLOCAL,Transform);
92         XMLOBJECTVALIDATOR_REQUIRE(Transform,Algorithm);
93     END_XMLOBJECTVALIDATOR;
94
95     BEGIN_XMLOBJECTVALIDATOR(XMLTOOL_DLLLOCAL,Transforms);
96         XMLOBJECTVALIDATOR_NONEMPTY(Transforms,Transform);
97     END_XMLOBJECTVALIDATOR;
98
99     BEGIN_XMLOBJECTVALIDATOR(XMLTOOL_DLLLOCAL,RetrievalMethod);
100         XMLOBJECTVALIDATOR_REQUIRE(RetrievalMethod,URI);
101     END_XMLOBJECTVALIDATOR;
102
103     BEGIN_XMLOBJECTVALIDATOR(XMLTOOL_DLLLOCAL,X509IssuerSerial);
104         XMLOBJECTVALIDATOR_REQUIRE(X509IssuerSerial,X509IssuerName);
105         XMLOBJECTVALIDATOR_REQUIRE(X509IssuerSerial,X509SerialNumber);
106     END_XMLOBJECTVALIDATOR;
107
108     class XMLTOOL_DLLLOCAL checkWildcardNS {
109     public:
110         void operator()(const XMLObject* xmlObject) const {
111             const XMLCh* ns=xmlObject->getElementQName().getNamespaceURI();
112             if (XMLString::equals(ns,XMLSIG_NS) || !ns || !*ns) {
113                 throw ValidationException(
114                     "Object contains an illegal extension child element ($1).",
115                     params(1,xmlObject->getElementQName().toString().c_str())
116                     );
117             }
118         }
119     };
120     
121     BEGIN_XMLOBJECTVALIDATOR(XMLTOOL_DLLLOCAL,X509Data);
122         if (!ptr->hasChildren())
123             throw ValidationException("X509Data must have at least one child element.");
124         const vector<XMLObject*>& anys=ptr->getUnknownXMLObjects();
125         for_each(anys.begin(),anys.end(),checkWildcardNS());
126     END_XMLOBJECTVALIDATOR;
127
128     BEGIN_XMLOBJECTVALIDATOR(XMLTOOL_DLLLOCAL,SPKIData);
129         XMLOBJECTVALIDATOR_NONEMPTY(SPKIData,SPKISexp);
130     END_XMLOBJECTVALIDATOR;
131
132     BEGIN_XMLOBJECTVALIDATOR(XMLTOOL_DLLLOCAL,PGPData);
133         XMLOBJECTVALIDATOR_ONEOF(PGPData,PGPKeyID,PGPKeyPacket);
134     END_XMLOBJECTVALIDATOR;
135
136     BEGIN_XMLOBJECTVALIDATOR(XMLTOOL_DLLLOCAL,KeyInfo);
137         if (!ptr->hasChildren())
138             throw ValidationException("KeyInfo must have at least one child element.");
139         const vector<XMLObject*>& anys=ptr->getUnknownXMLObjects();
140         for_each(anys.begin(),anys.end(),checkWildcardNS());
141     END_XMLOBJECTVALIDATOR;
142
143     BEGIN_XMLOBJECTVALIDATOR(XMLTOOL_DLLLOCAL,KeyInfoReference);
144         XMLOBJECTVALIDATOR_REQUIRE(KeyInfoReference,URI);
145     END_XMLOBJECTVALIDATOR;
146
147     BEGIN_XMLOBJECTVALIDATOR(XMLTOOL_DLLLOCAL,NamedCurve);
148         XMLOBJECTVALIDATOR_REQUIRE(NamedCurve,URI);
149     END_XMLOBJECTVALIDATOR;
150
151     BEGIN_XMLOBJECTVALIDATOR(XMLTOOL_DLLLOCAL,ECKeyValue);
152         XMLOBJECTVALIDATOR_ONEOF(ECKeyValue,ECParameters,NamedCurve);
153         XMLOBJECTVALIDATOR_REQUIRE(ECKeyValue,PublicKey);
154     END_XMLOBJECTVALIDATOR;
155
156     BEGIN_XMLOBJECTVALIDATOR(XMLTOOL_DLLLOCAL,X509Digest);
157         XMLOBJECTVALIDATOR_REQUIRE(X509Digest,Algorithm);
158     END_XMLOBJECTVALIDATOR;
159 };
160
161 #define REGISTER_ELEMENT(namespaceURI,cname) \
162     q=QName(namespaceURI,cname::LOCAL_NAME); \
163     XMLObjectBuilder::registerBuilder(q,new cname##Builder()); \
164     SchemaValidators.registerValidator(q,new cname##SchemaValidator())
165     
166 #define REGISTER_TYPE(namespaceURI,cname) \
167     q=QName(namespaceURI,cname::TYPE_NAME); \
168     XMLObjectBuilder::registerBuilder(q,new cname##Builder()); \
169     SchemaValidators.registerValidator(q,new cname##SchemaValidator())
170
171 void xmlsignature::registerKeyInfoClasses()
172 {
173     QName q;
174     REGISTER_ELEMENT(XMLSIG_NS,KeyInfo);
175     REGISTER_ELEMENT(XMLSIG_NS,KeyName);
176     REGISTER_ELEMENT(XMLSIG_NS,KeyValue);
177     REGISTER_ELEMENT(XMLSIG_NS,MgmtData);
178     REGISTER_ELEMENT(XMLSIG_NS,DSAKeyValue);
179     REGISTER_ELEMENT(XMLSIG_NS,RSAKeyValue);
180     REGISTER_ELEMENT(XMLSIG_NS,Exponent);
181     REGISTER_ELEMENT(XMLSIG_NS,Modulus);
182     REGISTER_ELEMENT(XMLSIG_NS,P);
183     REGISTER_ELEMENT(XMLSIG_NS,Q);
184     REGISTER_ELEMENT(XMLSIG_NS,G);
185     REGISTER_ELEMENT(XMLSIG_NS,Y);
186     REGISTER_ELEMENT(XMLSIG_NS,J);
187     REGISTER_ELEMENT(XMLSIG_NS,Seed);
188     REGISTER_ELEMENT(XMLSIG_NS,PgenCounter);
189     REGISTER_ELEMENT(XMLSIG_NS,XPath);
190     REGISTER_ELEMENT(XMLSIG_NS,Transform);
191     REGISTER_ELEMENT(XMLSIG_NS,Transforms);
192     REGISTER_ELEMENT(XMLSIG_NS,RetrievalMethod);
193     REGISTER_ELEMENT(XMLSIG_NS,X509IssuerSerial);
194     REGISTER_ELEMENT(XMLSIG_NS,X509IssuerName);
195     REGISTER_ELEMENT(XMLSIG_NS,X509SerialNumber);
196     REGISTER_ELEMENT(XMLSIG_NS,X509SKI);
197     REGISTER_ELEMENT(XMLSIG_NS,X509SubjectName);
198     REGISTER_ELEMENT(XMLSIG_NS,X509Certificate);
199     REGISTER_ELEMENT(XMLSIG_NS,X509CRL);
200     REGISTER_ELEMENT(XMLSIG_NS,X509Data);
201     REGISTER_ELEMENT(XMLSIG_NS,SPKISexp);
202     REGISTER_ELEMENT(XMLSIG_NS,SPKIData);
203     REGISTER_ELEMENT(XMLSIG_NS,PGPKeyID);
204     REGISTER_ELEMENT(XMLSIG_NS,PGPKeyPacket);
205     REGISTER_ELEMENT(XMLSIG_NS,PGPData);
206     REGISTER_TYPE(XMLSIG_NS,KeyInfo);
207     REGISTER_TYPE(XMLSIG_NS,KeyValue);
208     REGISTER_TYPE(XMLSIG_NS,DSAKeyValue);
209     REGISTER_TYPE(XMLSIG_NS,RSAKeyValue);
210     REGISTER_TYPE(XMLSIG_NS,Transform);
211     REGISTER_TYPE(XMLSIG_NS,Transforms);
212     REGISTER_TYPE(XMLSIG_NS,RetrievalMethod);
213     REGISTER_TYPE(XMLSIG_NS,X509IssuerSerial);
214     REGISTER_TYPE(XMLSIG_NS,X509Data);
215     REGISTER_TYPE(XMLSIG_NS,SPKIData);
216     REGISTER_TYPE(XMLSIG_NS,PGPData);
217
218     REGISTER_ELEMENT(XMLSIG11_NS,DEREncodedKeyValue);
219     REGISTER_ELEMENT(XMLSIG11_NS,ECKeyValue);
220     REGISTER_ELEMENT(XMLSIG11_NS,KeyInfoReference);
221     REGISTER_ELEMENT(XMLSIG11_NS,NamedCurve);
222     REGISTER_ELEMENT(XMLSIG11_NS,OCSPResponse);
223     REGISTER_ELEMENT(XMLSIG11_NS,PublicKey);
224     REGISTER_ELEMENT(XMLSIG11_NS,X509Digest);
225     REGISTER_TYPE(XMLSIG11_NS,DEREncodedKeyValue);
226     REGISTER_TYPE(XMLSIG11_NS,ECKeyValue);
227     REGISTER_TYPE(XMLSIG11_NS,KeyInfoReference);
228     REGISTER_TYPE(XMLSIG11_NS,NamedCurve);
229     REGISTER_TYPE(XMLSIG11_NS,X509Digest);
230 }