Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nodejs/node.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJames M Snell <jasnell@gmail.com>2021-01-26 03:38:51 +0300
committerDanielle Adams <adamzdanielle@gmail.com>2021-02-16 17:11:25 +0300
commitdc84c181c33d92c8bf910d52bbdc37d898d071e4 (patch)
treed3215763ce696ddfe2a0993612d4bb60b7995ef2 /src
parent13fe17c4ef548bc6b5808f61c418df1b0214d910 (diff)
tls: add ability to get cert/peer cert as X509Certificate object
Signed-off-by: James M Snell <jasnell@gmail.com> PR-URL: https://github.com/nodejs/node/pull/37070 Reviewed-By: Tobias Nießen <tniessen@tnie.de> Reviewed-By: Filip Skokan <panva.ip@gmail.com>
Diffstat (limited to 'src')
-rw-r--r--src/crypto/crypto_tls.cc26
-rw-r--r--src/crypto/crypto_tls.h4
-rw-r--r--src/crypto/crypto_x509.cc60
-rw-r--r--src/crypto/crypto_x509.h13
4 files changed, 73 insertions, 30 deletions
diff --git a/src/crypto/crypto_tls.cc b/src/crypto/crypto_tls.cc
index 52e57ab9862..398509bc5ce 100644
--- a/src/crypto/crypto_tls.cc
+++ b/src/crypto/crypto_tls.cc
@@ -1591,6 +1591,20 @@ void TLSWrap::GetPeerCertificate(const FunctionCallbackInfo<Value>& args) {
args.GetReturnValue().Set(ret);
}
+void TLSWrap::GetPeerX509Certificate(const FunctionCallbackInfo<Value>& args) {
+ TLSWrap* w;
+ ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder());
+ Environment* env = w->env();
+
+ X509Certificate::GetPeerCertificateFlag flag = w->is_server()
+ ? X509Certificate::GetPeerCertificateFlag::SERVER
+ : X509Certificate::GetPeerCertificateFlag::NONE;
+
+ Local<Value> ret;
+ if (X509Certificate::GetPeerCert(env, w->ssl_, flag).ToLocal(&ret))
+ args.GetReturnValue().Set(ret);
+}
+
void TLSWrap::GetCertificate(const FunctionCallbackInfo<Value>& args) {
TLSWrap* w;
ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder());
@@ -1601,6 +1615,15 @@ void TLSWrap::GetCertificate(const FunctionCallbackInfo<Value>& args) {
args.GetReturnValue().Set(ret);
}
+void TLSWrap::GetX509Certificate(const FunctionCallbackInfo<Value>& args) {
+ TLSWrap* w;
+ ASSIGN_OR_RETURN_UNWRAP(&w, args.Holder());
+ Environment* env = w->env();
+ Local<Value> ret;
+ if (X509Certificate::GetCert(env, w->ssl_).ToLocal(&ret))
+ args.GetReturnValue().Set(ret);
+}
+
void TLSWrap::GetFinished(const FunctionCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
@@ -2051,11 +2074,14 @@ void TLSWrap::Initialize(
env->SetProtoMethodNoSideEffect(t, "getALPNNegotiatedProtocol",
GetALPNNegotiatedProto);
env->SetProtoMethodNoSideEffect(t, "getCertificate", GetCertificate);
+ env->SetProtoMethodNoSideEffect(t, "getX509Certificate", GetX509Certificate);
env->SetProtoMethodNoSideEffect(t, "getCipher", GetCipher);
env->SetProtoMethodNoSideEffect(t, "getEphemeralKeyInfo",
GetEphemeralKeyInfo);
env->SetProtoMethodNoSideEffect(t, "getFinished", GetFinished);
env->SetProtoMethodNoSideEffect(t, "getPeerCertificate", GetPeerCertificate);
+ env->SetProtoMethodNoSideEffect(t, "getPeerX509Certificate",
+ GetPeerX509Certificate);
env->SetProtoMethodNoSideEffect(t, "getPeerFinished", GetPeerFinished);
env->SetProtoMethodNoSideEffect(t, "getProtocol", GetProtocol);
env->SetProtoMethodNoSideEffect(t, "getSession", GetSession);
diff --git a/src/crypto/crypto_tls.h b/src/crypto/crypto_tls.h
index 6bcd3f411c7..6dda31d22be 100644
--- a/src/crypto/crypto_tls.h
+++ b/src/crypto/crypto_tls.h
@@ -184,12 +184,16 @@ class TLSWrap : public AsyncWrap,
static void GetALPNNegotiatedProto(
const v8::FunctionCallbackInfo<v8::Value>& args);
static void GetCertificate(const v8::FunctionCallbackInfo<v8::Value>& args);
+ static void GetX509Certificate(
+ const v8::FunctionCallbackInfo<v8::Value>& args);
static void GetCipher(const v8::FunctionCallbackInfo<v8::Value>& args);
static void GetEphemeralKeyInfo(
const v8::FunctionCallbackInfo<v8::Value>& args);
static void GetFinished(const v8::FunctionCallbackInfo<v8::Value>& args);
static void GetPeerCertificate(
const v8::FunctionCallbackInfo<v8::Value>& args);
+ static void GetPeerX509Certificate(
+ const v8::FunctionCallbackInfo<v8::Value>& args);
static void GetPeerFinished(const v8::FunctionCallbackInfo<v8::Value>& args);
static void GetProtocol(const v8::FunctionCallbackInfo<v8::Value>& args);
static void GetServername(const v8::FunctionCallbackInfo<v8::Value>& args);
diff --git a/src/crypto/crypto_x509.cc b/src/crypto/crypto_x509.cc
index 0ea91bca877..574a3a194de 100644
--- a/src/crypto/crypto_x509.cc
+++ b/src/crypto/crypto_x509.cc
@@ -15,7 +15,6 @@
namespace node {
-using v8::Array;
using v8::ArrayBufferView;
using v8::Context;
using v8::EscapableHandleScope;
@@ -82,6 +81,7 @@ Local<FunctionTemplate> X509Certificate::GetConstructorTemplate(
env->SetProtoMethod(tmpl, "checkPrivateKey", CheckPrivateKey);
env->SetProtoMethod(tmpl, "verify", Verify);
env->SetProtoMethod(tmpl, "toLegacy", ToLegacy);
+ env->SetProtoMethod(tmpl, "getIssuerCert", GetIssuerCert);
env->set_x509_constructor_template(tmpl);
}
return tmpl;
@@ -93,14 +93,16 @@ bool X509Certificate::HasInstance(Environment* env, Local<Object> object) {
MaybeLocal<Object> X509Certificate::New(
Environment* env,
- X509Pointer cert) {
+ X509Pointer cert,
+ STACK_OF(X509)* issuer_chain) {
std::shared_ptr<ManagedX509> mcert(new ManagedX509(std::move(cert)));
- return New(env, std::move(mcert));
+ return New(env, std::move(mcert), issuer_chain);
}
MaybeLocal<Object> X509Certificate::New(
Environment* env,
- std::shared_ptr<ManagedX509> cert) {
+ std::shared_ptr<ManagedX509> cert,
+ STACK_OF(X509)* issuer_chain) {
EscapableHandleScope scope(env->isolate());
Local<Function> ctor;
if (!GetConstructorTemplate(env)->GetFunction(env->context()).ToLocal(&ctor))
@@ -110,7 +112,7 @@ MaybeLocal<Object> X509Certificate::New(
if (!ctor->NewInstance(env->context()).ToLocal(&obj))
return MaybeLocal<Object>();
- new X509Certificate(env, obj, std::move(cert));
+ new X509Certificate(env, obj, std::move(cert), issuer_chain);
return scope.Escape(obj);
}
@@ -122,7 +124,7 @@ MaybeLocal<Object> X509Certificate::GetCert(
if (cert == nullptr)
return MaybeLocal<Object>();
- X509Pointer ptr(cert);
+ X509Pointer ptr(X509_dup(cert));
return New(env, std::move(ptr));
}
@@ -130,16 +132,12 @@ MaybeLocal<Object> X509Certificate::GetPeerCert(
Environment* env,
const SSLPointer& ssl,
GetPeerCertificateFlag flag) {
- EscapableHandleScope scope(env->isolate());
ClearErrorOnReturn clear_error_on_return;
Local<Object> obj;
MaybeLocal<Object> maybe_cert;
bool is_server =
static_cast<int>(flag) & static_cast<int>(GetPeerCertificateFlag::SERVER);
- bool abbreviated =
- static_cast<int>(flag)
- & static_cast<int>(GetPeerCertificateFlag::ABBREVIATED);
X509Pointer cert(is_server ? SSL_get_peer_certificate(ssl.get()) : nullptr);
STACK_OF(X509)* ssl_certs = SSL_get_peer_cert_chain(ssl.get());
@@ -148,23 +146,14 @@ MaybeLocal<Object> X509Certificate::GetPeerCert(
std::vector<Local<Value>> certs;
- if (!cert) cert.reset(sk_X509_value(ssl_certs, 0));
- if (!X509Certificate::New(env, std::move(cert)).ToLocal(&obj))
- return MaybeLocal<Object>();
-
- certs.push_back(obj);
-
- int count = sk_X509_num(ssl_certs);
- if (!abbreviated) {
- for (int i = 0; i < count; i++) {
- cert.reset(X509_dup(sk_X509_value(ssl_certs, i)));
- if (!cert || !X509Certificate::New(env, std::move(cert)).ToLocal(&obj))
- return MaybeLocal<Object>();
- certs.push_back(obj);
- }
+ if (!cert) {
+ cert.reset(sk_X509_value(ssl_certs, 0));
+ sk_X509_delete(ssl_certs, 0);
}
- return scope.Escape(Array::New(env->isolate(), certs.data(), certs.size()));
+ return sk_X509_num(ssl_certs)
+ ? New(env, std::move(cert), ssl_certs)
+ : New(env, std::move(cert));
}
void X509Certificate::Parse(const FunctionCallbackInfo<Value>& args) {
@@ -475,13 +464,32 @@ void X509Certificate::ToLegacy(const FunctionCallbackInfo<Value>& args) {
args.GetReturnValue().Set(ret);
}
+void X509Certificate::GetIssuerCert(const FunctionCallbackInfo<Value>& args) {
+ X509Certificate* cert;
+ ASSIGN_OR_RETURN_UNWRAP(&cert, args.Holder());
+ if (cert->issuer_cert_)
+ args.GetReturnValue().Set(cert->issuer_cert_->object());
+}
+
X509Certificate::X509Certificate(
Environment* env,
Local<Object> object,
- std::shared_ptr<ManagedX509> cert)
+ std::shared_ptr<ManagedX509> cert,
+ STACK_OF(X509)* issuer_chain)
: BaseObject(env, object),
cert_(std::move(cert)) {
MakeWeak();
+
+ if (issuer_chain != nullptr && sk_X509_num(issuer_chain)) {
+ X509Pointer cert(X509_dup(sk_X509_value(issuer_chain, 0)));
+ sk_X509_delete(issuer_chain, 0);
+ Local<Object> obj = sk_X509_num(issuer_chain)
+ ? X509Certificate::New(env, std::move(cert), issuer_chain)
+ .ToLocalChecked()
+ : X509Certificate::New(env, std::move(cert))
+ .ToLocalChecked();
+ issuer_cert_.reset(Unwrap<X509Certificate>(obj));
+ }
}
void X509Certificate::MemoryInfo(MemoryTracker* tracker) const {
diff --git a/src/crypto/crypto_x509.h b/src/crypto/crypto_x509.h
index 4d46e43889b..3bebc8e37d1 100644
--- a/src/crypto/crypto_x509.h
+++ b/src/crypto/crypto_x509.h
@@ -38,7 +38,7 @@ class ManagedX509 : public MemoryRetainer {
class X509Certificate : public BaseObject {
public:
enum class GetPeerCertificateFlag {
- ABBREVIATED,
+ NONE,
SERVER
};
@@ -49,11 +49,13 @@ class X509Certificate : public BaseObject {
static v8::MaybeLocal<v8::Object> New(
Environment* env,
- X509Pointer cert);
+ X509Pointer cert,
+ STACK_OF(X509)* issuer_chain = nullptr);
static v8::MaybeLocal<v8::Object> New(
Environment* env,
- std::shared_ptr<ManagedX509> cert);
+ std::shared_ptr<ManagedX509> cert,
+ STACK_OF(X509)* issuer_chain = nullptr);
static v8::MaybeLocal<v8::Object> GetCert(
Environment* env,
@@ -91,6 +93,7 @@ class X509Certificate : public BaseObject {
static void CheckPrivateKey(const v8::FunctionCallbackInfo<v8::Value>& args);
static void Verify(const v8::FunctionCallbackInfo<v8::Value>& args);
static void ToLegacy(const v8::FunctionCallbackInfo<v8::Value>& args);
+ static void GetIssuerCert(const v8::FunctionCallbackInfo<v8::Value>& args);
X509* get() { return cert_->get(); }
@@ -124,9 +127,11 @@ class X509Certificate : public BaseObject {
X509Certificate(
Environment* env,
v8::Local<v8::Object> object,
- std::shared_ptr<ManagedX509> cert);
+ std::shared_ptr<ManagedX509> cert,
+ STACK_OF(X509)* issuer_chain = nullptr);
std::shared_ptr<ManagedX509> cert_;
+ BaseObjectPtr<X509Certificate> issuer_cert_;
};
} // namespace crypto