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,313 @@
|
|
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
|
+
#ifndef _VERIFIER_H
|
18
|
+
#define _VERIFIER_H
|
19
|
+
#include <vector>
|
20
|
+
#include "Key.h"
|
21
|
+
#include "XmlDoc.h"
|
22
|
+
#include "XPath.h"
|
23
|
+
#include "KeyStore.h"
|
24
|
+
#include "X509Certificate.h"
|
25
|
+
#include "XmlElement.h"
|
26
|
+
#include "Exceptions.h"
|
27
|
+
#include "NodeSet.h"
|
28
|
+
using namespace std;
|
29
|
+
|
30
|
+
|
31
|
+
/**
|
32
|
+
* Verifier verifies XML signatures according to the W3C XML-Signature specification (http://www.w3.org/2000/09/xmldsig#).
|
33
|
+
*
|
34
|
+
* A DOM document may contain several signatures. This class can
|
35
|
+
* verify all signatures in a document, one at a time, with either the
|
36
|
+
* verification key supplied in the document, or with a user-supplied
|
37
|
+
* key.
|
38
|
+
*
|
39
|
+
* Usage:
|
40
|
+
*
|
41
|
+
* -# Construct the Verifier. You must provide the Verifier with
|
42
|
+
* -# the XML document that contains the signature
|
43
|
+
* -# (optional) the location of the signature within the XML
|
44
|
+
* document. To provide the location of the signature within an
|
45
|
+
* XML document, you must use an XPath expression. For more on
|
46
|
+
* constructing XPaths, see http://www.w3.org/TR/xpath. If no
|
47
|
+
* location is specified, Verifier will attempt to verify the
|
48
|
+
* first Signature element it finds in the document.
|
49
|
+
* -# Supply the verification key. This key may be taken from the
|
50
|
+
* document (if available) by default, or a specific key may be
|
51
|
+
* supplied by the user.
|
52
|
+
* -# Verify the signature. Note that the Verifier will locate and
|
53
|
+
* verify the signature specified in Step 1.
|
54
|
+
*
|
55
|
+
* Note: An XML document may contain several signatures, but this API
|
56
|
+
* only supports verification of one signature per Verifier. If you
|
57
|
+
* need to verify multiple signatures, create a new Verifier for each
|
58
|
+
* signature.
|
59
|
+
*
|
60
|
+
* Example use (C++):
|
61
|
+
*
|
62
|
+
* @code
|
63
|
+
* XPath signatureLocation("//ds:Signature");
|
64
|
+
* signatureLocation.addNamespace("ds", "http://www.w3.org/2000/09/xmldsig#");
|
65
|
+
* Verifier verifier(doc, signatureLocation);
|
66
|
+
* bool isVerified = verifier.verify();
|
67
|
+
* @endcode
|
68
|
+
*
|
69
|
+
* In the above example, we try to verify the signature by
|
70
|
+
* \e signatureLocation using the key found within the signature at
|
71
|
+
* \e signatureLocation. If \e signatureLocation does not contain a single
|
72
|
+
* signature, an exception is thrown. To set the key used to verify
|
73
|
+
* the signature:
|
74
|
+
*
|
75
|
+
* @code
|
76
|
+
* XPath signatureLocation("//ds:Signature");
|
77
|
+
* signatureLocation.addNamespace("ds", "http://www.w3.org/2000/09/xmldsig#");
|
78
|
+
* Verifier verifier(doc, signatureLocation);
|
79
|
+
* Key verifyingKey = some_public_key;
|
80
|
+
* bool isVerified = verifier.verify(verifyingKey);
|
81
|
+
* @endcode
|
82
|
+
*
|
83
|
+
* If exceptions are enabled, error codes will not be returned.
|
84
|
+
*/
|
85
|
+
class Verifier
|
86
|
+
{
|
87
|
+
public:
|
88
|
+
/**
|
89
|
+
* Creates a Verifier that points to the first Signature in the document.
|
90
|
+
* @param doc An XML document
|
91
|
+
* @throws MemoryError
|
92
|
+
*/
|
93
|
+
Verifier (XmlDocClassPtr doc);
|
94
|
+
/**
|
95
|
+
* Creates a Verifier that points to a single Signature within the document.
|
96
|
+
* @param doc An XML document
|
97
|
+
* @param xpath An XPath expression that points to a single signature
|
98
|
+
* @throws MemoryError
|
99
|
+
*/
|
100
|
+
Verifier (XmlDocClassPtr doc, XPathPtr xpath);
|
101
|
+
/**
|
102
|
+
* Destroy the Verifier object.
|
103
|
+
*/
|
104
|
+
~Verifier ();
|
105
|
+
|
106
|
+
/**
|
107
|
+
* Use trusted certificates from a KeyStore to verify the signature.
|
108
|
+
* @param keyStore A key store
|
109
|
+
* @return 0 on success, -1 on error
|
110
|
+
* @throws ValueError If the keyStore is invalid
|
111
|
+
*/
|
112
|
+
int setKeyStore (KeyStorePtr keyStore);
|
113
|
+
/**
|
114
|
+
* Verifies the signature using the public key embedded in the document.
|
115
|
+
* @return 1 if signature valid, 0 if not valid, -1 on error
|
116
|
+
* @throws DocError The document to verify is invalid in some way
|
117
|
+
* @throws KeyError No verifying key is available
|
118
|
+
* @throws XMLError A signature couldn't be found in the document
|
119
|
+
*/
|
120
|
+
int verify ();
|
121
|
+
/**
|
122
|
+
* Verifies the signature at the previously given signature
|
123
|
+
* location using the supplied key. Note that all keying
|
124
|
+
* information in the signature being verified is ignored, and the
|
125
|
+
* supplied key will be used.
|
126
|
+
* @param key A public key
|
127
|
+
* @return 1 if signature valid, 0 if not valid, -1 on error
|
128
|
+
* @throws DocError The document to verify is invalid in some way
|
129
|
+
* @throws KeyError The verifying key is invalid
|
130
|
+
* @throws XMLError A signature couldn't be found in the document
|
131
|
+
*/
|
132
|
+
int verify (KeyPtr key);
|
133
|
+
/**
|
134
|
+
* Returns the verification key in the document. The verifying key
|
135
|
+
* will be retrieved from the Signature element pointed to by the
|
136
|
+
* XPath supplied in the constructor. If no XPath was specified,
|
137
|
+
* uses the first Signature element found in the document.
|
138
|
+
* @return Pointer to the key, or null if none is found, or for cases
|
139
|
+
* where both a key and a certificate are part of the signature's
|
140
|
+
* keying information, null is returned, if the key is not equal
|
141
|
+
* to the certificate's key.
|
142
|
+
* @throws DocError The document to verify is invalid in some way
|
143
|
+
* @throws XMLError A signature couldn't be found in the document
|
144
|
+
* @throws LibError An error occurred in one of the base libraries
|
145
|
+
*/
|
146
|
+
KeyPtr getVerifyingKey ();
|
147
|
+
/**
|
148
|
+
* Returns whether the element at the given XPath is contained by
|
149
|
+
* one of the Signature references, i.e., whether it is signed.
|
150
|
+
* @param xpath An XPath expression pointing to the signature
|
151
|
+
* @return 1 if element is referenced, 0 if not, -1 on error
|
152
|
+
*/
|
153
|
+
int isReferenced (XPathPtr xpath);
|
154
|
+
/**
|
155
|
+
* Returns all elements referenced by the Signature.
|
156
|
+
* @return a (possibly empty) list of elements
|
157
|
+
*/
|
158
|
+
vector<XmlElementPtr> getReferencedElements ();
|
159
|
+
|
160
|
+
/**
|
161
|
+
* Returns the certificate in the document. If there are multiple
|
162
|
+
* certificates available, only the first (in document order) will
|
163
|
+
* be returned.
|
164
|
+
* @return Pointer to the certificate found at the XPath
|
165
|
+
* expression; null if no certificate can be found, or if both
|
166
|
+
* a key and a certificate is part of the signature's keying
|
167
|
+
* information, and the key is not equal to the certificate's
|
168
|
+
* key.
|
169
|
+
* @throws DocError The document to verify is invalid in some way
|
170
|
+
* @throws XMLError A signature couldn't be found in the document
|
171
|
+
* @throws LibError An error occurred in one of the base libraries
|
172
|
+
* @throws XPathError if xpath results in no usable certificate
|
173
|
+
* (as defined by http://www.w3.org/2000/09/xmldsig:KeyInfo/X509Data)
|
174
|
+
*/
|
175
|
+
X509CertificatePtr getCertificate ();
|
176
|
+
/**
|
177
|
+
* Retrieve the certificate chain from the signature element.
|
178
|
+
* @return the certificate chain found at the xpath expression;
|
179
|
+
* null if no certificate chain can be found, or if both a key
|
180
|
+
* and at least one certificate is part of the signature's
|
181
|
+
* keying information, and the key is not equal to the leaf
|
182
|
+
* certificate's key. If there is a single certificate found,
|
183
|
+
* a vector of size 1 will be returned.
|
184
|
+
* @throws XPathError if xpath results in no usable certificate
|
185
|
+
* (as defined by http://www.w3.org/2000/09/xmldsig:KeyInfo/X509Data)
|
186
|
+
*/
|
187
|
+
vector<X509CertificatePtr> getCertificateChain ();
|
188
|
+
/**
|
189
|
+
* Set whether or not to check certificate chain on verify.
|
190
|
+
* (default is to do so.)
|
191
|
+
* @param skip 1 to NOT check certificate chain on verify, 0 to do so
|
192
|
+
*/
|
193
|
+
void skipCertCheck (int skip = 1) { skipCertCheckFlag = (skip != 0); }
|
194
|
+
|
195
|
+
/// @cond NO_INTERFACE
|
196
|
+
|
197
|
+
protected:
|
198
|
+
/**
|
199
|
+
* The XML document to verify.
|
200
|
+
*/
|
201
|
+
XmlDocClassPtr mXmlDoc;
|
202
|
+
/**
|
203
|
+
* The (possibly null) XPath expression pointing to a signature.
|
204
|
+
*/
|
205
|
+
XPathPtr xPath;
|
206
|
+
/**
|
207
|
+
* The KeyStore.
|
208
|
+
*/
|
209
|
+
KeyStorePtr mKeyStore;
|
210
|
+
/**
|
211
|
+
* Default keystore created internally.
|
212
|
+
*/
|
213
|
+
KeyStorePtr mDefaultKeyStore;
|
214
|
+
/**
|
215
|
+
* Don't check certificate chain on verification.
|
216
|
+
*/
|
217
|
+
bool skipCertCheckFlag;
|
218
|
+
|
219
|
+
/**
|
220
|
+
* Get internal representation of keystore.
|
221
|
+
*/
|
222
|
+
xmlSecKeysMngrPtr getKeysMngr ();
|
223
|
+
/**
|
224
|
+
* Set node to the first one returned by the xpath expression.
|
225
|
+
*/
|
226
|
+
int findSignatureXPath (xmlDocPtr doc, xmlNodePtr* node);
|
227
|
+
/**
|
228
|
+
* Find the signature node.
|
229
|
+
*/
|
230
|
+
int findStartNode (xmlDocPtr doc, xmlNodePtr* node);
|
231
|
+
/**
|
232
|
+
* Verify a signature specified by the node.
|
233
|
+
*/
|
234
|
+
int verifyNode (xmlDocPtr doc, xmlNodePtr node, KeyPtr key);
|
235
|
+
/**
|
236
|
+
* Verify a signature specified by the node (internal method called by verify(*)
|
237
|
+
*/
|
238
|
+
int doVerify (KeyPtr verifyingKey);
|
239
|
+
/**
|
240
|
+
* Initialiser.
|
241
|
+
*/
|
242
|
+
void verifierInit ();
|
243
|
+
/**
|
244
|
+
* Check if element referred to by XPath expression is contained
|
245
|
+
* in the nodeset.
|
246
|
+
*/
|
247
|
+
int isContained (xmlSecNodeSetPtr nodeSet, XPathPtr xPathElem);
|
248
|
+
/**
|
249
|
+
* Get a nodeset for the initial transform context.
|
250
|
+
*/
|
251
|
+
xmlSecNodeSetPtr nodeSetFromTransformCtx (xmlSecTransformCtxPtr ctx,
|
252
|
+
xmlDocPtr doc);
|
253
|
+
/**
|
254
|
+
* Get certificates from X509Data element.
|
255
|
+
* @param node Signature data node under which X509Data node exists
|
256
|
+
* @return list of X509 certificates
|
257
|
+
*/
|
258
|
+
vector<X509CertificatePtr> getX509Data (xmlNodePtr node);
|
259
|
+
/**
|
260
|
+
* Get the X509 certificate from the X509Certificate node.
|
261
|
+
* @param node X509Certificate element
|
262
|
+
* @return certificate pointer, null on error
|
263
|
+
*/
|
264
|
+
X509CertificatePtr getX509CertificateNode (xmlNodePtr node);
|
265
|
+
/**
|
266
|
+
* Callback type for Verifier::refNodes().
|
267
|
+
* @param nset node set for referenced nodes
|
268
|
+
* @param verifier verifier object we're operating on
|
269
|
+
* @param data user data pointer
|
270
|
+
* @return nonzero to abort (negative is an error)
|
271
|
+
*/
|
272
|
+
typedef int (*refNodesCallback) (xmlSecNodeSetPtr nset, Verifier* verifier, void* data);
|
273
|
+
/**
|
274
|
+
* Callback for Verifier::isReferenced(), passed to Verifier::refNodes().
|
275
|
+
* @param nset node set for referenced nodes
|
276
|
+
* @param verifier verifier object we're operating on
|
277
|
+
* @param data pointer to XPathPtr object
|
278
|
+
* @return nonzero if XPath expression is contained (negative is an error)
|
279
|
+
*/
|
280
|
+
static int isReferencedCallback (xmlSecNodeSetPtr nset, Verifier* verifier, void* data);
|
281
|
+
/**
|
282
|
+
* Callback for xmlSecNodeSetWalk, running through elements and adding copies
|
283
|
+
* of them to the vector in the user data pointer.
|
284
|
+
* @param cur the current node
|
285
|
+
* @param data pointer to vector<XmlElementPtr>
|
286
|
+
* @return 0, keep running through referenced nodesets or -1 on error
|
287
|
+
*/
|
288
|
+
static int getElementsCallback (xmlSecNodeSetPtr, xmlNodePtr cur, xmlNodePtr, void *data);
|
289
|
+
/**
|
290
|
+
* Callback for Verifier::getReferencedElements(), passed to Verifier::refNodes().
|
291
|
+
* @param nset node set for referenced nodes
|
292
|
+
* @param verifier verifier object we're operating on
|
293
|
+
* @param data pointer to vector<XmlElementPtr>
|
294
|
+
* @return 0, keep running through referenced nodesets or -1 on error
|
295
|
+
* @throw LibError if the node set walk call fails
|
296
|
+
*/
|
297
|
+
static int getReferencedElementsCallback (xmlSecNodeSetPtr nset, Verifier* verifier, void* data);
|
298
|
+
/**
|
299
|
+
* Get the set of nodes referenced by the signature, executing the callback
|
300
|
+
* for each node set.
|
301
|
+
* @param callbackFn function to call for each reference node set
|
302
|
+
* @data data pointer to pass to callback
|
303
|
+
* @return set of nodes, null on error
|
304
|
+
* @throws DocError if no document
|
305
|
+
* @throws XMLError if the signature can't be found
|
306
|
+
* @throws LibError on various xmlsec errors
|
307
|
+
*/
|
308
|
+
int refNodes (refNodesCallback callbackFn, void* data);
|
309
|
+
|
310
|
+
/// @endcond
|
311
|
+
};
|
312
|
+
|
313
|
+
#endif
|
@@ -0,0 +1,362 @@
|
|
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 "X509Certificate.h"
|
18
|
+
#include <libxml/tree.h>
|
19
|
+
#include <openssl/x509.h>
|
20
|
+
#include <openssl/x509v3.h>
|
21
|
+
#include <xmlsec/openssl/x509.h>
|
22
|
+
#include <xmlsec/openssl/app.h>
|
23
|
+
#include <xmlsec/openssl/evp.h>
|
24
|
+
#include <xmlsec/xmlsec.h>
|
25
|
+
#include <xmlsec/errors.h>
|
26
|
+
#include <iostream>
|
27
|
+
#include "BioWrap.h"
|
28
|
+
|
29
|
+
X509Certificate::X509Certificate ()
|
30
|
+
: ptr(0)
|
31
|
+
{}
|
32
|
+
|
33
|
+
|
34
|
+
X509Certificate::X509Certificate (X509* x509ptr)
|
35
|
+
: ptr(0)
|
36
|
+
{
|
37
|
+
if (x509ptr)
|
38
|
+
{
|
39
|
+
ptr = X509_dup(x509ptr);
|
40
|
+
if (ptr == NULL)
|
41
|
+
{
|
42
|
+
THROW_NORET(MemoryError, "Unable to copy certificate data");
|
43
|
+
}
|
44
|
+
}
|
45
|
+
}
|
46
|
+
|
47
|
+
|
48
|
+
X509Certificate::X509Certificate (const X509Certificate& cert)
|
49
|
+
: ptr(0)
|
50
|
+
{
|
51
|
+
operator=(cert);
|
52
|
+
}
|
53
|
+
|
54
|
+
|
55
|
+
const X509Certificate& X509Certificate::operator= (const X509Certificate& cert)
|
56
|
+
{
|
57
|
+
if (&cert != this)
|
58
|
+
{
|
59
|
+
ptr = cert.getDup();
|
60
|
+
}
|
61
|
+
return *this;
|
62
|
+
}
|
63
|
+
|
64
|
+
|
65
|
+
X509Certificate::~X509Certificate ()
|
66
|
+
{
|
67
|
+
if (ptr)
|
68
|
+
{
|
69
|
+
X509_free(ptr);
|
70
|
+
}
|
71
|
+
}
|
72
|
+
|
73
|
+
|
74
|
+
X509* X509Certificate::getDup () const
|
75
|
+
{
|
76
|
+
X509* dupCert = X509_dup(ptr);
|
77
|
+
if (dupCert == NULL)
|
78
|
+
{
|
79
|
+
THROW(MemoryError, "Unable to copy certificate data", 0);
|
80
|
+
}
|
81
|
+
return dupCert;
|
82
|
+
}
|
83
|
+
|
84
|
+
|
85
|
+
KeyPtr X509Certificate::getKey () const
|
86
|
+
{
|
87
|
+
KeyPtr keyPtr;
|
88
|
+
if (!ptr)
|
89
|
+
{
|
90
|
+
return 0;
|
91
|
+
}
|
92
|
+
xmlSecKeyDataPtr keyDataPtr = xmlSecOpenSSLX509CertGetKey(ptr);
|
93
|
+
if (!keyDataPtr)
|
94
|
+
{
|
95
|
+
return 0;
|
96
|
+
}
|
97
|
+
keyPtr = KeyPtr(new Key);
|
98
|
+
keyPtr->create();
|
99
|
+
if (xmlSecKeySetValue(*keyPtr, keyDataPtr) < 0)
|
100
|
+
{
|
101
|
+
THROW(LibError, "Couldn't set key value", 0);
|
102
|
+
}
|
103
|
+
|
104
|
+
xmlSecKeyDataPtr certData = xmlSecKeyEnsureData(*keyPtr,
|
105
|
+
xmlSecOpenSSLKeyDataX509Id);
|
106
|
+
if (certData == NULL)
|
107
|
+
{
|
108
|
+
THROW(LibError, "Couldn't create cert data", 0);
|
109
|
+
}
|
110
|
+
if (xmlSecOpenSSLKeyDataX509AdoptCert(certData, getDup()) < 0)
|
111
|
+
{
|
112
|
+
THROW(LibError, "Unable to adopt cert data", 0);
|
113
|
+
}
|
114
|
+
return keyPtr;
|
115
|
+
}
|
116
|
+
|
117
|
+
int X509Certificate::loadFromFile (string fileName, string format)
|
118
|
+
{
|
119
|
+
Key key;
|
120
|
+
if (ptr)
|
121
|
+
{
|
122
|
+
X509_free(ptr);
|
123
|
+
}
|
124
|
+
int ret = key.loadFromFile(fileName, format, "");
|
125
|
+
if (ret < 0)
|
126
|
+
{
|
127
|
+
THROW(IOError, "Unable to load X509 certificate key", ret);
|
128
|
+
}
|
129
|
+
X509CertificatePtr cert = key.getCertificate();
|
130
|
+
if (cert)
|
131
|
+
{
|
132
|
+
operator=(*cert);
|
133
|
+
}
|
134
|
+
else
|
135
|
+
{
|
136
|
+
return -1;
|
137
|
+
}
|
138
|
+
return 0;
|
139
|
+
}
|
140
|
+
|
141
|
+
string X509Certificate::getSubjectDN()
|
142
|
+
{
|
143
|
+
string name;
|
144
|
+
if (!ptr) {
|
145
|
+
THROW(LibError, "Certificate not loaded", name);
|
146
|
+
}
|
147
|
+
const xmlChar* buf = nameToString(X509_get_subject_name(ptr));
|
148
|
+
if (buf) {
|
149
|
+
name = string((const char*)buf);
|
150
|
+
}
|
151
|
+
return name;
|
152
|
+
}
|
153
|
+
|
154
|
+
string X509Certificate::getIssuerDN()
|
155
|
+
{
|
156
|
+
string name;
|
157
|
+
if (!ptr) {
|
158
|
+
THROW(LibError, "Certificate not loaded", name);
|
159
|
+
}
|
160
|
+
const xmlChar* buf = nameToString(X509_get_issuer_name(ptr));
|
161
|
+
if (buf) {
|
162
|
+
name = string((const char*)buf);
|
163
|
+
}
|
164
|
+
return name;
|
165
|
+
}
|
166
|
+
|
167
|
+
int X509Certificate::getVersion()
|
168
|
+
{
|
169
|
+
if (!ptr) {
|
170
|
+
THROW(LibError, "Certificate not loaded", -1);
|
171
|
+
}
|
172
|
+
return X509_get_version(ptr)+1;
|
173
|
+
}
|
174
|
+
|
175
|
+
int X509Certificate::isValid()
|
176
|
+
{
|
177
|
+
if (!ptr) {
|
178
|
+
THROW(LibError, "Certificate not loaded", -1);
|
179
|
+
}
|
180
|
+
int i = X509_cmp_time(X509_get_notBefore(ptr), NULL);
|
181
|
+
if (i == 0) {
|
182
|
+
THROW(LibError, "Invalid data in certificate notBefore field", 0);
|
183
|
+
}
|
184
|
+
if (i > 0) {
|
185
|
+
return 0;
|
186
|
+
}
|
187
|
+
i = X509_cmp_time(X509_get_notAfter(ptr), NULL);
|
188
|
+
if (i == 0) {
|
189
|
+
THROW(LibError, "Invalid data in certificate notAfter field", 0);
|
190
|
+
}
|
191
|
+
if (i < 0) {
|
192
|
+
return 0;
|
193
|
+
}
|
194
|
+
return 1;
|
195
|
+
}
|
196
|
+
|
197
|
+
// yanked from xmlsec/src/openssl/x509.c
|
198
|
+
xmlChar*
|
199
|
+
X509Certificate::nameToString(X509_NAME* nm) {
|
200
|
+
xmlChar *res = NULL;
|
201
|
+
BIO *mem = NULL;
|
202
|
+
long size;
|
203
|
+
|
204
|
+
xmlSecAssert2(nm != NULL, NULL);
|
205
|
+
|
206
|
+
mem = BIO_new(BIO_s_mem());
|
207
|
+
if(mem == NULL) {
|
208
|
+
xmlSecError(XMLSEC_ERRORS_HERE,
|
209
|
+
NULL,
|
210
|
+
"BIO_new",
|
211
|
+
XMLSEC_ERRORS_R_CRYPTO_FAILED,
|
212
|
+
"BIO_s_mem");
|
213
|
+
return(NULL);
|
214
|
+
}
|
215
|
+
|
216
|
+
if (X509_NAME_print_ex(mem, nm, 0, XN_FLAG_RFC2253) <=0) {
|
217
|
+
xmlSecError(XMLSEC_ERRORS_HERE,
|
218
|
+
NULL,
|
219
|
+
"X509_NAME_print_ex",
|
220
|
+
XMLSEC_ERRORS_R_CRYPTO_FAILED,
|
221
|
+
XMLSEC_ERRORS_NO_MESSAGE);
|
222
|
+
BIO_free_all(mem);
|
223
|
+
return(NULL);
|
224
|
+
}
|
225
|
+
|
226
|
+
BIO_flush(mem); /* should call flush ? */
|
227
|
+
|
228
|
+
size = BIO_pending(mem);
|
229
|
+
res = (xmlChar*) xmlMalloc(size + 1);
|
230
|
+
if(res == NULL) {
|
231
|
+
xmlSecError(XMLSEC_ERRORS_HERE,
|
232
|
+
NULL,
|
233
|
+
"xmlMalloc",
|
234
|
+
XMLSEC_ERRORS_R_MALLOC_FAILED,
|
235
|
+
XMLSEC_ERRORS_NO_MESSAGE);
|
236
|
+
BIO_free_all(mem);
|
237
|
+
return(NULL);
|
238
|
+
}
|
239
|
+
|
240
|
+
size = BIO_read(mem, res, size);
|
241
|
+
res[size] = '\0';
|
242
|
+
|
243
|
+
BIO_free_all(mem);
|
244
|
+
return(res);
|
245
|
+
}
|
246
|
+
|
247
|
+
|
248
|
+
int X509Certificate::verify (KeyPtr key)
|
249
|
+
{
|
250
|
+
if (!key || !key->isValid())
|
251
|
+
{
|
252
|
+
THROW(KeyError, "Invalid key", -1);
|
253
|
+
}
|
254
|
+
xmlSecKeyPtr secKey = key->getKey();
|
255
|
+
if (!secKey || !secKey->value)
|
256
|
+
{
|
257
|
+
THROW(KeyError, "Invalid key", -1);
|
258
|
+
}
|
259
|
+
EVP_PKEY* evp_pkey = xmlSecOpenSSLEvpKeyDataGetEvp(secKey->value);
|
260
|
+
if (!evp_pkey)
|
261
|
+
{
|
262
|
+
THROW(KeyError, "Key is not a public key", -1);
|
263
|
+
}
|
264
|
+
int ret = X509_verify(ptr, evp_pkey);
|
265
|
+
if (ret < 0)
|
266
|
+
{
|
267
|
+
THROW(LibError, "X509 verify failed", -1);
|
268
|
+
}
|
269
|
+
return ret;
|
270
|
+
}
|
271
|
+
|
272
|
+
#ifdef WIN32
|
273
|
+
#define strncasecmp _strnicmp
|
274
|
+
#endif
|
275
|
+
|
276
|
+
int X509Certificate::getBasicConstraints () {
|
277
|
+
if (!ptr) {
|
278
|
+
THROW(LibError, "Certificate not loaded", -1);
|
279
|
+
}
|
280
|
+
X509_EXTENSION *ext = NULL;
|
281
|
+
int pathlen = -1;
|
282
|
+
X509V3_EXT_METHOD *method = NULL;
|
283
|
+
STACK_OF(CONF_VALUE) *vals = NULL;
|
284
|
+
void *ext_str = NULL;
|
285
|
+
|
286
|
+
int index = X509_get_ext_by_NID(ptr, NID_basic_constraints, -1);
|
287
|
+
if((index >= 0) && (ext = X509_get_ext(ptr, index))) {
|
288
|
+
#if OPENSSL_VERSION_NUMBER >= 0x0090800fL
|
289
|
+
const unsigned char **ext_value_data;
|
290
|
+
ext_value_data = (const_cast<const unsigned char **> (&ext->value->data));
|
291
|
+
#else
|
292
|
+
unsigned char **ext_value_data = &ext->value->data;
|
293
|
+
#endif
|
294
|
+
if (!ext_value_data) {
|
295
|
+
goto end;
|
296
|
+
}
|
297
|
+
method = X509V3_EXT_get(ext);
|
298
|
+
if (!method || !method->i2v) {
|
299
|
+
goto end;
|
300
|
+
}
|
301
|
+
ext_str = ASN1_item_d2i(NULL, ext_value_data, ext->value->length, ASN1_ITEM_ptr(method->it));
|
302
|
+
if (!ext_str) {
|
303
|
+
goto end;
|
304
|
+
}
|
305
|
+
vals = method->i2v(method, ext_str, NULL);
|
306
|
+
if (!vals) {
|
307
|
+
goto end;
|
308
|
+
}
|
309
|
+
int isCA = 0;
|
310
|
+
for(int i = 0; i < sk_CONF_VALUE_num(vals); i++) {
|
311
|
+
CONF_VALUE *val = sk_CONF_VALUE_value(vals, i);
|
312
|
+
if (!val) {
|
313
|
+
goto end;
|
314
|
+
}
|
315
|
+
if ((strncasecmp(val->name,"CA", 2)==0) && (strncasecmp(val->value, "TRUE", 4)==0))
|
316
|
+
isCA=1;
|
317
|
+
if ((strncasecmp(val->name,"pathlen", 2)==0))
|
318
|
+
pathlen=atoi(val->value);
|
319
|
+
}
|
320
|
+
if (isCA) {
|
321
|
+
if (pathlen == -1) {
|
322
|
+
pathlen = 0x7fffffff;
|
323
|
+
}
|
324
|
+
}
|
325
|
+
}
|
326
|
+
end:
|
327
|
+
if (ext_str) ASN1_item_free((ASN1_VALUE*)ext_str, ASN1_ITEM_ptr(method->it));
|
328
|
+
if (vals) sk_CONF_VALUE_pop_free(vals, X509V3_conf_free);
|
329
|
+
return pathlen;
|
330
|
+
}
|
331
|
+
|
332
|
+
|
333
|
+
int X509Certificate::isEqualTo (X509Certificate& other)
|
334
|
+
{
|
335
|
+
BioWrap bioSelf, bioOther;
|
336
|
+
|
337
|
+
i2d_X509_bio(bioSelf, ptr);
|
338
|
+
BIO_flush(bioSelf);
|
339
|
+
|
340
|
+
i2d_X509_bio(bioOther, other.ptr);
|
341
|
+
BIO_flush(bioOther);
|
342
|
+
|
343
|
+
xmlSecByte *memSelf=0, *memOther=0;
|
344
|
+
long sizeSelf=0, sizeOther=0;
|
345
|
+
sizeSelf = BIO_get_mem_data(bioSelf, &memSelf);
|
346
|
+
sizeOther = BIO_get_mem_data(bioOther, &memOther);
|
347
|
+
|
348
|
+
if (sizeSelf != sizeOther)
|
349
|
+
{
|
350
|
+
return 0;
|
351
|
+
}
|
352
|
+
|
353
|
+
while (sizeSelf)
|
354
|
+
{
|
355
|
+
if (*memSelf++ != *memOther++)
|
356
|
+
{
|
357
|
+
return 0;
|
358
|
+
}
|
359
|
+
sizeSelf--;
|
360
|
+
}
|
361
|
+
return 1;
|
362
|
+
}
|