xmlsig 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.rdoc +0 -0
- data/ext/xmlsig/BioWrap.h +98 -0
- data/ext/xmlsig/DSig.cpp +109 -0
- data/ext/xmlsig/DSig.h +81 -0
- data/ext/xmlsig/DSigCtx.h +72 -0
- data/ext/xmlsig/Exceptions.cpp +151 -0
- data/ext/xmlsig/Exceptions.h +214 -0
- data/ext/xmlsig/Key.cpp +582 -0
- data/ext/xmlsig/Key.h +338 -0
- data/ext/xmlsig/KeyInfoCtx.h +67 -0
- data/ext/xmlsig/KeyStore.cpp +180 -0
- data/ext/xmlsig/KeyStore.h +157 -0
- data/ext/xmlsig/KeysMngrWrap.h +62 -0
- data/ext/xmlsig/NodeSet.h +60 -0
- data/ext/xmlsig/Signer.cpp +691 -0
- data/ext/xmlsig/Signer.h +373 -0
- data/ext/xmlsig/TrustVerifier.cpp +145 -0
- data/ext/xmlsig/TrustVerifier.h +174 -0
- data/ext/xmlsig/Verifier.cpp +677 -0
- data/ext/xmlsig/Verifier.h +313 -0
- data/ext/xmlsig/X509Certificate.cpp +362 -0
- data/ext/xmlsig/X509Certificate.h +146 -0
- data/ext/xmlsig/XPath.cpp +173 -0
- data/ext/xmlsig/XPath.h +156 -0
- data/ext/xmlsig/XPathCtx.h +68 -0
- data/ext/xmlsig/XmlCharBuf.h +60 -0
- data/ext/xmlsig/XmlDoc.cpp +278 -0
- data/ext/xmlsig/XmlDoc.h +157 -0
- data/ext/xmlsig/XmlElement.cpp +151 -0
- data/ext/xmlsig/XmlElement.h +134 -0
- data/ext/xmlsig/countptr.h +260 -0
- data/ext/xmlsig/extconf.rb +58 -0
- data/ext/xmlsig/runtests.rb +23 -0
- data/ext/xmlsig/swig/countptr.i +27 -0
- data/ext/xmlsig/swig/exceptions.i +79 -0
- data/ext/xmlsig/swig/ruby.i +17 -0
- data/ext/xmlsig/swig/xmlsig.i +405 -0
- data/ext/xmlsig/t/tc_cert.rb +34 -0
- data/ext/xmlsig/t/tc_interface.rb +158 -0
- data/ext/xmlsig/t/tc_signer.rb +501 -0
- data/ext/xmlsig/t/tc_tsik.rb +490 -0
- data/ext/xmlsig/t/tc_verifier.rb +151 -0
- data/ext/xmlsig/t/tsik_interop/sign.rb +48 -0
- data/ext/xmlsig/t/tsik_interop/verify.rb +31 -0
- data/ext/xmlsig/t/tsik_interop/verify_own.rb +46 -0
- data/ext/xmlsig/xmlsig.cpp +13363 -0
- data/lib/xmlsig.rb +1 -0
- metadata +113 -0
@@ -0,0 +1,677 @@
|
|
1
|
+
/*
|
2
|
+
* (C) Copyright 2006 VeriSign, Inc.
|
3
|
+
* Developed by Sxip Identity
|
4
|
+
*
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
* you may not use this file except in compliance with the License.
|
7
|
+
* You may obtain a copy of the License at
|
8
|
+
*
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
*
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
* See the License for the specific language governing permissions and
|
15
|
+
* limitations under the License.
|
16
|
+
*/
|
17
|
+
#include <iostream>
|
18
|
+
|
19
|
+
#include <libxml/tree.h>
|
20
|
+
#include <libxml/xmlmemory.h>
|
21
|
+
#include <libxml/parser.h>
|
22
|
+
#ifndef XMLSEC_NO_XSLT
|
23
|
+
#include <libxslt/xslt.h>
|
24
|
+
#endif /* XMLSEC_NO_XSLT */
|
25
|
+
#include <xmlsec/xmlsec.h>
|
26
|
+
#include <xmlsec/xmltree.h>
|
27
|
+
#include <xmlsec/xmldsig.h>
|
28
|
+
#include <xmlsec/templates.h>
|
29
|
+
#include <xmlsec/openssl/x509.h>
|
30
|
+
#include <xmlsec/base64.h>
|
31
|
+
#include <assert.h>
|
32
|
+
|
33
|
+
#include "Verifier.h"
|
34
|
+
#include "Key.h"
|
35
|
+
#include "XmlDoc.h"
|
36
|
+
#include "DSigCtx.h"
|
37
|
+
#include "KeyStore.h"
|
38
|
+
#include "XPath.h"
|
39
|
+
#include "KeyInfoCtx.h"
|
40
|
+
#include "BioWrap.h"
|
41
|
+
#include "XmlCharBuf.h"
|
42
|
+
#include "NodeSet.h"
|
43
|
+
using namespace std;
|
44
|
+
|
45
|
+
|
46
|
+
Verifier::Verifier (XmlDocClassPtr doc)
|
47
|
+
: mXmlDoc (doc),
|
48
|
+
xPath (0),
|
49
|
+
skipCertCheckFlag (0)
|
50
|
+
{
|
51
|
+
verifierInit();
|
52
|
+
}
|
53
|
+
|
54
|
+
|
55
|
+
Verifier::Verifier (XmlDocClassPtr doc, XPathPtr newXPath)
|
56
|
+
: mXmlDoc (doc),
|
57
|
+
xPath (newXPath),
|
58
|
+
skipCertCheckFlag (0)
|
59
|
+
{
|
60
|
+
verifierInit();
|
61
|
+
|
62
|
+
// Check that xPath points to a single Signature element
|
63
|
+
xmlXPathObjectPtr isRefXP = xPath ? xPath->evalExpression(mXmlDoc) : NULL;
|
64
|
+
if (isRefXP && isRefXP->nodesetval->nodeNr != 1)
|
65
|
+
{
|
66
|
+
THROW_NORET(XPathError, "XPath expression must refer to a single node");
|
67
|
+
}
|
68
|
+
}
|
69
|
+
|
70
|
+
|
71
|
+
void Verifier::verifierInit ()
|
72
|
+
{
|
73
|
+
mKeyStore = NULL;
|
74
|
+
mDefaultKeyStore = new KeyStore();
|
75
|
+
if (!mDefaultKeyStore)
|
76
|
+
{
|
77
|
+
THROW_NORET(MemoryError, "Could not create default KeyStore");
|
78
|
+
}
|
79
|
+
}
|
80
|
+
|
81
|
+
|
82
|
+
Verifier::~Verifier ()
|
83
|
+
{
|
84
|
+
assert(mDefaultKeyStore);
|
85
|
+
mDefaultKeyStore = 0;
|
86
|
+
}
|
87
|
+
|
88
|
+
|
89
|
+
int Verifier::setKeyStore (KeyStorePtr keyStore)
|
90
|
+
{
|
91
|
+
assert(keyStore);
|
92
|
+
if (keyStore->getKeyStore() == NULL)
|
93
|
+
{
|
94
|
+
THROW(ValueError, "Invalid keystore parameter", -1);
|
95
|
+
}
|
96
|
+
mKeyStore = keyStore;
|
97
|
+
return 0;
|
98
|
+
}
|
99
|
+
|
100
|
+
|
101
|
+
int Verifier::verify ()
|
102
|
+
{
|
103
|
+
return doVerify(NULL);
|
104
|
+
}
|
105
|
+
|
106
|
+
|
107
|
+
int Verifier::verify (KeyPtr verifyingKey)
|
108
|
+
{
|
109
|
+
return doVerify(verifyingKey);
|
110
|
+
}
|
111
|
+
|
112
|
+
|
113
|
+
int Verifier::doVerify (KeyPtr verifyingKey)
|
114
|
+
{
|
115
|
+
KeyPtr key = verifyingKey;
|
116
|
+
if (!key)
|
117
|
+
{
|
118
|
+
key = getVerifyingKey();
|
119
|
+
}
|
120
|
+
if (!key && !mKeyStore)
|
121
|
+
{
|
122
|
+
THROW(KeyError, "No verifying key available", -1);
|
123
|
+
}
|
124
|
+
if (!mXmlDoc || !(*mXmlDoc))
|
125
|
+
{
|
126
|
+
THROW(DocError, "XML document was not loaded", -1);
|
127
|
+
}
|
128
|
+
|
129
|
+
xmlNodePtr node = NULL;
|
130
|
+
if ((findStartNode(*mXmlDoc, &node) < 0) || (node == NULL))
|
131
|
+
{
|
132
|
+
THROW(XMLError, "Can't find start node in document", -1);
|
133
|
+
}
|
134
|
+
|
135
|
+
int ret = verifyNode(*mXmlDoc, node, key);
|
136
|
+
return ret;
|
137
|
+
}
|
138
|
+
|
139
|
+
|
140
|
+
int Verifier::findStartNode (xmlDocPtr doc, xmlNodePtr* node)
|
141
|
+
{
|
142
|
+
int res = -1;
|
143
|
+
if (xPath)
|
144
|
+
{
|
145
|
+
if (findSignatureXPath(doc, node) < 0)
|
146
|
+
{
|
147
|
+
return res;
|
148
|
+
}
|
149
|
+
}
|
150
|
+
else
|
151
|
+
{
|
152
|
+
*node = xmlSecFindNode(xmlDocGetRootElement(doc), xmlSecNodeSignature,
|
153
|
+
xmlSecDSigNs);
|
154
|
+
}
|
155
|
+
return 0;
|
156
|
+
}
|
157
|
+
|
158
|
+
|
159
|
+
int Verifier::findSignatureXPath (xmlDocPtr doc, xmlNodePtr* node)
|
160
|
+
{
|
161
|
+
assert(xPath);
|
162
|
+
xmlXPathObjectPtr xpObj = xPath->evalExpression(mXmlDoc);
|
163
|
+
if (xpObj == NULL)
|
164
|
+
{
|
165
|
+
THROW(XPathError, "Unable to evaluate XPath expression", -1);
|
166
|
+
}
|
167
|
+
//fprintf(stderr, "'%s' found %d nodes\n", xPath->getXPath().c_str(),
|
168
|
+
// xpObj->nodesetval->nodeNr);
|
169
|
+
if (xpObj->nodesetval->nodeNr <= 0)
|
170
|
+
{
|
171
|
+
THROW(XPathError, "Can't find signature node at XPath expression", -1);
|
172
|
+
}
|
173
|
+
// Return only the first node in the xpath node set
|
174
|
+
*node = xpObj->nodesetval->nodeTab[0];
|
175
|
+
return 0;
|
176
|
+
}
|
177
|
+
|
178
|
+
|
179
|
+
xmlSecKeysMngrPtr Verifier::getKeysMngr ()
|
180
|
+
{
|
181
|
+
KeyStorePtr keyStore = mDefaultKeyStore;
|
182
|
+
if (mKeyStore)
|
183
|
+
{
|
184
|
+
keyStore = mKeyStore;
|
185
|
+
}
|
186
|
+
assert(keyStore);
|
187
|
+
return keyStore->getKeyStore();
|
188
|
+
}
|
189
|
+
|
190
|
+
|
191
|
+
int Verifier::verifyNode (xmlDocPtr doc, xmlNodePtr node, KeyPtr key)
|
192
|
+
{
|
193
|
+
assert(doc);
|
194
|
+
assert(node);
|
195
|
+
|
196
|
+
// create signature context
|
197
|
+
DSigCtx dsigCtx (getKeysMngr());
|
198
|
+
if (!dsigCtx)
|
199
|
+
{
|
200
|
+
return -1;
|
201
|
+
}
|
202
|
+
if (key)
|
203
|
+
{
|
204
|
+
dsigCtx->signKey = key->dupKey();
|
205
|
+
}
|
206
|
+
|
207
|
+
// Set cert chain not to verify on key info read if requested
|
208
|
+
if (skipCertCheckFlag)
|
209
|
+
{
|
210
|
+
dsigCtx->keyInfoReadCtx.flags |=
|
211
|
+
XMLSEC_KEYINFO_FLAGS_X509DATA_DONT_VERIFY_CERTS;
|
212
|
+
}
|
213
|
+
|
214
|
+
// Verify signature
|
215
|
+
if (xmlSecDSigCtxVerify(dsigCtx, node) < 0)
|
216
|
+
{
|
217
|
+
THROW(LibError, "Signature verify fn failure", -1);
|
218
|
+
}
|
219
|
+
|
220
|
+
// return verification result
|
221
|
+
return (dsigCtx->status == xmlSecDSigStatusSucceeded);
|
222
|
+
}
|
223
|
+
|
224
|
+
|
225
|
+
KeyPtr Verifier::getVerifyingKey ()
|
226
|
+
{
|
227
|
+
if (!mXmlDoc || !(*mXmlDoc))
|
228
|
+
{
|
229
|
+
THROW(DocError, "XML document was not loaded", 0);
|
230
|
+
}
|
231
|
+
|
232
|
+
xmlNodePtr sigNode = NULL;
|
233
|
+
if (findStartNode(*mXmlDoc, &sigNode) < 0)
|
234
|
+
{
|
235
|
+
THROW(XMLError, "Can't find start node in document", 0);
|
236
|
+
}
|
237
|
+
// find keyinfo node
|
238
|
+
xmlNodePtr node = xmlSecFindNode(sigNode, xmlSecNodeKeyInfo, xmlSecDSigNs);
|
239
|
+
if (node == NULL)
|
240
|
+
{
|
241
|
+
// not an error, keyinfo may not exist
|
242
|
+
return 0;
|
243
|
+
}
|
244
|
+
|
245
|
+
KeyPtr keyObj = new Key();
|
246
|
+
int ret = -1;
|
247
|
+
try
|
248
|
+
{
|
249
|
+
ret = keyObj->loadFromKeyInfo(node, getKeysMngr());
|
250
|
+
if (ret >= 0)
|
251
|
+
{
|
252
|
+
X509CertificatePtr x509cert = getCertificate();
|
253
|
+
if (x509cert)
|
254
|
+
{
|
255
|
+
// Return null if key is not equal to certificate's key
|
256
|
+
// since both exists
|
257
|
+
KeyPtr certKeyObj = x509cert->getKey();
|
258
|
+
if (*certKeyObj != *keyObj)
|
259
|
+
return 0;
|
260
|
+
}
|
261
|
+
}
|
262
|
+
}
|
263
|
+
catch (LibError&)
|
264
|
+
{}
|
265
|
+
if (ret < 0)
|
266
|
+
{
|
267
|
+
X509CertificatePtr x509cert = getCertificate();
|
268
|
+
if (x509cert)
|
269
|
+
{
|
270
|
+
keyObj = x509cert->getKey();
|
271
|
+
}
|
272
|
+
}
|
273
|
+
return keyObj;
|
274
|
+
}
|
275
|
+
|
276
|
+
|
277
|
+
X509CertificatePtr Verifier::getCertificate ()
|
278
|
+
{
|
279
|
+
vector<X509CertificatePtr> certChain = getCertificateChain();
|
280
|
+
if (certChain.size())
|
281
|
+
{
|
282
|
+
return certChain[0];
|
283
|
+
}
|
284
|
+
return 0;
|
285
|
+
}
|
286
|
+
|
287
|
+
|
288
|
+
// TODO sort chain into subject-issuer order?
|
289
|
+
vector<X509CertificatePtr> Verifier::getCertificateChain ()
|
290
|
+
{
|
291
|
+
vector<X509CertificatePtr> certChain;
|
292
|
+
if (!mXmlDoc || !(*mXmlDoc))
|
293
|
+
{
|
294
|
+
THROW(DocError, "XML document was not loaded", certChain);
|
295
|
+
}
|
296
|
+
|
297
|
+
xmlNodePtr sigNode = NULL;
|
298
|
+
if (findStartNode(*mXmlDoc, &sigNode) < 0)
|
299
|
+
{
|
300
|
+
THROW(XMLError, "Can't find start node in document", certChain);
|
301
|
+
}
|
302
|
+
// find keyinfo node
|
303
|
+
xmlNodePtr node = xmlSecFindNode(sigNode, xmlSecNodeKeyInfo, xmlSecDSigNs);
|
304
|
+
if (node == NULL)
|
305
|
+
{
|
306
|
+
// not an error, keyinfo may not exist
|
307
|
+
return certChain;
|
308
|
+
}
|
309
|
+
if (!xmlSecCheckNodeName(node, xmlSecNodeKeyInfo, xmlSecDSigNs))
|
310
|
+
{
|
311
|
+
THROW(XMLError, "Invalid key info node", certChain);
|
312
|
+
}
|
313
|
+
KeyInfoCtx keyInfoCtx;
|
314
|
+
if (!keyInfoCtx)
|
315
|
+
{
|
316
|
+
return certChain;
|
317
|
+
}
|
318
|
+
keyInfoCtx->mode = xmlSecKeyInfoModeRead;
|
319
|
+
keyInfoCtx->flags = XMLSEC_KEYINFO_FLAGS_DONT_STOP_ON_KEY_FOUND |
|
320
|
+
XMLSEC_KEYINFO_FLAGS_X509DATA_DONT_VERIFY_CERTS;
|
321
|
+
keyInfoCtx->keysMngr = getKeysMngr();
|
322
|
+
Key keyObj;
|
323
|
+
keyObj.create();
|
324
|
+
if (xmlSecKeyInfoNodeRead(node, keyObj, keyInfoCtx) < 0)
|
325
|
+
{
|
326
|
+
THROW(LibError, "Couldn't read key info node", certChain);
|
327
|
+
}
|
328
|
+
if (!keyObj)
|
329
|
+
{
|
330
|
+
try
|
331
|
+
{
|
332
|
+
certChain = getX509Data(node);
|
333
|
+
}
|
334
|
+
catch (XMLError&)
|
335
|
+
{}
|
336
|
+
}
|
337
|
+
else
|
338
|
+
{
|
339
|
+
certChain = keyObj.getCertificateChain();
|
340
|
+
}
|
341
|
+
return certChain;
|
342
|
+
}
|
343
|
+
|
344
|
+
|
345
|
+
vector<X509CertificatePtr> Verifier::getX509Data (xmlNodePtr node)
|
346
|
+
{
|
347
|
+
vector<X509CertificatePtr> certChain;
|
348
|
+
|
349
|
+
node = xmlSecFindNode(node, xmlSecNodeX509Data, xmlSecDSigNs);
|
350
|
+
if (node == NULL)
|
351
|
+
{
|
352
|
+
THROW(XMLError, "Can't find X509Data node", certChain);
|
353
|
+
}
|
354
|
+
for (xmlNodePtr cur = xmlSecGetNextElementNode(node->children);
|
355
|
+
cur != NULL;
|
356
|
+
cur = xmlSecGetNextElementNode(cur->next))
|
357
|
+
{
|
358
|
+
if (xmlSecCheckNodeName(cur, xmlSecNodeX509Certificate, xmlSecDSigNs))
|
359
|
+
{
|
360
|
+
X509CertificatePtr x509 = getX509CertificateNode(cur);
|
361
|
+
if (x509)
|
362
|
+
{
|
363
|
+
certChain.push_back(x509);
|
364
|
+
}
|
365
|
+
}
|
366
|
+
}
|
367
|
+
return certChain;
|
368
|
+
}
|
369
|
+
|
370
|
+
|
371
|
+
X509CertificatePtr Verifier::getX509CertificateNode (xmlNodePtr node)
|
372
|
+
{
|
373
|
+
if ((node == NULL) ||
|
374
|
+
(!xmlSecCheckNodeName(node, xmlSecNodeX509Certificate, xmlSecDSigNs)))
|
375
|
+
{
|
376
|
+
return 0;
|
377
|
+
}
|
378
|
+
XmlCharBuf buf (xmlNodeGetContent(node));
|
379
|
+
if (!(int)buf || xmlSecIsEmptyString(buf))
|
380
|
+
{
|
381
|
+
THROW(XMLError, "X509Certificate has no content", 0);
|
382
|
+
}
|
383
|
+
int size = xmlSecBase64Decode(buf, (xmlSecByte*)buf, xmlStrlen(buf));
|
384
|
+
if (size < 0)
|
385
|
+
{
|
386
|
+
THROW(XMLError, "Failed to decode X509Certificate content", 0);
|
387
|
+
}
|
388
|
+
BioWrap mem;
|
389
|
+
if (!(int)mem || (mem.write(buf, size) <= 0))
|
390
|
+
{
|
391
|
+
return 0;
|
392
|
+
}
|
393
|
+
X509* cert = d2i_X509_bio(mem, NULL);
|
394
|
+
if (cert == NULL)
|
395
|
+
{
|
396
|
+
THROW(LibError, "Couldn't load certificate from BIO", 0);
|
397
|
+
}
|
398
|
+
return new X509Certificate(cert);
|
399
|
+
}
|
400
|
+
|
401
|
+
|
402
|
+
int Verifier::isContained (xmlSecNodeSetPtr nodeSet, XPathPtr xPathElem)
|
403
|
+
{
|
404
|
+
assert(xPathElem);
|
405
|
+
xmlXPathObjectPtr isRefXP = xPathElem->evalExpression(mXmlDoc);
|
406
|
+
if (isRefXP == 0)
|
407
|
+
{
|
408
|
+
return -1;
|
409
|
+
}
|
410
|
+
if (isRefXP->nodesetval->nodeNr != 1)
|
411
|
+
{
|
412
|
+
THROW(XPathError, "XPath expression must refer to a single node", -1);
|
413
|
+
}
|
414
|
+
xmlNodePtr node = *(isRefXP->nodesetval->nodeTab);
|
415
|
+
assert(node);
|
416
|
+
|
417
|
+
return xmlSecNodeSetContains(nodeSet, node, node->parent);
|
418
|
+
}
|
419
|
+
|
420
|
+
|
421
|
+
int Verifier::refNodes (Verifier::refNodesCallback callbackFn, void* data)
|
422
|
+
{
|
423
|
+
assert(mXmlDoc);
|
424
|
+
if (!mXmlDoc || !(*mXmlDoc))
|
425
|
+
{
|
426
|
+
THROW(DocError, "XML document was not loaded", -1);
|
427
|
+
}
|
428
|
+
|
429
|
+
// create signature context
|
430
|
+
DSigCtx dsigCtx (getKeysMngr());
|
431
|
+
if (!dsigCtx)
|
432
|
+
{
|
433
|
+
return -1;
|
434
|
+
}
|
435
|
+
xmlNodePtr node = 0;
|
436
|
+
if (findStartNode(*mXmlDoc, &node) < 0)
|
437
|
+
{
|
438
|
+
THROW(XMLError, "Can't find start node in document", -1);
|
439
|
+
}
|
440
|
+
dsigCtx->operation = xmlSecTransformOperationVerify;
|
441
|
+
dsigCtx->status = xmlSecDSigStatusUnknown;
|
442
|
+
dsigCtx->id = xmlGetProp(node, xmlSecAttrId);
|
443
|
+
//xmlSecAddIDs(node->doc, node, xmlSecDSigIds);
|
444
|
+
|
445
|
+
node = xmlSecGetNextElementNode(node->children);
|
446
|
+
if ((node == NULL) ||
|
447
|
+
(!xmlSecCheckNodeName(node, xmlSecNodeSignedInfo, xmlSecDSigNs)))
|
448
|
+
{
|
449
|
+
THROW(XMLError, "Expected signed info node", -1);
|
450
|
+
}
|
451
|
+
|
452
|
+
// Get c14 method and add it to new transform ctx
|
453
|
+
xmlNodePtr cur = xmlSecGetNextElementNode(node->children);
|
454
|
+
if ((cur != NULL) &&
|
455
|
+
(xmlSecCheckNodeName(cur, xmlSecNodeCanonicalizationMethod, xmlSecDSigNs)))
|
456
|
+
{
|
457
|
+
dsigCtx->c14nMethod =
|
458
|
+
xmlSecTransformCtxNodeRead(&(dsigCtx->transformCtx),
|
459
|
+
cur,
|
460
|
+
xmlSecTransformUsageC14NMethod);
|
461
|
+
if (dsigCtx->c14nMethod == NULL)
|
462
|
+
{
|
463
|
+
THROW(LibError, "Unable to create transform context with c14n method from node", -1);
|
464
|
+
}
|
465
|
+
}
|
466
|
+
else if (dsigCtx->defC14NMethodId != xmlSecTransformIdUnknown)
|
467
|
+
{
|
468
|
+
dsigCtx->c14nMethod =
|
469
|
+
xmlSecTransformCtxCreateAndAppend(&(dsigCtx->transformCtx),
|
470
|
+
dsigCtx->defC14NMethodId);
|
471
|
+
if (dsigCtx->c14nMethod == NULL)
|
472
|
+
{
|
473
|
+
THROW(LibError, "Unable to create transform ctx with c14n method", -1);
|
474
|
+
}
|
475
|
+
}
|
476
|
+
else
|
477
|
+
{
|
478
|
+
THROW(XMLError, "Expected c14n method", -1);
|
479
|
+
}
|
480
|
+
|
481
|
+
// Set up signature method
|
482
|
+
cur = xmlSecGetNextElementNode(cur->next);
|
483
|
+
if ((cur != NULL) &&
|
484
|
+
(xmlSecCheckNodeName(cur, xmlSecNodeSignatureMethod, xmlSecDSigNs)))
|
485
|
+
{
|
486
|
+
dsigCtx->signMethod =
|
487
|
+
xmlSecTransformCtxNodeRead(&(dsigCtx->transformCtx),
|
488
|
+
cur, xmlSecTransformUsageSignatureMethod);
|
489
|
+
if (dsigCtx->signMethod == NULL)
|
490
|
+
{
|
491
|
+
THROW(LibError, "Unable to read signature method from node", -1);
|
492
|
+
}
|
493
|
+
}
|
494
|
+
else if (dsigCtx->defSignMethodId != xmlSecTransformIdUnknown)
|
495
|
+
{
|
496
|
+
dsigCtx->signMethod =
|
497
|
+
xmlSecTransformCtxCreateAndAppend(&(dsigCtx->transformCtx),
|
498
|
+
dsigCtx->defSignMethodId);
|
499
|
+
if (dsigCtx->signMethod == NULL)
|
500
|
+
{
|
501
|
+
THROW(LibError, "Unable to create signature method", -1);
|
502
|
+
}
|
503
|
+
}
|
504
|
+
else
|
505
|
+
{
|
506
|
+
THROW(XMLError, "Expected signature method", -1);
|
507
|
+
}
|
508
|
+
|
509
|
+
cur = xmlSecGetNextElementNode(cur->next);
|
510
|
+
while ((cur != NULL) &&
|
511
|
+
(xmlSecCheckNodeName(cur, xmlSecNodeReference, xmlSecDSigNs)))
|
512
|
+
{
|
513
|
+
// Don't have to call xmlSecDSigReferenceCtxDestroy because
|
514
|
+
// dsigCtx will own dsigRefCtx
|
515
|
+
xmlSecDSigReferenceCtxPtr dsigRefCtx =
|
516
|
+
xmlSecDSigReferenceCtxCreate(dsigCtx,
|
517
|
+
xmlSecDSigReferenceOriginSignedInfo);
|
518
|
+
if (dsigRefCtx == NULL)
|
519
|
+
{
|
520
|
+
THROW(LibError, "Couldn't create DSIG reference context", -1);
|
521
|
+
}
|
522
|
+
if (xmlSecPtrListAdd(&(dsigCtx->signedInfoReferences), dsigRefCtx) < 0)
|
523
|
+
{
|
524
|
+
THROW(LibError, "Couldn't add reference ctx to dsigCtx", -1);
|
525
|
+
}
|
526
|
+
if (xmlSecDSigReferenceCtxProcessNode(dsigRefCtx, cur) < 0)
|
527
|
+
{
|
528
|
+
THROW(LibError, "Failed to process reference node", -1);
|
529
|
+
}
|
530
|
+
if (dsigRefCtx->status != xmlSecDSigStatusSucceeded)
|
531
|
+
{
|
532
|
+
THROW(LibError, "Process reference node status failure", -1);
|
533
|
+
}
|
534
|
+
// xmlSecDSigReferenceCtxDebugDump(dsigRefCtx, stderr);
|
535
|
+
NodeSet nodes (nodeSetFromTransformCtx(&(dsigRefCtx->transformCtx), *mXmlDoc));
|
536
|
+
if (!nodes)
|
537
|
+
{
|
538
|
+
return 0;
|
539
|
+
}
|
540
|
+
dsigRefCtx->transformCtx.result = NULL;
|
541
|
+
dsigRefCtx->transformCtx.status = xmlSecTransformStatusNone;
|
542
|
+
|
543
|
+
xmlSecTransformPtr transformPtr = dsigRefCtx->transformCtx.first;
|
544
|
+
while (transformPtr != NULL)
|
545
|
+
{
|
546
|
+
transformPtr->inNodes = NULL;
|
547
|
+
transformPtr->outNodes = NULL;
|
548
|
+
transformPtr = transformPtr->next;
|
549
|
+
}
|
550
|
+
|
551
|
+
if (xmlSecTransformCtxXmlExecute(&(dsigRefCtx->transformCtx), nodes) < 0)
|
552
|
+
{
|
553
|
+
THROW(LibError, "Transform execute failure", -1);
|
554
|
+
}
|
555
|
+
|
556
|
+
transformPtr = dsigRefCtx->transformCtx.first;
|
557
|
+
while (transformPtr != NULL)
|
558
|
+
{
|
559
|
+
if (transformPtr->next &&
|
560
|
+
(transformPtr->next->id->usage | xmlSecTransformUsageC14NMethod))
|
561
|
+
{
|
562
|
+
break;
|
563
|
+
}
|
564
|
+
transformPtr = transformPtr->next;
|
565
|
+
}
|
566
|
+
if (!transformPtr || !transformPtr->outNodes)
|
567
|
+
{
|
568
|
+
THROW(XMLError, "Couldn't find transform node", -1);
|
569
|
+
}
|
570
|
+
{
|
571
|
+
int ret = (*callbackFn)(transformPtr->outNodes, this, data);
|
572
|
+
if (ret != 0)
|
573
|
+
{
|
574
|
+
return ret;
|
575
|
+
}
|
576
|
+
}
|
577
|
+
cur = xmlSecGetNextElementNode(cur->next);
|
578
|
+
}
|
579
|
+
return 0;
|
580
|
+
}
|
581
|
+
|
582
|
+
|
583
|
+
int Verifier::isReferencedCallback (xmlSecNodeSetPtr nset, Verifier* verifier, void* data)
|
584
|
+
{
|
585
|
+
assert(verifier);
|
586
|
+
assert(data);
|
587
|
+
if (nset == NULL)
|
588
|
+
{
|
589
|
+
return 0;
|
590
|
+
}
|
591
|
+
XPathPtr xPathElem (*(XPathPtr*)data);
|
592
|
+
return verifier->isContained(nset, xPathElem);
|
593
|
+
}
|
594
|
+
|
595
|
+
|
596
|
+
int Verifier::isReferenced (XPathPtr xPathElem)
|
597
|
+
{
|
598
|
+
assert(xPathElem);
|
599
|
+
return refNodes(Verifier::isReferencedCallback, &xPathElem);
|
600
|
+
}
|
601
|
+
|
602
|
+
|
603
|
+
int Verifier::getElementsCallback (xmlSecNodeSetPtr, xmlNodePtr cur, xmlNodePtr, void *data)
|
604
|
+
{
|
605
|
+
try
|
606
|
+
{
|
607
|
+
XmlElementPtr element (new XmlElement(cur));
|
608
|
+
if (element)
|
609
|
+
{
|
610
|
+
if (*element)
|
611
|
+
{
|
612
|
+
vector<XmlElementPtr>& elementVec (*(vector<XmlElementPtr>*)data);
|
613
|
+
elementVec.push_back(element);
|
614
|
+
}
|
615
|
+
}
|
616
|
+
}
|
617
|
+
// ignore exception thrown if cur node is not of element type
|
618
|
+
catch (XMLError)
|
619
|
+
{}
|
620
|
+
return 0;
|
621
|
+
}
|
622
|
+
|
623
|
+
|
624
|
+
int Verifier::getReferencedElementsCallback (xmlSecNodeSetPtr nset, Verifier* verifier, void* data)
|
625
|
+
{
|
626
|
+
assert(verifier);
|
627
|
+
assert(data);
|
628
|
+
if (nset == NULL)
|
629
|
+
{
|
630
|
+
return 0;
|
631
|
+
}
|
632
|
+
if (xmlSecNodeSetWalk(nset, Verifier::getElementsCallback, data) < 0)
|
633
|
+
{
|
634
|
+
THROW(LibError, "Node set walk failure", -1);
|
635
|
+
}
|
636
|
+
return 0;
|
637
|
+
}
|
638
|
+
|
639
|
+
|
640
|
+
vector<XmlElementPtr> Verifier::getReferencedElements ()
|
641
|
+
{
|
642
|
+
vector<XmlElementPtr> elementVec;
|
643
|
+
if (refNodes(Verifier::getReferencedElementsCallback, &elementVec) < 0)
|
644
|
+
{
|
645
|
+
vector<XmlElementPtr> nullVec;
|
646
|
+
return nullVec;
|
647
|
+
}
|
648
|
+
return elementVec;
|
649
|
+
}
|
650
|
+
|
651
|
+
|
652
|
+
xmlSecNodeSetPtr Verifier::nodeSetFromTransformCtx (xmlSecTransformCtxPtr ctx, xmlDocPtr doc)
|
653
|
+
{
|
654
|
+
xmlSecNodeSetPtr nodes;
|
655
|
+
|
656
|
+
if ((ctx->uri != NULL) &&
|
657
|
+
(xmlStrlen(ctx->uri) > 0))
|
658
|
+
{
|
659
|
+
return NULL;
|
660
|
+
}
|
661
|
+
|
662
|
+
if ((ctx->xptrExpr != NULL) && (xmlStrlen(ctx->xptrExpr) > 0))
|
663
|
+
{
|
664
|
+
// our xpointer transform takes care of providing correct nodes set
|
665
|
+
nodes = xmlSecNodeSetCreate(doc, NULL, xmlSecNodeSetNormal);
|
666
|
+
}
|
667
|
+
else
|
668
|
+
{
|
669
|
+
// we do not want to have comments for empty URI
|
670
|
+
nodes = xmlSecNodeSetGetChildren(doc, NULL, 0, 0);
|
671
|
+
}
|
672
|
+
if (nodes == NULL)
|
673
|
+
{
|
674
|
+
THROW(LibError, "Unable to create nodeset", 0);
|
675
|
+
}
|
676
|
+
return nodes;
|
677
|
+
}
|