xmlsig 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
}
|