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,691 @@
|
|
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
|
+
#include <libxml/uri.h>
|
23
|
+
#include <libxml/debugXML.h>
|
24
|
+
#ifndef XMLSEC_NO_XSLT
|
25
|
+
#include <libxslt/xslt.h>
|
26
|
+
#endif /* XMLSEC_NO_XSLT */
|
27
|
+
#include <xmlsec/xmlsec.h>
|
28
|
+
#include <xmlsec/xmltree.h>
|
29
|
+
#include <xmlsec/xmldsig.h>
|
30
|
+
#include <xmlsec/templates.h>
|
31
|
+
#include <xmlsec/openssl/app.h>
|
32
|
+
#include <xmlsec/openssl/crypto.h>
|
33
|
+
#if defined(WIN32) && defined(PHP_EXPORTS)
|
34
|
+
#define IN_XMLSEC
|
35
|
+
#endif
|
36
|
+
#include <xmlsec/openssl/symbols.h>
|
37
|
+
#include <assert.h>
|
38
|
+
|
39
|
+
#include "Signer.h"
|
40
|
+
#include "Key.h"
|
41
|
+
#include "XmlDoc.h"
|
42
|
+
#include "XPath.h"
|
43
|
+
#include "DSigCtx.h"
|
44
|
+
#include "KeysMngrWrap.h"
|
45
|
+
#include "XmlCharBuf.h"
|
46
|
+
using namespace std;
|
47
|
+
|
48
|
+
|
49
|
+
Signer::Signer (XmlDocClassPtr doc, KeyPtr key)
|
50
|
+
: mXmlDoc(doc),
|
51
|
+
mKey(key),
|
52
|
+
mVerifyKey(0),
|
53
|
+
c14n_excl(0),
|
54
|
+
mAddKeyInfo(0),
|
55
|
+
mAddKeyValue(0)
|
56
|
+
{}
|
57
|
+
|
58
|
+
|
59
|
+
Signer::Signer (XmlDocClassPtr doc, KeyPtr key, KeyPtr verifyKey)
|
60
|
+
: mXmlDoc(doc),
|
61
|
+
mKey(key),
|
62
|
+
mVerifyKey(verifyKey),
|
63
|
+
c14n_excl(0),
|
64
|
+
mAddKeyInfo(0),
|
65
|
+
mAddKeyValue(0)
|
66
|
+
{
|
67
|
+
if (!mVerifyKey)
|
68
|
+
{
|
69
|
+
return;
|
70
|
+
}
|
71
|
+
key->addCert(mVerifyKey);
|
72
|
+
mAddKeyInfo = 1;
|
73
|
+
mAddKeyValue = 1;
|
74
|
+
}
|
75
|
+
|
76
|
+
|
77
|
+
Signer::Signer (XmlDocClassPtr doc, KeyPtr key, X509CertificatePtr cert)
|
78
|
+
: mXmlDoc(doc),
|
79
|
+
mKey(key),
|
80
|
+
mVerifyKey(0),
|
81
|
+
c14n_excl(0),
|
82
|
+
mAddKeyInfo(0),
|
83
|
+
mAddKeyValue(0)
|
84
|
+
{
|
85
|
+
if (key && key->isValid() && cert)
|
86
|
+
{
|
87
|
+
mVerifyKey = cert->getKey();
|
88
|
+
if (mKey->addCert(cert) >= 0)
|
89
|
+
{
|
90
|
+
mAddKeyInfo = 1;
|
91
|
+
}
|
92
|
+
}
|
93
|
+
}
|
94
|
+
|
95
|
+
|
96
|
+
Signer::Signer (XmlDocClassPtr doc, KeyPtr key, vector<X509CertificatePtr> cert)
|
97
|
+
: mXmlDoc(doc),
|
98
|
+
mKey(key),
|
99
|
+
mVerifyKey(0),
|
100
|
+
c14n_excl(0),
|
101
|
+
mAddKeyInfo(0),
|
102
|
+
mAddKeyValue(0)
|
103
|
+
{
|
104
|
+
if (key && key->isValid() && (cert.size() > 0))
|
105
|
+
{
|
106
|
+
mVerifyKey = cert[0]->getKey();
|
107
|
+
if (mKey->addCert(cert) >= 0)
|
108
|
+
{
|
109
|
+
mAddKeyInfo = 1;
|
110
|
+
}
|
111
|
+
}
|
112
|
+
}
|
113
|
+
|
114
|
+
|
115
|
+
Signer::~Signer ()
|
116
|
+
{}
|
117
|
+
|
118
|
+
|
119
|
+
XmlDocClassPtr Signer::sign ()
|
120
|
+
{
|
121
|
+
return sign((XPathPtr)0);
|
122
|
+
}
|
123
|
+
|
124
|
+
|
125
|
+
XmlDocClassPtr Signer::sign (XPathPtr xPath)
|
126
|
+
{
|
127
|
+
return sign(xPath, false);
|
128
|
+
}
|
129
|
+
|
130
|
+
|
131
|
+
XmlDocClassPtr Signer::sign (XPathPtr xPath, bool insertBefore)
|
132
|
+
{
|
133
|
+
assert(mXmlDoc);
|
134
|
+
XmlDocClassPtr copyDoc = new XmlDoc(*mXmlDoc);
|
135
|
+
if (!copyDoc)
|
136
|
+
{
|
137
|
+
THROW(MemoryError, "Unable to create duplicate XML document", 0);
|
138
|
+
}
|
139
|
+
XmlDocClassPtr origXmlDoc = mXmlDoc;
|
140
|
+
mXmlDoc = copyDoc;
|
141
|
+
int retVal = xPath ? signInPlace(xPath, insertBefore) : signInPlace();
|
142
|
+
mXmlDoc = origXmlDoc;
|
143
|
+
if (retVal < 0)
|
144
|
+
{
|
145
|
+
return 0;
|
146
|
+
}
|
147
|
+
return copyDoc;
|
148
|
+
}
|
149
|
+
|
150
|
+
|
151
|
+
int Signer::signInPlace ()
|
152
|
+
{
|
153
|
+
assert(mXmlDoc);
|
154
|
+
if (!*mXmlDoc)
|
155
|
+
{
|
156
|
+
THROW(DocError, "Document was not loaded", -1);
|
157
|
+
}
|
158
|
+
if (!validateXPathRefs())
|
159
|
+
{
|
160
|
+
THROW(XPathError, "Invalid XPath references", -1);
|
161
|
+
}
|
162
|
+
xmlNodePtr sigNode = xmlSecFindNode(xmlDocGetRootElement(*mXmlDoc),
|
163
|
+
xmlSecNodeSignature, xmlSecDSigNs);
|
164
|
+
if (sigNode == NULL)
|
165
|
+
{
|
166
|
+
sigNode = createTemplate(*mXmlDoc, 0, false);
|
167
|
+
}
|
168
|
+
return signNode(sigNode);
|
169
|
+
}
|
170
|
+
|
171
|
+
|
172
|
+
int Signer::signInPlace (XPathPtr xPath)
|
173
|
+
{
|
174
|
+
return signInPlace(xPath, false);
|
175
|
+
}
|
176
|
+
|
177
|
+
|
178
|
+
int Signer::signInPlace (XPathPtr xPath, bool insertBefore)
|
179
|
+
{
|
180
|
+
assert(xPath);
|
181
|
+
assert(mXmlDoc);
|
182
|
+
if (!*mXmlDoc)
|
183
|
+
{
|
184
|
+
THROW(DocError, "Document was not loaded", -1);
|
185
|
+
}
|
186
|
+
if (!validateXPathRefs())
|
187
|
+
{
|
188
|
+
THROW(XPathError, "Invalid XPath references", -1);
|
189
|
+
}
|
190
|
+
xmlNodePtr node = locateSignature(xPath);
|
191
|
+
if (!node)
|
192
|
+
{
|
193
|
+
return -1;
|
194
|
+
}
|
195
|
+
xmlNodePtr sigNode = checkForSignatureElement(node, insertBefore);
|
196
|
+
if (!sigNode)
|
197
|
+
{
|
198
|
+
sigNode = createTemplate(*mXmlDoc, node, insertBefore);
|
199
|
+
}
|
200
|
+
return signNode(sigNode);
|
201
|
+
}
|
202
|
+
|
203
|
+
|
204
|
+
xmlNodePtr Signer::locateSignature (XPathPtr xPath)
|
205
|
+
{
|
206
|
+
xmlXPathObjectPtr xpObj = xPath->evalExpression(mXmlDoc);
|
207
|
+
if (xpObj == NULL)
|
208
|
+
{
|
209
|
+
THROW(XPathError, "Unable to evaluate XPath expression", 0);
|
210
|
+
}
|
211
|
+
//fprintf(stderr, "'%s' found %d nodes\n", xpathstr, xpObj->nodesetval->nodeNr);
|
212
|
+
if (xpObj->nodesetval->nodeNr == 0)
|
213
|
+
{
|
214
|
+
THROW(XPathError, "No nodes found for XPath expression", 0);
|
215
|
+
}
|
216
|
+
if (xpObj->nodesetval->nodeNr > 1)
|
217
|
+
{
|
218
|
+
THROW(XPathError, "Multiple nodes found for XPath expression", 0);
|
219
|
+
}
|
220
|
+
xmlNodePtr node = *(xpObj->nodesetval->nodeTab);
|
221
|
+
if (node->type == XML_DOCUMENT_NODE)
|
222
|
+
{
|
223
|
+
// take care of the "/" xpath case; we sign the first child of the doc
|
224
|
+
// instead of the entire doc (a fine but necessary distinction)
|
225
|
+
node = node->children;
|
226
|
+
}
|
227
|
+
//xmlElemDump(stderr, *mXmlDoc, node);
|
228
|
+
return node;
|
229
|
+
}
|
230
|
+
|
231
|
+
|
232
|
+
xmlNodePtr Signer::checkForSignatureElement (xmlNodePtr node, int insertBefore)
|
233
|
+
{
|
234
|
+
xmlNodePtr sigNode = 0;
|
235
|
+
if (node)
|
236
|
+
{
|
237
|
+
if (insertBefore && (node->parent->type != XML_DOCUMENT_NODE))
|
238
|
+
{
|
239
|
+
// Check previous sibling
|
240
|
+
node = node->prev;
|
241
|
+
}
|
242
|
+
else
|
243
|
+
{
|
244
|
+
// Check children
|
245
|
+
node = xmlSecFindChild(node, xmlSecNodeSignature, xmlSecDSigNs);
|
246
|
+
}
|
247
|
+
}
|
248
|
+
else
|
249
|
+
{
|
250
|
+
// check root element
|
251
|
+
node = xmlDocGetRootElement(*mXmlDoc);
|
252
|
+
}
|
253
|
+
if (node && xmlSecCheckNodeName(node, xmlSecNodeSignature, xmlSecDSigNs))
|
254
|
+
{
|
255
|
+
sigNode = node;
|
256
|
+
}
|
257
|
+
return sigNode;
|
258
|
+
}
|
259
|
+
|
260
|
+
|
261
|
+
int Signer::setKeyStore (KeyStorePtr newKeyStore)
|
262
|
+
{
|
263
|
+
keyStore = newKeyStore;
|
264
|
+
return keyStore ? 0 : -1;
|
265
|
+
}
|
266
|
+
|
267
|
+
|
268
|
+
void Signer::attachPublicKey (int value)
|
269
|
+
{
|
270
|
+
mAddKeyValue = value;
|
271
|
+
}
|
272
|
+
|
273
|
+
|
274
|
+
int Signer::addCertFromFile (string fileName, string format)
|
275
|
+
{
|
276
|
+
assert(mKey);
|
277
|
+
if (mKey->addCertFromFile(fileName, format) < 0)
|
278
|
+
{
|
279
|
+
return -1;
|
280
|
+
}
|
281
|
+
mAddKeyInfo = 1;
|
282
|
+
return 0;
|
283
|
+
}
|
284
|
+
|
285
|
+
|
286
|
+
int Signer::addCert (X509CertificatePtr cert)
|
287
|
+
{
|
288
|
+
assert(mKey);
|
289
|
+
if (mKey->addCert(cert) < 0)
|
290
|
+
{
|
291
|
+
return -1;
|
292
|
+
}
|
293
|
+
mAddKeyInfo = 1;
|
294
|
+
return 0;
|
295
|
+
}
|
296
|
+
|
297
|
+
|
298
|
+
int Signer::useExclusiveCanonicalizer (string prefixes)
|
299
|
+
{
|
300
|
+
c14n_excl = 1;
|
301
|
+
c14n_excl_incprefixes = prefixes;
|
302
|
+
return 0;
|
303
|
+
}
|
304
|
+
|
305
|
+
|
306
|
+
void Signer::addReference (XPathPtr xPathPtr)
|
307
|
+
{
|
308
|
+
assert(xPathPtr);
|
309
|
+
XPath xPath (*xPathPtr);
|
310
|
+
xPathRefs.push_back(xPath);
|
311
|
+
}
|
312
|
+
|
313
|
+
|
314
|
+
xmlSecTransformId Signer::c14nMethod () const
|
315
|
+
{
|
316
|
+
return c14n_excl ?
|
317
|
+
xmlSecTransformExclC14NId :
|
318
|
+
xmlSecTransformInclC14NId;
|
319
|
+
}
|
320
|
+
|
321
|
+
|
322
|
+
xmlNodePtr Signer::c14nMethodTransform (xmlNodePtr refNode)
|
323
|
+
{
|
324
|
+
assert(refNode);
|
325
|
+
xmlNodePtr xformNode = xmlSecTmplReferenceAddTransform(refNode,
|
326
|
+
c14nMethod());
|
327
|
+
if (xformNode == 0)
|
328
|
+
{
|
329
|
+
THROW(LibError, "Failed to add c14n transform to reference", 0);
|
330
|
+
}
|
331
|
+
return xformNode;
|
332
|
+
}
|
333
|
+
|
334
|
+
|
335
|
+
int Signer::isEnveloped (xmlNodePtr refNode, XPath& xPath)
|
336
|
+
{
|
337
|
+
xmlXPathObjectPtr xpObj = xPath.evalExpression(mXmlDoc);
|
338
|
+
if (xpObj == NULL)
|
339
|
+
{
|
340
|
+
THROW(XPathError, "Unable to evaluate XPath expression", -1);
|
341
|
+
}
|
342
|
+
xmlSecNodeSetPtr nodes = xmlSecNodeSetCreate(*mXmlDoc,
|
343
|
+
xpObj->nodesetval,
|
344
|
+
xmlSecNodeSetTree);
|
345
|
+
if (nodes == NULL)
|
346
|
+
{
|
347
|
+
THROW(LibError, "Unable to create node set from XPath results", -1);
|
348
|
+
}
|
349
|
+
int ret = xmlSecNodeSetContains(nodes, refNode, refNode->parent);
|
350
|
+
if (ret < 0)
|
351
|
+
{
|
352
|
+
THROW(LibError, "Failure checking containment in node set", ret);
|
353
|
+
}
|
354
|
+
return ret;
|
355
|
+
}
|
356
|
+
|
357
|
+
|
358
|
+
int Signer::certAdded ()
|
359
|
+
{
|
360
|
+
int certAdded = 0;
|
361
|
+
if (mKey)
|
362
|
+
{
|
363
|
+
X509CertificatePtr cert = mKey->getCertificate();
|
364
|
+
certAdded = ((const void*)cert != 0);
|
365
|
+
}
|
366
|
+
return certAdded;
|
367
|
+
}
|
368
|
+
|
369
|
+
|
370
|
+
xmlNodePtr Signer::createTemplate (xmlDocPtr doc, xmlNodePtr node, bool insertBefore)
|
371
|
+
{
|
372
|
+
assert(doc);
|
373
|
+
assert(mKey);
|
374
|
+
assert(mKey->getKey());
|
375
|
+
assert(mKey->getKey()->value);
|
376
|
+
assert(mKey->getKey()->value->id);
|
377
|
+
|
378
|
+
XmlCharBuf objectId (xmlSecGenerateID(BAD_CAST "obj-", 10));
|
379
|
+
if (!(int)objectId)
|
380
|
+
{
|
381
|
+
THROW(MemoryError, "Unable to allocate generated ID", 0);
|
382
|
+
}
|
383
|
+
|
384
|
+
xmlSecKeyDataId keyDataId = mKey->getKey()->value->id;
|
385
|
+
xmlSecTransformId signatureTransformId = NULL;
|
386
|
+
if (keyDataId == xmlSecKeyDataDsaId)
|
387
|
+
{
|
388
|
+
signatureTransformId = xmlSecTransformDsaSha1Id;
|
389
|
+
}
|
390
|
+
else if (keyDataId == xmlSecKeyDataRsaId)
|
391
|
+
{
|
392
|
+
signatureTransformId = xmlSecTransformRsaSha1Id;
|
393
|
+
}
|
394
|
+
else if (keyDataId == xmlSecKeyDataHmacId)
|
395
|
+
{
|
396
|
+
signatureTransformId = xmlSecTransformHmacSha1Id;
|
397
|
+
}
|
398
|
+
else
|
399
|
+
{
|
400
|
+
THROW(KeyError, "Unable to find signature transform for key type", 0);
|
401
|
+
}
|
402
|
+
xmlNodePtr sigNode =
|
403
|
+
#ifdef HAVE_XMLSECTMPLSIGNATURECREATENSPREF
|
404
|
+
xmlSecTmplSignatureCreateNsPref(doc, c14nMethod(), signatureTransformId, NULL, BAD_CAST "ds");
|
405
|
+
#else
|
406
|
+
xmlSecTmplSignatureCreate(doc, c14nMethod(), signatureTransformId, NULL);
|
407
|
+
#endif
|
408
|
+
if (sigNode == NULL)
|
409
|
+
{
|
410
|
+
THROW(LibError, "Failed to create signature template", 0);
|
411
|
+
}
|
412
|
+
|
413
|
+
// enveloping if no location to put the signature
|
414
|
+
if (node == NULL)
|
415
|
+
{
|
416
|
+
// add <dsig:Signature/> node to the doc
|
417
|
+
xmlNodePtr objContents = xmlDocGetRootElement(doc);
|
418
|
+
xmlDocSetRootElement(doc, sigNode);
|
419
|
+
|
420
|
+
// Add ObjectNode
|
421
|
+
xmlNodePtr objNode = xmlSecTmplSignatureAddObject(xmlDocGetRootElement(doc),
|
422
|
+
BAD_CAST objectId, NULL, NULL);
|
423
|
+
if (objNode == NULL)
|
424
|
+
{
|
425
|
+
THROW(LibError, "Failed to add object to signature template", 0);
|
426
|
+
}
|
427
|
+
|
428
|
+
xmlAddChild(objNode, objContents);
|
429
|
+
}
|
430
|
+
|
431
|
+
if (c14n_excl)
|
432
|
+
{
|
433
|
+
xmlNodePtr c14nMethodNode = xmlSecTmplSignatureGetC14NMethodNode(sigNode);
|
434
|
+
if (c14nMethodNode == NULL)
|
435
|
+
{
|
436
|
+
THROW(LibError, "Couldn't retrieve C14N method node", 0);
|
437
|
+
}
|
438
|
+
if (c14n_excl_incprefixes.length() > 0)
|
439
|
+
{
|
440
|
+
if (xmlSecTmplTransformAddC14NInclNamespaces(c14nMethodNode,
|
441
|
+
BAD_CAST c14n_excl_incprefixes.c_str()) < 0)
|
442
|
+
{
|
443
|
+
THROW(LibError, "Couldn't set C14N incl namespaces", 0);
|
444
|
+
}
|
445
|
+
}
|
446
|
+
}
|
447
|
+
|
448
|
+
if (xPathRefs.size() > 0)
|
449
|
+
{
|
450
|
+
for (vector<XPath>::iterator xPathRef = xPathRefs.begin();
|
451
|
+
xPathRef != xPathRefs.end(); xPathRef++)
|
452
|
+
{
|
453
|
+
int enveloped = 0;
|
454
|
+
string uri ("");
|
455
|
+
// don't use xpointer(/), use "" instead for greater compatibility
|
456
|
+
if (xPathRef->getXPath() != "/")
|
457
|
+
{
|
458
|
+
uri = "#";
|
459
|
+
uri += xPathRef->getNamespaceStr();
|
460
|
+
if (node == NULL)
|
461
|
+
{
|
462
|
+
uri += "xmlns(dsig=http://www.w3.org/2000/09/xmldsig#)xpointer(";
|
463
|
+
uri += "/descendant::dsig:Object[@Id='";
|
464
|
+
uri += (const char*)objectId;
|
465
|
+
uri += "']";
|
466
|
+
}
|
467
|
+
else
|
468
|
+
{
|
469
|
+
uri += "xpointer(";
|
470
|
+
}
|
471
|
+
uri += xPathRef->getXPath();
|
472
|
+
uri += ")";
|
473
|
+
}
|
474
|
+
else
|
475
|
+
{
|
476
|
+
// reference is "/", so we're definitely enveloped
|
477
|
+
enveloped = 1;
|
478
|
+
}
|
479
|
+
xmlNodePtr refNode =
|
480
|
+
xmlSecTmplSignatureAddReference(sigNode, xmlSecTransformSha1Id,
|
481
|
+
NULL, BAD_CAST uri.c_str(), NULL);
|
482
|
+
if (refNode == NULL)
|
483
|
+
{
|
484
|
+
THROW(LibError, "Failed to add reference to signature template", 0);
|
485
|
+
}
|
486
|
+
if (node)
|
487
|
+
{
|
488
|
+
enveloped = enveloped || isEnveloped(node, *xPathRef);
|
489
|
+
if (enveloped < 0)
|
490
|
+
{
|
491
|
+
return 0;
|
492
|
+
}
|
493
|
+
else if (enveloped)
|
494
|
+
{
|
495
|
+
// add enveloped transform
|
496
|
+
if (xmlSecTmplReferenceAddTransform(refNode,
|
497
|
+
xmlSecTransformEnvelopedId) == NULL)
|
498
|
+
{
|
499
|
+
THROW(LibError, "Failed to add enveloped transform to reference", 0);
|
500
|
+
}
|
501
|
+
}
|
502
|
+
}
|
503
|
+
if (c14nMethodTransform(refNode) == 0)
|
504
|
+
{
|
505
|
+
return 0;
|
506
|
+
}
|
507
|
+
}
|
508
|
+
}
|
509
|
+
else if (node)
|
510
|
+
{
|
511
|
+
// add reference
|
512
|
+
xmlNodePtr refNode =
|
513
|
+
xmlSecTmplSignatureAddReference(sigNode, xmlSecTransformSha1Id,
|
514
|
+
NULL, BAD_CAST "", NULL);
|
515
|
+
if (refNode == NULL)
|
516
|
+
{
|
517
|
+
THROW(LibError, "Failed to add reference to signature template", 0);
|
518
|
+
}
|
519
|
+
|
520
|
+
// add enveloped transform
|
521
|
+
if (xmlSecTmplReferenceAddTransform(refNode,
|
522
|
+
xmlSecTransformEnvelopedId) == NULL)
|
523
|
+
{
|
524
|
+
THROW(LibError, "Failed to add enveloped transform to reference", 0);
|
525
|
+
}
|
526
|
+
if (c14nMethodTransform(refNode) == 0)
|
527
|
+
{
|
528
|
+
return 0;
|
529
|
+
}
|
530
|
+
}
|
531
|
+
else
|
532
|
+
{
|
533
|
+
string objectRef;
|
534
|
+
objectRef += "#";
|
535
|
+
objectRef += (const char*)objectId;
|
536
|
+
xmlNodePtr refNode =
|
537
|
+
xmlSecTmplSignatureAddReference(xmlDocGetRootElement(doc),
|
538
|
+
xmlSecTransformSha1Id,
|
539
|
+
NULL, BAD_CAST objectRef.c_str(), NULL);
|
540
|
+
if (refNode == NULL)
|
541
|
+
{
|
542
|
+
THROW(LibError, "Failed to add reference to signature template", 0);
|
543
|
+
}
|
544
|
+
if (c14nMethodTransform(refNode) == 0)
|
545
|
+
{
|
546
|
+
return 0;
|
547
|
+
}
|
548
|
+
}
|
549
|
+
|
550
|
+
// add <dsig:KeyInfo/> and <dsig:KeyName/> nodes to put key name
|
551
|
+
// in the signed document
|
552
|
+
// Don't add <dsig:KeyInfo/> unless absolutely necessary though
|
553
|
+
xmlNodePtr keyInfoNode = NULL;
|
554
|
+
|
555
|
+
if (mAddKeyInfo || mAddKeyValue || keyStore)
|
556
|
+
{
|
557
|
+
if (!keyInfoNode)
|
558
|
+
{
|
559
|
+
keyInfoNode = xmlSecTmplSignatureEnsureKeyInfo(sigNode, NULL);
|
560
|
+
if (keyInfoNode == NULL)
|
561
|
+
{
|
562
|
+
THROW(LibError, "Failed to add key info to signature template", 0);
|
563
|
+
}
|
564
|
+
}
|
565
|
+
if (mAddKeyValue) {
|
566
|
+
if (xmlSecTmplKeyInfoAddKeyValue(keyInfoNode) == NULL)
|
567
|
+
{
|
568
|
+
THROW(LibError, "Failed to add key value to signature template", 0);
|
569
|
+
}
|
570
|
+
}
|
571
|
+
}
|
572
|
+
|
573
|
+
if (certAdded() > 0)
|
574
|
+
{
|
575
|
+
if (!keyInfoNode)
|
576
|
+
{
|
577
|
+
keyInfoNode = xmlSecTmplSignatureEnsureKeyInfo(sigNode, NULL);
|
578
|
+
if (keyInfoNode == NULL)
|
579
|
+
{
|
580
|
+
THROW(LibError, "Failed to add key info to signature template", 0);
|
581
|
+
}
|
582
|
+
}
|
583
|
+
if (xmlSecTmplKeyInfoAddX509Data(keyInfoNode) == NULL)
|
584
|
+
{
|
585
|
+
THROW(LibError, "Failed to add X509Data node to signature template", 0);
|
586
|
+
}
|
587
|
+
}
|
588
|
+
|
589
|
+
if (mKey->getName().length())
|
590
|
+
{
|
591
|
+
if (!keyInfoNode)
|
592
|
+
{
|
593
|
+
keyInfoNode = xmlSecTmplSignatureEnsureKeyInfo(sigNode, NULL);
|
594
|
+
if (keyInfoNode == NULL)
|
595
|
+
{
|
596
|
+
THROW(LibError, "Failed to add key info to signature template", 0);
|
597
|
+
}
|
598
|
+
}
|
599
|
+
if (xmlSecTmplKeyInfoAddKeyName(keyInfoNode, NULL) == NULL)
|
600
|
+
{
|
601
|
+
THROW(LibError, "Failed to add key name to signature template", 0);
|
602
|
+
}
|
603
|
+
}
|
604
|
+
|
605
|
+
if (node)
|
606
|
+
{
|
607
|
+
if (insertBefore && (node->parent->type != XML_DOCUMENT_NODE))
|
608
|
+
{
|
609
|
+
return xmlAddPrevSibling(node, sigNode);
|
610
|
+
}
|
611
|
+
return xmlAddChild(node, sigNode);
|
612
|
+
}
|
613
|
+
return xmlDocGetRootElement(doc);
|
614
|
+
}
|
615
|
+
|
616
|
+
|
617
|
+
int Signer::signNode (xmlNodePtr sigNode)
|
618
|
+
{
|
619
|
+
//xmlDocDump(stderr, sigNode->doc);
|
620
|
+
if (!sigNode ||
|
621
|
+
!xmlSecCheckNodeName(sigNode, xmlSecNodeSignature, xmlSecDSigNs))
|
622
|
+
{
|
623
|
+
THROW(XMLError, "Invalid signature node", -1);
|
624
|
+
}
|
625
|
+
|
626
|
+
if (!mKey || !(*mKey))
|
627
|
+
{
|
628
|
+
THROW(KeyError, "Key was not loaded", -1);
|
629
|
+
}
|
630
|
+
|
631
|
+
// create a keys manager if necessary
|
632
|
+
KeysMngr localKeysMngr;
|
633
|
+
xmlSecKeysMngrPtr keysMngr = 0;
|
634
|
+
if (keyStore)
|
635
|
+
{
|
636
|
+
keysMngr = *keyStore;
|
637
|
+
}
|
638
|
+
else
|
639
|
+
{
|
640
|
+
keysMngr = localKeysMngr;
|
641
|
+
}
|
642
|
+
|
643
|
+
if (mVerifyKey)
|
644
|
+
{
|
645
|
+
if ((!keysMngr) ||
|
646
|
+
(xmlSecOpenSSLAppDefaultKeysMngrInit(keysMngr) < 0))
|
647
|
+
{
|
648
|
+
THROW(LibError, "Key manager not created", -1);
|
649
|
+
}
|
650
|
+
// create a duplicate so keys mngr can adopt it & destroy later
|
651
|
+
xmlSecKeyPtr vKey = mVerifyKey->dupKey();
|
652
|
+
if (vKey == NULL)
|
653
|
+
{
|
654
|
+
return -1;
|
655
|
+
}
|
656
|
+
if (xmlSecOpenSSLAppDefaultKeysMngrAdoptKey(keysMngr, vKey) < 0)
|
657
|
+
{
|
658
|
+
THROW(LibError, "Unable to adopt verify key into key manager", -1);
|
659
|
+
}
|
660
|
+
}
|
661
|
+
|
662
|
+
DSigCtx dsigCtx(keysMngr);
|
663
|
+
if (!dsigCtx)
|
664
|
+
{
|
665
|
+
return -1;
|
666
|
+
}
|
667
|
+
// dsigCtx destruction also tries to free key, so give it a dup
|
668
|
+
dsigCtx->signKey = mKey->dupKey();
|
669
|
+
|
670
|
+
// sign the template
|
671
|
+
if (xmlSecDSigCtxSign(dsigCtx, sigNode) < 0)
|
672
|
+
{
|
673
|
+
THROW(LibError, "Signature failed", -1);
|
674
|
+
}
|
675
|
+
// success
|
676
|
+
return 0;
|
677
|
+
}
|
678
|
+
|
679
|
+
|
680
|
+
int Signer::validateXPathRefs ()
|
681
|
+
{
|
682
|
+
int valid = 1;
|
683
|
+
for (vector<XPath>::iterator xPathRef = xPathRefs.begin();
|
684
|
+
xPathRef != xPathRefs.end(); xPathRef++)
|
685
|
+
{
|
686
|
+
valid = valid && (xPathRef->evalExpression(mXmlDoc) != 0);
|
687
|
+
// fprintf(stderr, "Checking '%s': valid %d\n",
|
688
|
+
// xPathRef->getXPath().c_str(), valid);
|
689
|
+
}
|
690
|
+
return valid;
|
691
|
+
}
|