1 |
|
|
#include "base_object-inl.h" |
2 |
|
|
#include "crypto_x509.h" |
3 |
|
|
#include "crypto_common.h" |
4 |
|
|
#include "crypto_context.h" |
5 |
|
|
#include "crypto_keys.h" |
6 |
|
|
#include "crypto_bio.h" |
7 |
|
|
#include "env-inl.h" |
8 |
|
|
#include "memory_tracker-inl.h" |
9 |
|
|
#include "node_errors.h" |
10 |
|
|
#include "util-inl.h" |
11 |
|
|
#include "v8.h" |
12 |
|
|
|
13 |
|
|
#include <string> |
14 |
|
|
#include <vector> |
15 |
|
|
|
16 |
|
|
namespace node { |
17 |
|
|
|
18 |
|
|
using v8::ArrayBufferView; |
19 |
|
|
using v8::Context; |
20 |
|
|
using v8::EscapableHandleScope; |
21 |
|
|
using v8::Function; |
22 |
|
|
using v8::FunctionCallbackInfo; |
23 |
|
|
using v8::FunctionTemplate; |
24 |
|
|
using v8::Isolate; |
25 |
|
|
using v8::Local; |
26 |
|
|
using v8::MaybeLocal; |
27 |
|
|
using v8::Object; |
28 |
|
|
using v8::Uint32; |
29 |
|
|
using v8::Value; |
30 |
|
|
|
31 |
|
|
namespace crypto { |
32 |
|
|
|
33 |
|
53 |
ManagedX509::ManagedX509(X509Pointer&& cert) : cert_(std::move(cert)) {} |
34 |
|
|
|
35 |
|
|
ManagedX509::ManagedX509(const ManagedX509& that) { |
36 |
|
|
*this = that; |
37 |
|
|
} |
38 |
|
|
|
39 |
|
|
ManagedX509& ManagedX509::operator=(const ManagedX509& that) { |
40 |
|
|
cert_.reset(that.get()); |
41 |
|
|
|
42 |
|
|
if (cert_) |
43 |
|
|
X509_up_ref(cert_.get()); |
44 |
|
|
|
45 |
|
|
return *this; |
46 |
|
|
} |
47 |
|
|
|
48 |
|
|
void ManagedX509::MemoryInfo(MemoryTracker* tracker) const { |
49 |
|
|
// This is an approximation based on the der encoding size. |
50 |
|
|
int size = i2d_X509(cert_.get(), nullptr); |
51 |
|
|
tracker->TrackFieldWithSize("cert", size); |
52 |
|
|
} |
53 |
|
|
|
54 |
|
56 |
Local<FunctionTemplate> X509Certificate::GetConstructorTemplate( |
55 |
|
|
Environment* env) { |
56 |
|
56 |
Local<FunctionTemplate> tmpl = env->x509_constructor_template(); |
57 |
✓✓ |
56 |
if (tmpl.IsEmpty()) { |
58 |
|
3 |
Isolate* isolate = env->isolate(); |
59 |
|
3 |
tmpl = NewFunctionTemplate(isolate, nullptr); |
60 |
|
6 |
tmpl->InstanceTemplate()->SetInternalFieldCount( |
61 |
|
|
BaseObject::kInternalFieldCount); |
62 |
|
3 |
tmpl->Inherit(BaseObject::GetConstructorTemplate(env)); |
63 |
|
3 |
tmpl->SetClassName( |
64 |
|
|
FIXED_ONE_BYTE_STRING(env->isolate(), "X509Certificate")); |
65 |
|
3 |
SetProtoMethod(isolate, tmpl, "subject", Subject); |
66 |
|
3 |
SetProtoMethod(isolate, tmpl, "subjectAltName", SubjectAltName); |
67 |
|
3 |
SetProtoMethod(isolate, tmpl, "infoAccess", InfoAccess); |
68 |
|
3 |
SetProtoMethod(isolate, tmpl, "issuer", Issuer); |
69 |
|
3 |
SetProtoMethod(isolate, tmpl, "validTo", ValidTo); |
70 |
|
3 |
SetProtoMethod(isolate, tmpl, "validFrom", ValidFrom); |
71 |
|
3 |
SetProtoMethod(isolate, tmpl, "fingerprint", Fingerprint); |
72 |
|
3 |
SetProtoMethod(isolate, tmpl, "fingerprint256", Fingerprint256); |
73 |
|
3 |
SetProtoMethod(isolate, tmpl, "fingerprint512", Fingerprint512); |
74 |
|
3 |
SetProtoMethod(isolate, tmpl, "keyUsage", KeyUsage); |
75 |
|
3 |
SetProtoMethod(isolate, tmpl, "serialNumber", SerialNumber); |
76 |
|
3 |
SetProtoMethod(isolate, tmpl, "pem", Pem); |
77 |
|
3 |
SetProtoMethod(isolate, tmpl, "raw", Raw); |
78 |
|
3 |
SetProtoMethod(isolate, tmpl, "publicKey", PublicKey); |
79 |
|
3 |
SetProtoMethod(isolate, tmpl, "checkCA", CheckCA); |
80 |
|
3 |
SetProtoMethod(isolate, tmpl, "checkHost", CheckHost); |
81 |
|
3 |
SetProtoMethod(isolate, tmpl, "checkEmail", CheckEmail); |
82 |
|
3 |
SetProtoMethod(isolate, tmpl, "checkIP", CheckIP); |
83 |
|
3 |
SetProtoMethod(isolate, tmpl, "checkIssued", CheckIssued); |
84 |
|
3 |
SetProtoMethod(isolate, tmpl, "checkPrivateKey", CheckPrivateKey); |
85 |
|
3 |
SetProtoMethod(isolate, tmpl, "verify", Verify); |
86 |
|
3 |
SetProtoMethod(isolate, tmpl, "toLegacy", ToLegacy); |
87 |
|
3 |
SetProtoMethod(isolate, tmpl, "getIssuerCert", GetIssuerCert); |
88 |
|
3 |
env->set_x509_constructor_template(tmpl); |
89 |
|
|
} |
90 |
|
56 |
return tmpl; |
91 |
|
|
} |
92 |
|
|
|
93 |
|
2 |
bool X509Certificate::HasInstance(Environment* env, Local<Object> object) { |
94 |
|
4 |
return GetConstructorTemplate(env)->HasInstance(object); |
95 |
|
|
} |
96 |
|
|
|
97 |
|
53 |
MaybeLocal<Object> X509Certificate::New( |
98 |
|
|
Environment* env, |
99 |
|
|
X509Pointer cert, |
100 |
|
|
STACK_OF(X509)* issuer_chain) { |
101 |
|
53 |
std::shared_ptr<ManagedX509> mcert(new ManagedX509(std::move(cert))); |
102 |
|
53 |
return New(env, std::move(mcert), issuer_chain); |
103 |
|
|
} |
104 |
|
|
|
105 |
|
54 |
MaybeLocal<Object> X509Certificate::New( |
106 |
|
|
Environment* env, |
107 |
|
|
std::shared_ptr<ManagedX509> cert, |
108 |
|
|
STACK_OF(X509)* issuer_chain) { |
109 |
|
54 |
EscapableHandleScope scope(env->isolate()); |
110 |
|
|
Local<Function> ctor; |
111 |
✗✓ |
162 |
if (!GetConstructorTemplate(env)->GetFunction(env->context()).ToLocal(&ctor)) |
112 |
|
|
return MaybeLocal<Object>(); |
113 |
|
|
|
114 |
|
|
Local<Object> obj; |
115 |
✗✓ |
108 |
if (!ctor->NewInstance(env->context()).ToLocal(&obj)) |
116 |
|
|
return MaybeLocal<Object>(); |
117 |
|
|
|
118 |
|
54 |
new X509Certificate(env, obj, std::move(cert), issuer_chain); |
119 |
|
54 |
return scope.Escape(obj); |
120 |
|
|
} |
121 |
|
|
|
122 |
|
1 |
MaybeLocal<Object> X509Certificate::GetCert( |
123 |
|
|
Environment* env, |
124 |
|
|
const SSLPointer& ssl) { |
125 |
|
1 |
ClearErrorOnReturn clear_error_on_return; |
126 |
|
1 |
X509* cert = SSL_get_certificate(ssl.get()); |
127 |
✗✓ |
1 |
if (cert == nullptr) |
128 |
|
|
return MaybeLocal<Object>(); |
129 |
|
|
|
130 |
|
1 |
X509Pointer ptr(X509_dup(cert)); |
131 |
|
1 |
return New(env, std::move(ptr)); |
132 |
|
|
} |
133 |
|
|
|
134 |
✗✓ |
1 |
MaybeLocal<Object> X509Certificate::GetPeerCert( |
135 |
|
|
Environment* env, |
136 |
|
|
const SSLPointer& ssl, |
137 |
|
|
GetPeerCertificateFlag flag) { |
138 |
|
1 |
ClearErrorOnReturn clear_error_on_return; |
139 |
|
|
Local<Object> obj; |
140 |
|
|
MaybeLocal<Object> maybe_cert; |
141 |
|
|
|
142 |
|
1 |
bool is_server = |
143 |
|
1 |
static_cast<int>(flag) & static_cast<int>(GetPeerCertificateFlag::SERVER); |
144 |
|
|
|
145 |
✗✓ |
2 |
X509Pointer cert(is_server ? SSL_get_peer_certificate(ssl.get()) : nullptr); |
146 |
|
1 |
STACK_OF(X509)* ssl_certs = SSL_get_peer_cert_chain(ssl.get()); |
147 |
✓✗✓✗ ✗✓✗✓
|
1 |
if (!cert && (ssl_certs == nullptr || sk_X509_num(ssl_certs) == 0)) |
148 |
|
|
return MaybeLocal<Object>(); |
149 |
|
|
|
150 |
|
1 |
std::vector<Local<Value>> certs; |
151 |
|
|
|
152 |
✓✗ |
1 |
if (!cert) { |
153 |
|
1 |
cert.reset(sk_X509_value(ssl_certs, 0)); |
154 |
|
1 |
sk_X509_delete(ssl_certs, 0); |
155 |
|
|
} |
156 |
|
|
|
157 |
|
1 |
return sk_X509_num(ssl_certs) |
158 |
|
2 |
? New(env, std::move(cert), ssl_certs) |
159 |
✓✗✗✓ ✓✗ |
2 |
: New(env, std::move(cert)); |
160 |
|
|
} |
161 |
|
|
|
162 |
|
50 |
void X509Certificate::Parse(const FunctionCallbackInfo<Value>& args) { |
163 |
|
50 |
Environment* env = Environment::GetCurrent(args); |
164 |
|
|
|
165 |
✗✓ |
50 |
CHECK(args[0]->IsArrayBufferView()); |
166 |
|
100 |
ArrayBufferViewContents<unsigned char> buf(args[0].As<ArrayBufferView>()); |
167 |
|
50 |
const unsigned char* data = buf.data(); |
168 |
✓✗ |
50 |
unsigned data_len = buf.length(); |
169 |
|
|
|
170 |
|
|
ClearErrorOnReturn clear_error_on_return; |
171 |
|
50 |
BIOPointer bio(LoadBIO(env, args[0])); |
172 |
✗✓ |
50 |
if (!bio) |
173 |
|
|
return ThrowCryptoError(env, ERR_get_error()); |
174 |
|
|
|
175 |
|
|
Local<Object> cert; |
176 |
|
|
|
177 |
|
|
X509Pointer pem(PEM_read_bio_X509_AUX( |
178 |
|
50 |
bio.get(), nullptr, NoPasswordCallback, nullptr)); |
179 |
✗✓ |
50 |
if (!pem) { |
180 |
|
|
// Try as DER, but return the original PEM failure if it isn't DER. |
181 |
|
|
MarkPopErrorOnReturn mark_here; |
182 |
|
|
|
183 |
|
|
X509Pointer der(d2i_X509(nullptr, &data, data_len)); |
184 |
|
|
if (!der) |
185 |
|
|
return ThrowCryptoError(env, ERR_get_error()); |
186 |
|
|
|
187 |
|
|
if (!X509Certificate::New(env, std::move(der)).ToLocal(&cert)) |
188 |
|
|
return; |
189 |
✗✓ |
100 |
} else if (!X509Certificate::New(env, std::move(pem)).ToLocal(&cert)) { |
190 |
|
|
return; |
191 |
|
|
} |
192 |
|
|
|
193 |
|
100 |
args.GetReturnValue().Set(cert); |
194 |
|
|
} |
195 |
|
|
|
196 |
|
13 |
void X509Certificate::Subject(const FunctionCallbackInfo<Value>& args) { |
197 |
|
13 |
Environment* env = Environment::GetCurrent(args); |
198 |
|
|
X509Certificate* cert; |
199 |
✗✓ |
13 |
ASSIGN_OR_RETURN_UNWRAP(&cert, args.Holder()); |
200 |
|
26 |
BIOPointer bio(BIO_new(BIO_s_mem())); |
201 |
✗✓ |
13 |
CHECK(bio); |
202 |
|
|
Local<Value> ret; |
203 |
✓✗ |
26 |
if (GetSubject(env, bio, cert->get()).ToLocal(&ret)) |
204 |
|
26 |
args.GetReturnValue().Set(ret); |
205 |
|
|
} |
206 |
|
|
|
207 |
|
11 |
void X509Certificate::Issuer(const FunctionCallbackInfo<Value>& args) { |
208 |
|
11 |
Environment* env = Environment::GetCurrent(args); |
209 |
|
|
X509Certificate* cert; |
210 |
✗✓ |
11 |
ASSIGN_OR_RETURN_UNWRAP(&cert, args.Holder()); |
211 |
|
22 |
BIOPointer bio(BIO_new(BIO_s_mem())); |
212 |
✗✓ |
11 |
CHECK(bio); |
213 |
|
|
Local<Value> ret; |
214 |
✓✗ |
22 |
if (GetIssuerString(env, bio, cert->get()).ToLocal(&ret)) |
215 |
|
22 |
args.GetReturnValue().Set(ret); |
216 |
|
|
} |
217 |
|
|
|
218 |
|
34 |
void X509Certificate::SubjectAltName(const FunctionCallbackInfo<Value>& args) { |
219 |
|
34 |
Environment* env = Environment::GetCurrent(args); |
220 |
|
|
X509Certificate* cert; |
221 |
✗✓ |
34 |
ASSIGN_OR_RETURN_UNWRAP(&cert, args.Holder()); |
222 |
|
68 |
BIOPointer bio(BIO_new(BIO_s_mem())); |
223 |
✗✓ |
34 |
CHECK(bio); |
224 |
|
|
Local<Value> ret; |
225 |
✓✗ |
68 |
if (GetSubjectAltNameString(env, bio, cert->get()).ToLocal(&ret)) |
226 |
|
68 |
args.GetReturnValue().Set(ret); |
227 |
|
|
} |
228 |
|
|
|
229 |
|
6 |
void X509Certificate::InfoAccess(const FunctionCallbackInfo<Value>& args) { |
230 |
|
6 |
Environment* env = Environment::GetCurrent(args); |
231 |
|
|
X509Certificate* cert; |
232 |
✗✓ |
6 |
ASSIGN_OR_RETURN_UNWRAP(&cert, args.Holder()); |
233 |
|
12 |
BIOPointer bio(BIO_new(BIO_s_mem())); |
234 |
✗✓ |
6 |
CHECK(bio); |
235 |
|
|
Local<Value> ret; |
236 |
✓✗ |
12 |
if (GetInfoAccessString(env, bio, cert->get()).ToLocal(&ret)) |
237 |
|
12 |
args.GetReturnValue().Set(ret); |
238 |
|
|
} |
239 |
|
|
|
240 |
|
1 |
void X509Certificate::ValidFrom(const FunctionCallbackInfo<Value>& args) { |
241 |
|
1 |
Environment* env = Environment::GetCurrent(args); |
242 |
|
|
X509Certificate* cert; |
243 |
✗✓ |
1 |
ASSIGN_OR_RETURN_UNWRAP(&cert, args.Holder()); |
244 |
|
2 |
BIOPointer bio(BIO_new(BIO_s_mem())); |
245 |
✗✓ |
1 |
CHECK(bio); |
246 |
|
|
Local<Value> ret; |
247 |
✓✗ |
2 |
if (GetValidFrom(env, cert->get(), bio).ToLocal(&ret)) |
248 |
|
2 |
args.GetReturnValue().Set(ret); |
249 |
|
|
} |
250 |
|
|
|
251 |
|
1 |
void X509Certificate::ValidTo(const FunctionCallbackInfo<Value>& args) { |
252 |
|
1 |
Environment* env = Environment::GetCurrent(args); |
253 |
|
|
X509Certificate* cert; |
254 |
✗✓ |
1 |
ASSIGN_OR_RETURN_UNWRAP(&cert, args.Holder()); |
255 |
|
2 |
BIOPointer bio(BIO_new(BIO_s_mem())); |
256 |
✗✓ |
1 |
CHECK(bio); |
257 |
|
|
Local<Value> ret; |
258 |
✓✗ |
2 |
if (GetValidTo(env, cert->get(), bio).ToLocal(&ret)) |
259 |
|
2 |
args.GetReturnValue().Set(ret); |
260 |
|
|
} |
261 |
|
|
|
262 |
|
1 |
void X509Certificate::Fingerprint(const FunctionCallbackInfo<Value>& args) { |
263 |
|
1 |
Environment* env = Environment::GetCurrent(args); |
264 |
|
|
X509Certificate* cert; |
265 |
✗✓ |
1 |
ASSIGN_OR_RETURN_UNWRAP(&cert, args.Holder()); |
266 |
|
|
Local<Value> ret; |
267 |
✓✗ |
2 |
if (GetFingerprintDigest(env, EVP_sha1(), cert->get()).ToLocal(&ret)) |
268 |
|
2 |
args.GetReturnValue().Set(ret); |
269 |
|
|
} |
270 |
|
|
|
271 |
|
1 |
void X509Certificate::Fingerprint256(const FunctionCallbackInfo<Value>& args) { |
272 |
|
1 |
Environment* env = Environment::GetCurrent(args); |
273 |
|
|
X509Certificate* cert; |
274 |
✗✓ |
1 |
ASSIGN_OR_RETURN_UNWRAP(&cert, args.Holder()); |
275 |
|
|
Local<Value> ret; |
276 |
✓✗ |
2 |
if (GetFingerprintDigest(env, EVP_sha256(), cert->get()).ToLocal(&ret)) |
277 |
|
2 |
args.GetReturnValue().Set(ret); |
278 |
|
|
} |
279 |
|
|
|
280 |
|
1 |
void X509Certificate::Fingerprint512(const FunctionCallbackInfo<Value>& args) { |
281 |
|
1 |
Environment* env = Environment::GetCurrent(args); |
282 |
|
|
X509Certificate* cert; |
283 |
✗✓ |
1 |
ASSIGN_OR_RETURN_UNWRAP(&cert, args.Holder()); |
284 |
|
|
Local<Value> ret; |
285 |
✓✗ |
2 |
if (GetFingerprintDigest(env, EVP_sha512(), cert->get()).ToLocal(&ret)) |
286 |
|
2 |
args.GetReturnValue().Set(ret); |
287 |
|
|
} |
288 |
|
|
|
289 |
|
1 |
void X509Certificate::KeyUsage(const FunctionCallbackInfo<Value>& args) { |
290 |
|
1 |
Environment* env = Environment::GetCurrent(args); |
291 |
|
|
X509Certificate* cert; |
292 |
✗✓ |
1 |
ASSIGN_OR_RETURN_UNWRAP(&cert, args.Holder()); |
293 |
|
|
Local<Value> ret; |
294 |
✓✗ |
2 |
if (GetKeyUsage(env, cert->get()).ToLocal(&ret)) |
295 |
|
2 |
args.GetReturnValue().Set(ret); |
296 |
|
|
} |
297 |
|
|
|
298 |
|
3 |
void X509Certificate::SerialNumber(const FunctionCallbackInfo<Value>& args) { |
299 |
|
3 |
Environment* env = Environment::GetCurrent(args); |
300 |
|
|
X509Certificate* cert; |
301 |
✗✓ |
3 |
ASSIGN_OR_RETURN_UNWRAP(&cert, args.Holder()); |
302 |
|
|
Local<Value> ret; |
303 |
✓✗ |
6 |
if (GetSerialNumber(env, cert->get()).ToLocal(&ret)) |
304 |
|
6 |
args.GetReturnValue().Set(ret); |
305 |
|
|
} |
306 |
|
|
|
307 |
|
2 |
void X509Certificate::Raw(const FunctionCallbackInfo<Value>& args) { |
308 |
|
2 |
Environment* env = Environment::GetCurrent(args); |
309 |
|
|
X509Certificate* cert; |
310 |
✗✓ |
2 |
ASSIGN_OR_RETURN_UNWRAP(&cert, args.Holder()); |
311 |
|
|
Local<Value> ret; |
312 |
✓✗ |
4 |
if (GetRawDERCertificate(env, cert->get()).ToLocal(&ret)) |
313 |
|
4 |
args.GetReturnValue().Set(ret); |
314 |
|
|
} |
315 |
|
|
|
316 |
|
2 |
void X509Certificate::PublicKey(const FunctionCallbackInfo<Value>& args) { |
317 |
|
2 |
Environment* env = Environment::GetCurrent(args); |
318 |
|
|
X509Certificate* cert; |
319 |
✗✓ |
2 |
ASSIGN_OR_RETURN_UNWRAP(&cert, args.Holder()); |
320 |
|
|
|
321 |
|
4 |
EVPKeyPointer pkey(X509_get_pubkey(cert->get())); |
322 |
|
4 |
ManagedEVPPKey epkey(std::move(pkey)); |
323 |
|
|
std::shared_ptr<KeyObjectData> key_data = |
324 |
|
4 |
KeyObjectData::CreateAsymmetric(kKeyTypePublic, epkey); |
325 |
|
|
|
326 |
|
|
Local<Value> ret; |
327 |
✓✗ |
4 |
if (KeyObjectHandle::Create(env, key_data).ToLocal(&ret)) |
328 |
|
4 |
args.GetReturnValue().Set(ret); |
329 |
|
|
} |
330 |
|
|
|
331 |
|
1 |
void X509Certificate::Pem(const FunctionCallbackInfo<Value>& args) { |
332 |
|
1 |
Environment* env = Environment::GetCurrent(args); |
333 |
|
|
X509Certificate* cert; |
334 |
✗✓ |
1 |
ASSIGN_OR_RETURN_UNWRAP(&cert, args.Holder()); |
335 |
|
2 |
BIOPointer bio(BIO_new(BIO_s_mem())); |
336 |
✗✓ |
1 |
CHECK(bio); |
337 |
✓✗ |
1 |
if (PEM_write_bio_X509(bio.get(), cert->get())) |
338 |
|
2 |
args.GetReturnValue().Set(ToV8Value(env, bio)); |
339 |
|
|
} |
340 |
|
|
|
341 |
|
1 |
void X509Certificate::CheckCA(const FunctionCallbackInfo<Value>& args) { |
342 |
|
|
X509Certificate* cert; |
343 |
✗✓ |
1 |
ASSIGN_OR_RETURN_UNWRAP(&cert, args.Holder()); |
344 |
✗✓ |
2 |
args.GetReturnValue().Set(X509_check_ca(cert->get()) == 1); |
345 |
|
|
} |
346 |
|
|
|
347 |
|
11 |
void X509Certificate::CheckHost(const FunctionCallbackInfo<Value>& args) { |
348 |
|
11 |
Environment* env = Environment::GetCurrent(args); |
349 |
|
|
X509Certificate* cert; |
350 |
✗✓ |
11 |
ASSIGN_OR_RETURN_UNWRAP(&cert, args.Holder()); |
351 |
|
|
|
352 |
✗✓ |
22 |
CHECK(args[0]->IsString()); // name |
353 |
✗✓ |
11 |
CHECK(args[1]->IsUint32()); // flags |
354 |
|
|
|
355 |
|
22 |
Utf8Value name(env->isolate(), args[0]); |
356 |
|
22 |
uint32_t flags = args[1].As<Uint32>()->Value(); |
357 |
|
|
char* peername; |
358 |
|
|
|
359 |
✓✓✓✗
|
22 |
switch (X509_check_host( |
360 |
|
|
cert->get(), |
361 |
|
11 |
*name, |
362 |
|
|
name.length(), |
363 |
|
|
flags, |
364 |
|
|
&peername)) { |
365 |
✓✗ |
5 |
case 1: { // Match! |
366 |
|
5 |
Local<Value> ret = args[0]; |
367 |
✓✗ |
5 |
if (peername != nullptr) { |
368 |
|
5 |
ret = OneByteString(env->isolate(), peername); |
369 |
|
5 |
OPENSSL_free(peername); |
370 |
|
|
} |
371 |
|
10 |
return args.GetReturnValue().Set(ret); |
372 |
|
|
} |
373 |
|
5 |
case 0: // No Match! |
374 |
|
5 |
return; // No return value is set |
375 |
|
1 |
case -2: // Error! |
376 |
|
1 |
return THROW_ERR_INVALID_ARG_VALUE(env, "Invalid name"); |
377 |
|
|
default: // Error! |
378 |
|
|
return THROW_ERR_CRYPTO_OPERATION_FAILED(env); |
379 |
|
|
} |
380 |
|
|
} |
381 |
|
|
|
382 |
|
3 |
void X509Certificate::CheckEmail(const FunctionCallbackInfo<Value>& args) { |
383 |
|
3 |
Environment* env = Environment::GetCurrent(args); |
384 |
|
|
X509Certificate* cert; |
385 |
✗✓ |
3 |
ASSIGN_OR_RETURN_UNWRAP(&cert, args.Holder()); |
386 |
|
|
|
387 |
✗✓ |
6 |
CHECK(args[0]->IsString()); // name |
388 |
✗✓ |
3 |
CHECK(args[1]->IsUint32()); // flags |
389 |
|
|
|
390 |
|
6 |
Utf8Value name(env->isolate(), args[0]); |
391 |
|
6 |
uint32_t flags = args[1].As<Uint32>()->Value(); |
392 |
|
|
|
393 |
✓✓✓✗
|
6 |
switch (X509_check_email( |
394 |
|
|
cert->get(), |
395 |
|
3 |
*name, |
396 |
|
|
name.length(), |
397 |
|
|
flags)) { |
398 |
|
1 |
case 1: // Match! |
399 |
✓✗ |
2 |
return args.GetReturnValue().Set(args[0]); |
400 |
|
1 |
case 0: // No Match! |
401 |
|
1 |
return; // No return value is set |
402 |
|
1 |
case -2: // Error! |
403 |
|
1 |
return THROW_ERR_INVALID_ARG_VALUE(env, "Invalid name"); |
404 |
|
|
default: // Error! |
405 |
|
|
return THROW_ERR_CRYPTO_OPERATION_FAILED(env); |
406 |
|
|
} |
407 |
|
|
} |
408 |
|
|
|
409 |
|
3 |
void X509Certificate::CheckIP(const FunctionCallbackInfo<Value>& args) { |
410 |
|
3 |
Environment* env = Environment::GetCurrent(args); |
411 |
|
|
X509Certificate* cert; |
412 |
✗✓ |
3 |
ASSIGN_OR_RETURN_UNWRAP(&cert, args.Holder()); |
413 |
|
|
|
414 |
✗✓ |
6 |
CHECK(args[0]->IsString()); // IP |
415 |
✗✓ |
3 |
CHECK(args[1]->IsUint32()); // flags |
416 |
|
|
|
417 |
|
6 |
Utf8Value name(env->isolate(), args[0]); |
418 |
|
6 |
uint32_t flags = args[1].As<Uint32>()->Value(); |
419 |
|
|
|
420 |
✗✓✓✗
|
3 |
switch (X509_check_ip_asc(cert->get(), *name, flags)) { |
421 |
|
|
case 1: // Match! |
422 |
|
|
return args.GetReturnValue().Set(args[0]); |
423 |
|
2 |
case 0: // No Match! |
424 |
|
2 |
return; // No return value is set |
425 |
|
1 |
case -2: // Error! |
426 |
|
1 |
return THROW_ERR_INVALID_ARG_VALUE(env, "Invalid IP"); |
427 |
|
|
default: // Error! |
428 |
|
|
return THROW_ERR_CRYPTO_OPERATION_FAILED(env); |
429 |
|
|
} |
430 |
|
|
} |
431 |
|
|
|
432 |
|
2 |
void X509Certificate::CheckIssued(const FunctionCallbackInfo<Value>& args) { |
433 |
|
2 |
Environment* env = Environment::GetCurrent(args); |
434 |
|
|
X509Certificate* cert; |
435 |
✗✓ |
2 |
ASSIGN_OR_RETURN_UNWRAP(&cert, args.Holder()); |
436 |
|
|
|
437 |
✗✓ |
2 |
CHECK(args[0]->IsObject()); |
438 |
✗✓ |
4 |
CHECK(X509Certificate::HasInstance(env, args[0].As<Object>())); |
439 |
|
|
|
440 |
|
|
X509Certificate* issuer; |
441 |
✗✓ |
2 |
ASSIGN_OR_RETURN_UNWRAP(&issuer, args[0]); |
442 |
|
|
|
443 |
✓✓ |
4 |
args.GetReturnValue().Set( |
444 |
|
2 |
X509_check_issued(issuer->get(), cert->get()) == X509_V_OK); |
445 |
|
|
} |
446 |
|
|
|
447 |
|
2 |
void X509Certificate::CheckPrivateKey(const FunctionCallbackInfo<Value>& args) { |
448 |
|
|
X509Certificate* cert; |
449 |
✗✓ |
2 |
ASSIGN_OR_RETURN_UNWRAP(&cert, args.Holder()); |
450 |
|
|
|
451 |
✗✓ |
2 |
CHECK(args[0]->IsObject()); |
452 |
|
|
KeyObjectHandle* key; |
453 |
✗✓ |
2 |
ASSIGN_OR_RETURN_UNWRAP(&key, args[0]); |
454 |
✗✓ |
2 |
CHECK_EQ(key->Data()->GetKeyType(), kKeyTypePrivate); |
455 |
|
|
|
456 |
|
2 |
ClearErrorOnReturn clear_error_on_return; |
457 |
|
|
|
458 |
✓✓ |
2 |
args.GetReturnValue().Set( |
459 |
|
2 |
X509_check_private_key( |
460 |
|
2 |
cert->get(), |
461 |
|
4 |
key->Data()->GetAsymmetricKey().get()) == 1); |
462 |
|
|
} |
463 |
|
|
|
464 |
|
3 |
void X509Certificate::Verify(const FunctionCallbackInfo<Value>& args) { |
465 |
|
|
X509Certificate* cert; |
466 |
✗✓ |
3 |
ASSIGN_OR_RETURN_UNWRAP(&cert, args.Holder()); |
467 |
|
|
|
468 |
✗✓ |
3 |
CHECK(args[0]->IsObject()); |
469 |
|
|
KeyObjectHandle* key; |
470 |
✗✓ |
3 |
ASSIGN_OR_RETURN_UNWRAP(&key, args[0]); |
471 |
✗✓ |
3 |
CHECK_EQ(key->Data()->GetKeyType(), kKeyTypePublic); |
472 |
|
|
|
473 |
|
3 |
ClearErrorOnReturn clear_error_on_return; |
474 |
|
|
|
475 |
✓✓ |
3 |
args.GetReturnValue().Set( |
476 |
|
3 |
X509_verify( |
477 |
|
|
cert->get(), |
478 |
|
6 |
key->Data()->GetAsymmetricKey().get()) > 0); |
479 |
|
|
} |
480 |
|
|
|
481 |
|
16 |
void X509Certificate::ToLegacy(const FunctionCallbackInfo<Value>& args) { |
482 |
|
16 |
Environment* env = Environment::GetCurrent(args); |
483 |
|
|
X509Certificate* cert; |
484 |
✗✓ |
16 |
ASSIGN_OR_RETURN_UNWRAP(&cert, args.Holder()); |
485 |
|
|
Local<Value> ret; |
486 |
✓✗ |
32 |
if (X509ToObject(env, cert->get()).ToLocal(&ret)) |
487 |
|
32 |
args.GetReturnValue().Set(ret); |
488 |
|
|
} |
489 |
|
|
|
490 |
|
3 |
void X509Certificate::GetIssuerCert(const FunctionCallbackInfo<Value>& args) { |
491 |
|
|
X509Certificate* cert; |
492 |
✗✓ |
3 |
ASSIGN_OR_RETURN_UNWRAP(&cert, args.Holder()); |
493 |
✓✓ |
3 |
if (cert->issuer_cert_) |
494 |
|
4 |
args.GetReturnValue().Set(cert->issuer_cert_->object()); |
495 |
|
|
} |
496 |
|
|
|
497 |
|
54 |
X509Certificate::X509Certificate( |
498 |
|
|
Environment* env, |
499 |
|
|
Local<Object> object, |
500 |
|
|
std::shared_ptr<ManagedX509> cert, |
501 |
|
54 |
STACK_OF(X509)* issuer_chain) |
502 |
|
|
: BaseObject(env, object), |
503 |
|
54 |
cert_(std::move(cert)) { |
504 |
|
54 |
MakeWeak(); |
505 |
|
|
|
506 |
✓✓✓✗ ✓✓ |
54 |
if (issuer_chain != nullptr && sk_X509_num(issuer_chain)) { |
507 |
|
1 |
X509Pointer cert(X509_dup(sk_X509_value(issuer_chain, 0))); |
508 |
|
1 |
sk_X509_delete(issuer_chain, 0); |
509 |
|
1 |
Local<Object> obj = sk_X509_num(issuer_chain) |
510 |
|
|
? X509Certificate::New(env, std::move(cert), issuer_chain) |
511 |
|
|
.ToLocalChecked() |
512 |
✓✗✗✓
|
2 |
: X509Certificate::New(env, std::move(cert)) |
513 |
✗✓ |
2 |
.ToLocalChecked(); |
514 |
|
1 |
issuer_cert_.reset(Unwrap<X509Certificate>(obj)); |
515 |
|
|
} |
516 |
|
54 |
} |
517 |
|
|
|
518 |
|
|
void X509Certificate::MemoryInfo(MemoryTracker* tracker) const { |
519 |
|
|
tracker->TrackField("cert", cert_); |
520 |
|
|
} |
521 |
|
|
|
522 |
|
|
BaseObjectPtr<BaseObject> |
523 |
|
1 |
X509Certificate::X509CertificateTransferData::Deserialize( |
524 |
|
|
Environment* env, |
525 |
|
|
Local<Context> context, |
526 |
|
|
std::unique_ptr<worker::TransferData> self) { |
527 |
✗✓ |
2 |
if (context != env->context()) { |
528 |
|
|
THROW_ERR_MESSAGE_TARGET_CONTEXT_UNAVAILABLE(env); |
529 |
|
|
return {}; |
530 |
|
|
} |
531 |
|
|
|
532 |
|
|
Local<Value> handle; |
533 |
✗✓ |
2 |
if (!X509Certificate::New(env, data_).ToLocal(&handle)) |
534 |
|
|
return {}; |
535 |
|
|
|
536 |
|
|
return BaseObjectPtr<BaseObject>( |
537 |
|
1 |
Unwrap<X509Certificate>(handle.As<Object>())); |
538 |
|
|
} |
539 |
|
|
|
540 |
|
|
|
541 |
|
1 |
BaseObject::TransferMode X509Certificate::GetTransferMode() const { |
542 |
|
1 |
return BaseObject::TransferMode::kCloneable; |
543 |
|
|
} |
544 |
|
|
|
545 |
|
1 |
std::unique_ptr<worker::TransferData> X509Certificate::CloneForMessaging() |
546 |
|
|
const { |
547 |
|
1 |
return std::make_unique<X509CertificateTransferData>(cert_); |
548 |
|
|
} |
549 |
|
|
|
550 |
|
|
|
551 |
|
800 |
void X509Certificate::Initialize(Environment* env, Local<Object> target) { |
552 |
|
800 |
SetMethod(env->context(), target, "parseX509", X509Certificate::Parse); |
553 |
|
|
|
554 |
|
2400 |
NODE_DEFINE_CONSTANT(target, X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT); |
555 |
|
2400 |
NODE_DEFINE_CONSTANT(target, X509_CHECK_FLAG_NEVER_CHECK_SUBJECT); |
556 |
|
2400 |
NODE_DEFINE_CONSTANT(target, X509_CHECK_FLAG_NO_WILDCARDS); |
557 |
|
2400 |
NODE_DEFINE_CONSTANT(target, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS); |
558 |
|
2400 |
NODE_DEFINE_CONSTANT(target, X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS); |
559 |
|
1600 |
NODE_DEFINE_CONSTANT(target, X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS); |
560 |
|
800 |
} |
561 |
|
|
|
562 |
|
5639 |
void X509Certificate::RegisterExternalReferences( |
563 |
|
|
ExternalReferenceRegistry* registry) { |
564 |
|
5639 |
registry->Register(X509Certificate::Parse); |
565 |
|
5639 |
registry->Register(Subject); |
566 |
|
5639 |
registry->Register(SubjectAltName); |
567 |
|
5639 |
registry->Register(InfoAccess); |
568 |
|
5639 |
registry->Register(Issuer); |
569 |
|
5639 |
registry->Register(ValidTo); |
570 |
|
5639 |
registry->Register(ValidFrom); |
571 |
|
5639 |
registry->Register(Fingerprint); |
572 |
|
5639 |
registry->Register(Fingerprint256); |
573 |
|
5639 |
registry->Register(KeyUsage); |
574 |
|
5639 |
registry->Register(SerialNumber); |
575 |
|
5639 |
registry->Register(Pem); |
576 |
|
5639 |
registry->Register(Raw); |
577 |
|
5639 |
registry->Register(PublicKey); |
578 |
|
5639 |
registry->Register(CheckCA); |
579 |
|
5639 |
registry->Register(CheckHost); |
580 |
|
5639 |
registry->Register(CheckEmail); |
581 |
|
5639 |
registry->Register(CheckIP); |
582 |
|
5639 |
registry->Register(CheckIssued); |
583 |
|
5639 |
registry->Register(CheckPrivateKey); |
584 |
|
5639 |
registry->Register(Verify); |
585 |
|
5639 |
registry->Register(ToLegacy); |
586 |
|
5639 |
registry->Register(GetIssuerCert); |
587 |
|
5639 |
} |
588 |
|
|
} // namespace crypto |
589 |
|
|
} // namespace node |