diff options
author | James M Snell <jasnell@gmail.com> | 2021-01-26 03:38:51 +0300 |
---|---|---|
committer | Danielle Adams <adamzdanielle@gmail.com> | 2021-02-16 17:11:25 +0300 |
commit | dc84c181c33d92c8bf910d52bbdc37d898d071e4 (patch) | |
tree | d3215763ce696ddfe2a0993612d4bb60b7995ef2 /src | |
parent | 13fe17c4ef548bc6b5808f61c418df1b0214d910 (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.cc | 26 | ||||
-rw-r--r-- | src/crypto/crypto_tls.h | 4 | ||||
-rw-r--r-- | src/crypto/crypto_x509.cc | 60 | ||||
-rw-r--r-- | src/crypto/crypto_x509.h | 13 |
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 |