| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent f5725ca commit 3009980
6 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -2443,5 +2443,30 @@ void UseExtraCaCerts(std::string_view file) { | |||
| 2443 | 2443 | extra_root_certs_file = file; | |
| 2444 | 2444 | } | |
| 2445 | 2445 | ||
| 2446 | + NODE_EXTERN SSL_CTX* GetSSLCtx(Local<Context> context, Local<Value> value) { | ||
| 2447 | + Environment* env = Environment::GetCurrent(context); | ||
| 2448 | + if (env == nullptr) return nullptr; | ||
| 2449 | + | ||
| 2450 | + // TryCatchto swallow any exceptions from Get() (e.g. failing getters) | ||
| 2451 | + v8::TryCatch try_catch(env->isolate()); | ||
| 2452 | + | ||
| 2453 | + // Unwrap the .context property from the JS SecureContext wrapper | ||
| 2454 | + // (as returned by tls.createSecureContext()). | ||
| 2455 | + if (value->IsObject()) { | ||
| 2456 | + Local<Value> inner; | ||
| 2457 | + if (!value.As<v8::Object>() | ||
| 2458 | + ->Get(context, FIXED_ONE_BYTE_STRING(env->isolate(), "context")) | ||
| 2459 | + .ToLocal(&inner)) { | ||
| 2460 | + return nullptr; | ||
| 2461 | + } | ||
| 2462 | + value = inner; | ||
| 2463 | + } | ||
| 2464 | + | ||
| 2465 | + if (!SecureContext::HasInstance(env, value)) return nullptr; | ||
| 2466 | + SecureContext* sc = BaseObject::FromJSObject<SecureContext>(value); | ||
| 2467 | + if (sc == nullptr) return nullptr; | ||
| 2468 | + return sc->ctx().get(); | ||
| 2469 | + } | ||
| 2470 | + | ||
| 2446 | 2471 | } // namespace crypto | |
| 2447 | 2472 | } // namespace node | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -124,6 +124,8 @@ | |||
| 124 | 124 | ||
| 125 | 125 | // Forward-declare libuv loop | |
| 126 | 126 | struct uv_loop_s; | |
| 127 | + struct napi_module; | ||
| 128 | + struct ssl_ctx_st; // Forward declaration of SSL_CTX for OpenSSL. | ||
| 127 | 129 | ||
| 128 | 130 | // Forward-declare these functions now to stop MSVS from becoming | |
| 129 | 131 | // terminally confused when it's done in node_internals.h | |
@@ -1656,6 +1658,20 @@ NODE_DEPRECATED( | |||
| 1656 | 1658 | v8::Local<v8::Object> object, | |
| 1657 | 1659 | v8::Object::Wrappable* wrappable)); | |
| 1658 | 1660 | ||
| 1661 | + namespace crypto { | ||
| 1662 | + | ||
| 1663 | + // Returns the SSL_CTX* from a SecureContext JS object, as returned by | ||
| 1664 | + // tls.createSecureContext(). | ||
| 1665 | + // Returns nullptr if the value is not a SecureContext instance, | ||
| 1666 | + // or if Node.js was built without OpenSSL. | ||
| 1667 | + // | ||
| 1668 | + // The returned pointer is not owned by the caller and must not be freed. | ||
| 1669 | + // It is valid only while the SecureContext JS object remains alive. | ||
| 1670 | + NODE_EXTERN struct ssl_ctx_st* GetSSLCtx(v8::Local<v8::Context> context, | ||
| 1671 | + v8::Local<v8::Value> secure_context); | ||
| 1672 | + | ||
| 1673 | + } // namespace crypto | ||
| 1674 | + | ||
| 1659 | 1675 | } // namespace node | |
| 1660 | 1676 | ||
| 1661 | 1677 | #endif // SRC_NODE_H_ | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -12,6 +12,7 @@ openssl-binding/test: PASS,FLAKY | |||
| 12 | 12 | ||
| 13 | 13 | [$system==ibmi] | |
| 14 | 14 | openssl-binding/test: SKIP | |
| 15 | + openssl-get-ssl-ctx/test: SKIP | ||
| 15 | 16 | openssl-providers/test-default-only-config: SKIP | |
| 16 | 17 | openssl-providers/test-legacy-provider-config: SKIP | |
| 17 | 18 | openssl-providers/test-legacy-provider-inactive-config: SKIP | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,52 @@ | |||
| 1 | + #include <node.h> | ||
| 2 | + #include <openssl/ssl.h> | ||
| 3 | + | ||
| 4 | + namespace { | ||
| 5 | + | ||
| 6 | + // Test: extract SSL_CTX* from a SecureContext object via | ||
| 7 | + // node::crypto::GetSSLCtx. | ||
| 8 | + void GetSSLCtx(const v8::FunctionCallbackInfo<v8::Value>& args) { | ||
| 9 | + v8::Isolate* isolate = args.GetIsolate(); | ||
| 10 | + v8::Local<v8::Context> context = isolate->GetCurrentContext(); | ||
| 11 | + | ||
| 12 | + SSL_CTX* ctx = node::crypto::GetSSLCtx(context, args[0]); | ||
| 13 | + if (ctx == nullptr) { | ||
| 14 | + isolate->ThrowException(v8::Exception::Error( | ||
| 15 | + v8::String::NewFromUtf8( | ||
| 16 | + isolate, "GetSSLCtx returned nullptr for a valid SecureContext") | ||
| 17 | + .ToLocalChecked())); | ||
| 18 | + return; | ||
| 19 | + } | ||
| 20 | + | ||
| 21 | + // Verify the pointer is a valid SSL_CTX by calling an OpenSSL function. | ||
| 22 | + const SSL_METHOD* method = SSL_CTX_get_ssl_method(ctx); | ||
| 23 | + if (method == nullptr) { | ||
| 24 | + isolate->ThrowException(v8::Exception::Error( | ||
| 25 | + v8::String::NewFromUtf8(isolate, | ||
| 26 | + "SSL_CTX_get_ssl_method returned nullptr") | ||
| 27 | + .ToLocalChecked())); | ||
| 28 | + return; | ||
| 29 | + } | ||
| 30 | + | ||
| 31 | + args.GetReturnValue().Set(true); | ||
| 32 | + } | ||
| 33 | + | ||
| 34 | + // Test: passing a non-SecureContext value returns nullptr. | ||
| 35 | + void GetSSLCtxInvalid(const v8::FunctionCallbackInfo<v8::Value>& args) { | ||
| 36 | + v8::Isolate* isolate = args.GetIsolate(); | ||
| 37 | + v8::Local<v8::Context> context = isolate->GetCurrentContext(); | ||
| 38 | + | ||
| 39 | + SSL_CTX* ctx = node::crypto::GetSSLCtx(context, args[0]); | ||
| 40 | + args.GetReturnValue().Set(ctx == nullptr); | ||
| 41 | + } | ||
| 42 | + | ||
| 43 | + void Initialize(v8::Local<v8::Object> exports, | ||
| 44 | + v8::Local<v8::Value> module, | ||
| 45 | + v8::Local<v8::Context> context) { | ||
| 46 | + NODE_SET_METHOD(exports, "getSSLCtx", GetSSLCtx); | ||
| 47 | + NODE_SET_METHOD(exports, "getSSLCtxInvalid", GetSSLCtxInvalid); | ||
| 48 | + } | ||
| 49 | + | ||
| 50 | + } // anonymous namespace | ||
| 51 | + | ||
| 52 | + NODE_MODULE_CONTEXT_AWARE(NODE_GYP_MODULE_NAME, Initialize) | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,29 @@ | |||
| 1 | + { | ||
| 2 | + 'targets': [ | ||
| 3 | + { | ||
| 4 | + 'target_name': 'binding', | ||
| 5 | + 'includes': ['../common.gypi'], | ||
| 6 | + 'conditions': [ | ||
| 7 | + ['node_use_openssl=="true"', { | ||
| 8 | + 'conditions': [ | ||
| 9 | + ['OS in "aix os400"', { | ||
| 10 | + 'variables': { | ||
| 11 | + # Used to differentiate `AIX` and `OS400`(IBM i). | ||
| 12 | + 'aix_variant_name': '<!(uname -s)', | ||
| 13 | + }, | ||
| 14 | + 'conditions': [ | ||
| 15 | + [ '"<(aix_variant_name)"!="OS400"', { # Not `OS400`(IBM i) | ||
| 16 | + 'sources': ['binding.cc'], | ||
| 17 | + 'include_dirs': ['../../../deps/openssl/openssl/include'], | ||
| 18 | + }], | ||
| 19 | + ], | ||
| 20 | + }, { | ||
| 21 | + 'sources': ['binding.cc'], | ||
| 22 | + 'include_dirs': ['../../../deps/openssl/openssl/include'], | ||
| 23 | + }], | ||
| 24 | + ], | ||
| 25 | + }], | ||
| 26 | + ], | ||
| 27 | + }, | ||
| 28 | + ], | ||
| 29 | + } | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,49 @@ | |||
| 1 | + 'use strict'; | ||
| 2 | + const common = require('../../common'); | ||
| 3 | + if (!common.hasCrypto) | ||
| 4 | + common.skip('missing crypto'); | ||
| 5 | + | ||
| 6 | + const assert = require('assert'); | ||
| 7 | + const tls = require('tls'); | ||
| 8 | + const binding = require(`./build/${common.buildType}/binding`); | ||
| 9 | + | ||
| 10 | + // Test 1: Pass a SecureContext to getSSLCtx. | ||
| 11 | + { | ||
| 12 | + const ctx = tls.createSecureContext(); | ||
| 13 | + assert.strictEqual(binding.getSSLCtx(ctx), true); | ||
| 14 | + } | ||
| 15 | + | ||
| 16 | + // Test 2: Passing a non-SecureContext should return nullptr. | ||
| 17 | + { | ||
| 18 | + assert.strictEqual(binding.getSSLCtxInvalid({}), true); | ||
| 19 | + } | ||
| 20 | + | ||
| 21 | + // Test 3: Passing a number should return nullptr. | ||
| 22 | + { | ||
| 23 | + assert.strictEqual(binding.getSSLCtxInvalid(42), true); | ||
| 24 | + } | ||
| 25 | + | ||
| 26 | + // Test 4: Passing undefined should return nullptr. | ||
| 27 | + { | ||
| 28 | + assert.strictEqual(binding.getSSLCtxInvalid(undefined), true); | ||
| 29 | + } | ||
| 30 | + | ||
| 31 | + // Test 5: Passing null should return nullptr. | ||
| 32 | + { | ||
| 33 | + assert.strictEqual(binding.getSSLCtxInvalid(null), true); | ||
| 34 | + } | ||
| 35 | + | ||
| 36 | + // Test 6: An object with a non-SecureContext .context property should return | ||
| 37 | + // nullptr. | ||
| 38 | + { | ||
| 39 | + assert.strictEqual(binding.getSSLCtxInvalid({ context: 'not a context' }), true); | ||
| 40 | + } | ||
| 41 | + | ||
| 42 | + // Test 7: An object with a throwing .context getter should return nullptr | ||
| 43 | + // without propagating the exception. | ||
| 44 | + { | ||
| 45 | + const obj = { | ||
| 46 | + get context() { throw new Error('getter threw'); }, | ||
| 47 | + }; | ||
| 48 | + assert.strictEqual(binding.getSSLCtxInvalid(obj), true); | ||
| 49 | + } | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments