Merge branch '1.x' of ssh://authdev.it.ohio-state.edu/~scantor/git/cpp-xmltooling...
[shibboleth/cpp-xmltooling.git] / xmltooling / signature / impl / KeyInfoSchemaValidators.cpp
1 /**
2  * Licensed to the University Corporation for Advanced Internet
3  * Development, Inc. (UCAID) under one or more contributor license
4  * agreements. See the NOTICE file distributed with this work for
5  * additional information regarding copyright ownership.
6  *
7  * UCAID licenses this file to you under the Apache License,
8  * Version 2.0 (the "License"); you may not use this file except
9  * in compliance with the License. You may obtain a copy of the
10  * License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing,
15  * software distributed under the License is distributed on an
16  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
17  * either express or implied. See the License for the specific
18  * language governing permissions and limitations under the License.
19  */
20
21 /**
22  * KeyInfoSchemaValidators.cpp
23  * 
24  * Schema validators for KeyInfo schema.
25  */
26
27 #include "internal.h"
28 #include "exceptions.h"
29 #include "signature/KeyInfo.h"
30 #include "validation/Validator.h"
31 #include "validation/ValidatorSuite.h"
32
33 using namespace xmlsignature;
34 using namespace xmltooling;
35 using namespace std;
36 using xmlconstants::XMLSIG_NS;
37 using xmlconstants::XMLSIG11_NS;
38
39 #define XMLOBJECTVALIDATOR_ONLYONEOF4(cname,proper1,proper2,proper3,proper4) \
40     int c##proper1##proper2##proper3##proper4=0; \
41     if (ptr->get##proper1()!=nullptr) \
42         c##proper1##proper2##proper3##proper4++; \
43     if (ptr->get##proper2()!=nullptr) \
44         c##proper1##proper2##proper3##proper4++; \
45     if (ptr->get##proper3()!=nullptr) \
46         c##proper1##proper2##proper3##proper4++; \
47     if (ptr->get##proper4()!=nullptr) \
48         c##proper1##proper2##proper3##proper4++; \
49     if (c##proper1##proper2##proper3##proper4 != 1) \
50         throw xmltooling::ValidationException(#cname" must have only one of "#proper1", "#proper2", "#proper3", or "#proper4".")
51
52 namespace xmlsignature {
53
54     XMLOBJECTVALIDATOR_SIMPLE(XMLTOOL_DLLLOCAL,KeyName);
55     XMLOBJECTVALIDATOR_SIMPLE(XMLTOOL_DLLLOCAL,MgmtData);
56     XMLOBJECTVALIDATOR_SIMPLE(XMLTOOL_DLLLOCAL,Modulus);
57     XMLOBJECTVALIDATOR_SIMPLE(XMLTOOL_DLLLOCAL,Exponent);
58     XMLOBJECTVALIDATOR_SIMPLE(XMLTOOL_DLLLOCAL,Seed);
59     XMLOBJECTVALIDATOR_SIMPLE(XMLTOOL_DLLLOCAL,PgenCounter);
60     XMLOBJECTVALIDATOR_SIMPLE(XMLTOOL_DLLLOCAL,P);
61     XMLOBJECTVALIDATOR_SIMPLE(XMLTOOL_DLLLOCAL,Q);
62     XMLOBJECTVALIDATOR_SIMPLE(XMLTOOL_DLLLOCAL,G);
63     XMLOBJECTVALIDATOR_SIMPLE(XMLTOOL_DLLLOCAL,Y);
64     XMLOBJECTVALIDATOR_SIMPLE(XMLTOOL_DLLLOCAL,J);
65     XMLOBJECTVALIDATOR_SIMPLE(XMLTOOL_DLLLOCAL,XPath);
66     XMLOBJECTVALIDATOR_SIMPLE(XMLTOOL_DLLLOCAL,X509IssuerName);
67     XMLOBJECTVALIDATOR_SIMPLE(XMLTOOL_DLLLOCAL,X509SerialNumber);
68     XMLOBJECTVALIDATOR_SIMPLE(XMLTOOL_DLLLOCAL,X509SKI);
69     XMLOBJECTVALIDATOR_SIMPLE(XMLTOOL_DLLLOCAL,X509SubjectName);
70     XMLOBJECTVALIDATOR_SIMPLE(XMLTOOL_DLLLOCAL,X509Certificate);
71     XMLOBJECTVALIDATOR_SIMPLE(XMLTOOL_DLLLOCAL,X509CRL);
72     XMLOBJECTVALIDATOR_SIMPLE(XMLTOOL_DLLLOCAL,SPKISexp);
73     XMLOBJECTVALIDATOR_SIMPLE(XMLTOOL_DLLLOCAL,PGPKeyID);
74     XMLOBJECTVALIDATOR_SIMPLE(XMLTOOL_DLLLOCAL,PGPKeyPacket);
75
76     XMLOBJECTVALIDATOR_SIMPLE(XMLTOOL_DLLLOCAL,DEREncodedKeyValue);
77     XMLOBJECTVALIDATOR_SIMPLE(XMLTOOL_DLLLOCAL,OCSPResponse);
78     XMLOBJECTVALIDATOR_SIMPLE(XMLTOOL_DLLLOCAL,PublicKey);
79     
80     BEGIN_XMLOBJECTVALIDATOR(XMLTOOL_DLLLOCAL,RSAKeyValue);
81         XMLOBJECTVALIDATOR_REQUIRE(RSAKeyValue,Modulus);
82         XMLOBJECTVALIDATOR_REQUIRE(RSAKeyValue,Exponent);
83     END_XMLOBJECTVALIDATOR;
84
85     BEGIN_XMLOBJECTVALIDATOR(XMLTOOL_DLLLOCAL,DSAKeyValue);
86         XMLOBJECTVALIDATOR_REQUIRE(DSAKeyValue,Y);
87         XMLOBJECTVALIDATOR_NONEORBOTH(DSKeyValue,P,Q);
88         XMLOBJECTVALIDATOR_NONEORBOTH(DSKeyValue,Seed,PgenCounter);
89     END_XMLOBJECTVALIDATOR;
90
91     BEGIN_XMLOBJECTVALIDATOR(XMLTOOL_DLLLOCAL,KeyValue);
92         XMLOBJECTVALIDATOR_ONLYONEOF4(KeyValue,DSAKeyValue,RSAKeyValue,ECKeyValue,UnknownXMLObject);
93     END_XMLOBJECTVALIDATOR;
94
95     BEGIN_XMLOBJECTVALIDATOR(XMLTOOL_DLLLOCAL,Transform);
96         XMLOBJECTVALIDATOR_REQUIRE(Transform,Algorithm);
97     END_XMLOBJECTVALIDATOR;
98
99     BEGIN_XMLOBJECTVALIDATOR(XMLTOOL_DLLLOCAL,Transforms);
100         XMLOBJECTVALIDATOR_NONEMPTY(Transforms,Transform);
101     END_XMLOBJECTVALIDATOR;
102
103     BEGIN_XMLOBJECTVALIDATOR(XMLTOOL_DLLLOCAL,RetrievalMethod);
104         XMLOBJECTVALIDATOR_REQUIRE(RetrievalMethod,URI);
105     END_XMLOBJECTVALIDATOR;
106
107     BEGIN_XMLOBJECTVALIDATOR(XMLTOOL_DLLLOCAL,X509IssuerSerial);
108         XMLOBJECTVALIDATOR_REQUIRE(X509IssuerSerial,X509IssuerName);
109         XMLOBJECTVALIDATOR_REQUIRE(X509IssuerSerial,X509SerialNumber);
110     END_XMLOBJECTVALIDATOR;
111
112     class XMLTOOL_DLLLOCAL checkWildcardNS {
113     public:
114         void operator()(const XMLObject* xmlObject) const {
115             const XMLCh* ns=xmlObject->getElementQName().getNamespaceURI();
116             if (XMLString::equals(ns,XMLSIG_NS) || !ns || !*ns) {
117                 throw ValidationException(
118                     "Object contains an illegal extension child element ($1).",
119                     params(1,xmlObject->getElementQName().toString().c_str())
120                     );
121             }
122         }
123     };
124     
125     BEGIN_XMLOBJECTVALIDATOR(XMLTOOL_DLLLOCAL,X509Data);
126         if (!ptr->hasChildren())
127             throw ValidationException("X509Data must have at least one child element.");
128         const vector<XMLObject*>& anys=ptr->getUnknownXMLObjects();
129         for_each(anys.begin(),anys.end(),checkWildcardNS());
130     END_XMLOBJECTVALIDATOR;
131
132     BEGIN_XMLOBJECTVALIDATOR(XMLTOOL_DLLLOCAL,SPKIData);
133         XMLOBJECTVALIDATOR_NONEMPTY(SPKIData,SPKISexp);
134     END_XMLOBJECTVALIDATOR;
135
136     BEGIN_XMLOBJECTVALIDATOR(XMLTOOL_DLLLOCAL,PGPData);
137         XMLOBJECTVALIDATOR_ONEOF(PGPData,PGPKeyID,PGPKeyPacket);
138     END_XMLOBJECTVALIDATOR;
139
140     BEGIN_XMLOBJECTVALIDATOR(XMLTOOL_DLLLOCAL,KeyInfo);
141         if (!ptr->hasChildren())
142             throw ValidationException("KeyInfo must have at least one child element.");
143         const vector<XMLObject*>& anys=ptr->getUnknownXMLObjects();
144         for_each(anys.begin(),anys.end(),checkWildcardNS());
145     END_XMLOBJECTVALIDATOR;
146
147     BEGIN_XMLOBJECTVALIDATOR(XMLTOOL_DLLLOCAL,KeyInfoReference);
148         XMLOBJECTVALIDATOR_REQUIRE(KeyInfoReference,URI);
149     END_XMLOBJECTVALIDATOR;
150
151     BEGIN_XMLOBJECTVALIDATOR(XMLTOOL_DLLLOCAL,NamedCurve);
152         XMLOBJECTVALIDATOR_REQUIRE(NamedCurve,URI);
153     END_XMLOBJECTVALIDATOR;
154
155     BEGIN_XMLOBJECTVALIDATOR(XMLTOOL_DLLLOCAL,ECKeyValue);
156         XMLOBJECTVALIDATOR_ONEOF(ECKeyValue,ECParameters,NamedCurve);
157         XMLOBJECTVALIDATOR_REQUIRE(ECKeyValue,PublicKey);
158     END_XMLOBJECTVALIDATOR;
159
160     BEGIN_XMLOBJECTVALIDATOR(XMLTOOL_DLLLOCAL,X509Digest);
161         XMLOBJECTVALIDATOR_REQUIRE(X509Digest,Algorithm);
162     END_XMLOBJECTVALIDATOR;
163 };
164
165 #define REGISTER_ELEMENT(namespaceURI,cname) \
166     q=QName(namespaceURI,cname::LOCAL_NAME); \
167     XMLObjectBuilder::registerBuilder(q,new cname##Builder()); \
168     SchemaValidators.registerValidator(q,new cname##SchemaValidator())
169     
170 #define REGISTER_TYPE(namespaceURI,cname) \
171     q=QName(namespaceURI,cname::TYPE_NAME); \
172     XMLObjectBuilder::registerBuilder(q,new cname##Builder()); \
173     SchemaValidators.registerValidator(q,new cname##SchemaValidator())
174
175 void xmlsignature::registerKeyInfoClasses()
176 {
177     QName q;
178     REGISTER_ELEMENT(XMLSIG_NS,KeyInfo);
179     REGISTER_ELEMENT(XMLSIG_NS,KeyName);
180     REGISTER_ELEMENT(XMLSIG_NS,KeyValue);
181     REGISTER_ELEMENT(XMLSIG_NS,MgmtData);
182     REGISTER_ELEMENT(XMLSIG_NS,DSAKeyValue);
183     REGISTER_ELEMENT(XMLSIG_NS,RSAKeyValue);
184     REGISTER_ELEMENT(XMLSIG_NS,Exponent);
185     REGISTER_ELEMENT(XMLSIG_NS,Modulus);
186     REGISTER_ELEMENT(XMLSIG_NS,P);
187     REGISTER_ELEMENT(XMLSIG_NS,Q);
188     REGISTER_ELEMENT(XMLSIG_NS,G);
189     REGISTER_ELEMENT(XMLSIG_NS,Y);
190     REGISTER_ELEMENT(XMLSIG_NS,J);
191     REGISTER_ELEMENT(XMLSIG_NS,Seed);
192     REGISTER_ELEMENT(XMLSIG_NS,PgenCounter);
193     REGISTER_ELEMENT(XMLSIG_NS,XPath);
194     REGISTER_ELEMENT(XMLSIG_NS,Transform);
195     REGISTER_ELEMENT(XMLSIG_NS,Transforms);
196     REGISTER_ELEMENT(XMLSIG_NS,RetrievalMethod);
197     REGISTER_ELEMENT(XMLSIG_NS,X509IssuerSerial);
198     REGISTER_ELEMENT(XMLSIG_NS,X509IssuerName);
199     REGISTER_ELEMENT(XMLSIG_NS,X509SerialNumber);
200     REGISTER_ELEMENT(XMLSIG_NS,X509SKI);
201     REGISTER_ELEMENT(XMLSIG_NS,X509SubjectName);
202     REGISTER_ELEMENT(XMLSIG_NS,X509Certificate);
203     REGISTER_ELEMENT(XMLSIG_NS,X509CRL);
204     REGISTER_ELEMENT(XMLSIG_NS,X509Data);
205     REGISTER_ELEMENT(XMLSIG_NS,SPKISexp);
206     REGISTER_ELEMENT(XMLSIG_NS,SPKIData);
207     REGISTER_ELEMENT(XMLSIG_NS,PGPKeyID);
208     REGISTER_ELEMENT(XMLSIG_NS,PGPKeyPacket);
209     REGISTER_ELEMENT(XMLSIG_NS,PGPData);
210     REGISTER_TYPE(XMLSIG_NS,KeyInfo);
211     REGISTER_TYPE(XMLSIG_NS,KeyValue);
212     REGISTER_TYPE(XMLSIG_NS,DSAKeyValue);
213     REGISTER_TYPE(XMLSIG_NS,RSAKeyValue);
214     REGISTER_TYPE(XMLSIG_NS,Transform);
215     REGISTER_TYPE(XMLSIG_NS,Transforms);
216     REGISTER_TYPE(XMLSIG_NS,RetrievalMethod);
217     REGISTER_TYPE(XMLSIG_NS,X509IssuerSerial);
218     REGISTER_TYPE(XMLSIG_NS,X509Data);
219     REGISTER_TYPE(XMLSIG_NS,SPKIData);
220     REGISTER_TYPE(XMLSIG_NS,PGPData);
221
222     REGISTER_ELEMENT(XMLSIG11_NS,DEREncodedKeyValue);
223     REGISTER_ELEMENT(XMLSIG11_NS,ECKeyValue);
224     REGISTER_ELEMENT(XMLSIG11_NS,KeyInfoReference);
225     REGISTER_ELEMENT(XMLSIG11_NS,NamedCurve);
226     REGISTER_ELEMENT(XMLSIG11_NS,OCSPResponse);
227     REGISTER_ELEMENT(XMLSIG11_NS,PublicKey);
228     REGISTER_ELEMENT(XMLSIG11_NS,X509Digest);
229     REGISTER_TYPE(XMLSIG11_NS,DEREncodedKeyValue);
230     REGISTER_TYPE(XMLSIG11_NS,ECKeyValue);
231     REGISTER_TYPE(XMLSIG11_NS,KeyInfoReference);
232     REGISTER_TYPE(XMLSIG11_NS,NamedCurve);
233     REGISTER_TYPE(XMLSIG11_NS,X509Digest);
234 }