| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -547,6 +547,12 @@ description are taken from deps/openssl/openssl/crypto/x509/x509_txt.c | |||
| 547 | 547 | * `'CERT_REJECTED'`: Certificate rejected. | |
| 548 | 548 | * `'HOSTNAME_MISMATCH'`: Hostname mismatch. | |
| 549 | 549 | ||
| 550 | + When certificate errors like `UNABLE_TO_VERIFY_LEAF_SIGNATURE`, | ||
| 551 | + `DEPTH_ZERO_SELF_SIGNED_CERT`, or `UNABLE_TO_GET_ISSUER_CERT` occur, Node.js | ||
| 552 | + appends a hint suggesting that if the root CA is installed locally, | ||
| 553 | + try running with the `--use-system-ca` flag to direct developers towards a | ||
| 554 | + secure solution, to prevent unsafe workarounds. | ||
| 555 | + | ||
| 550 | 556 | ## Class: `tls.CryptoStream` | |
| 551 | 557 | ||
| 552 | 558 | <!-- YAML | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -53,8 +53,20 @@ SSLSessionPointer GetTLSSession(const unsigned char* buf, size_t length) { | |||
| 53 | 53 | } | |
| 54 | 54 | ||
| 55 | 55 | MaybeLocal<Value> GetValidationErrorReason(Environment* env, int err) { | |
| 56 | - auto reason = X509Pointer::ErrorReason(err).value_or(""); | ||
| 56 | + auto reason = std::string(X509Pointer::ErrorReason(err).value_or("")); | ||
| 57 | 57 | if (reason == "") return Undefined(env->isolate()); | |
| 58 | + | ||
| 59 | + // Suggest --use-system-ca if the error indicates a certificate issue | ||
| 60 | + bool suggest_system_ca = | ||
| 61 | + (err == X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE) || | ||
| 62 | + (err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) || | ||
| 63 | + ((err == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT) && | ||
| 64 | + !per_process::cli_options->use_system_ca); | ||
| 65 | + | ||
| 66 | + if (suggest_system_ca) { | ||
| 67 | + reason.append("; if the root CA is installed locally, " | ||
| 68 | + "try running Node.js with --use-system-ca"); | ||
| 69 | + } | ||
| 58 | 70 | return OneByteString(env->isolate(), reason); | |
| 59 | 71 | } | |
| 60 | 72 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -17,7 +17,7 @@ const options = { | |||
| 17 | 17 | ||
| 18 | 18 | const expectedHeader = /^HTTP\/1\.1 200 OK/; | |
| 19 | 19 | const expectedBody = /hello world\n/; | |
| 20 | - const expectCertError = /^Error: unable to verify the first certificate$/; | ||
| 20 | + const expectCertError = /^UNABLE_TO_VERIFY_LEAF_SIGNATURE$/; | ||
| 21 | 21 | ||
| 22 | 22 | const checkRequest = (socket, server) => { | |
| 23 | 23 | let result = ''; | |
@@ -112,7 +112,7 @@ function createServer() { | |||
| 112 | 112 | const options = null; | |
| 113 | 113 | const socket = agent.createConnection(port, host, options); | |
| 114 | 114 | socket.on('error', common.mustCall((e) => { | |
| 115 | - assert.match(e.toString(), expectCertError); | ||
| 115 | + assert.match(e.code, expectCertError); | ||
| 116 | 116 | server.close(); | |
| 117 | 117 | })); | |
| 118 | 118 | })); | |
@@ -127,7 +127,7 @@ function createServer() { | |||
| 127 | 127 | const options = undefined; | |
| 128 | 128 | const socket = agent.createConnection(port, host, options); | |
| 129 | 129 | socket.on('error', common.mustCall((e) => { | |
| 130 | - assert.match(e.toString(), expectCertError); | ||
| 130 | + assert.match(e.code, expectCertError); | ||
| 131 | 131 | server.close(); | |
| 132 | 132 | })); | |
| 133 | 133 | })); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -34,7 +34,7 @@ connect({ | |||
| 34 | 34 | server: serverOptions, | |
| 35 | 35 | }, common.mustCall((err, pair, cleanup) => { | |
| 36 | 36 | assert(err); | |
| 37 | - assert.strictEqual(err.message, 'unable to verify the first certificate'); | ||
| 37 | + assert.strictEqual(err.code, 'UNABLE_TO_VERIFY_LEAF_SIGNATURE'); | ||
| 38 | 38 | cleanup(); | |
| 39 | 39 | ||
| 40 | 40 | // This time it should connect because contextWithCert includes the needed CA | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -40,6 +40,5 @@ tls.createServer({ key, cert }).on('connection', common.mustCall(function() { | |||
| 40 | 40 | const options = { port: this.address().port, rejectUnauthorized: true }; | |
| 41 | 41 | tls.connect(options).on('error', common.mustCall(function(err) { | |
| 42 | 42 | assert.strictEqual(err.code, 'UNABLE_TO_VERIFY_LEAF_SIGNATURE'); | |
| 43 | - assert.strictEqual(err.message, 'unable to verify the first certificate'); | ||
| 44 | 43 | })); | |
| 45 | 44 | })); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -13,7 +13,6 @@ const assert = require('assert'); | |||
| 13 | 13 | const events = require('events'); | |
| 14 | 14 | const https = require('https'); | |
| 15 | 15 | const timers = require('timers/promises'); | |
| 16 | - const { hasOpenSSL3 } = require('../common/crypto'); | ||
| 17 | 16 | const fixtures = require('../common/fixtures'); | |
| 18 | 17 | const credentialOptions = [ | |
| 19 | 18 | { | |
@@ -57,17 +56,18 @@ server.listen(0, common.mustCall(() => { | |||
| 57 | 56 | ||
| 58 | 57 | server.setSecureContext(credentialOptions[1]); | |
| 59 | 58 | firstResponse.write('request-'); | |
| 60 | - const errorMessageRegex = hasOpenSSL3 ? | ||
| 61 | - /^Error: self-signed certificate$/ : | ||
| 62 | - /^Error: self signed certificate$/; | ||
| 63 | - await assert.rejects(makeRequest(port, 3), errorMessageRegex); | ||
| 59 | + await assert.rejects(makeRequest(port, 3), { | ||
| 60 | + code: 'DEPTH_ZERO_SELF_SIGNED_CERT', | ||
| 61 | + }); | ||
| 64 | 62 | ||
| 65 | 63 | server.setSecureContext(credentialOptions[0]); | |
| 66 | 64 | assert.strictEqual(await makeRequest(port, 4), 'success'); | |
| 67 | 65 | ||
| 68 | 66 | server.setSecureContext(credentialOptions[1]); | |
| 69 | 67 | firstResponse.end('fun!'); | |
| 70 | - await assert.rejects(makeRequest(port, 5), errorMessageRegex); | ||
| 68 | + await assert.rejects(makeRequest(port, 5), { | ||
| 69 | + code: 'DEPTH_ZERO_SELF_SIGNED_CERT', | ||
| 70 | + }); | ||
| 71 | 71 | ||
| 72 | 72 | assert.strictEqual(await firstRequest, 'multi-request-success-fun!'); | |
| 73 | 73 | server.close(); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -10,11 +10,11 @@ const { | |||
| 10 | 10 | } = require(fixtures.path('tls-connect')); | |
| 11 | 11 | ||
| 12 | 12 | test(undefined, (err) => { | |
| 13 | - assert.strictEqual(err.message, 'unable to verify the first certificate'); | ||
| 13 | + assert.strictEqual(err.code, 'UNABLE_TO_VERIFY_LEAF_SIGNATURE'); | ||
| 14 | 14 | }); | |
| 15 | 15 | ||
| 16 | 16 | test({}, (err) => { | |
| 17 | - assert.strictEqual(err.message, 'unable to verify the first certificate'); | ||
| 17 | + assert.strictEqual(err.code, 'UNABLE_TO_VERIFY_LEAF_SIGNATURE'); | ||
| 18 | 18 | }); | |
| 19 | 19 | ||
| 20 | 20 | test( | |
@@ -30,8 +30,8 @@ test( | |||
| 30 | 30 | test( | |
| 31 | 31 | { secureContext: tls.createSecureContext(), ca: keys.agent1.ca }, | |
| 32 | 32 | (err) => { | |
| 33 | - assert.strictEqual(err.message, | ||
| 34 | - 'unable to verify the first certificate'); | ||
| 33 | + assert.strictEqual(err.code, | ||
| 34 | + 'UNABLE_TO_VERIFY_LEAF_SIGNATURE'); | ||
| 35 | 35 | }); | |
| 36 | 36 | ||
| 37 | 37 | function test(client, callback) { | |
@@ -42,7 +42,7 @@ function test(client, callback) { | |||
| 42 | 42 | cert: keys.agent1.cert, | |
| 43 | 43 | }, | |
| 44 | 44 | }, function(err, pair, cleanup) { | |
| 45 | - assert.strictEqual(err.message, 'unable to verify the first certificate'); | ||
| 45 | + assert.strictEqual(err.code, 'UNABLE_TO_VERIFY_LEAF_SIGNATURE'); | ||
| 46 | 46 | let recv = ''; | |
| 47 | 47 | pair.server.server.once('secureConnection', common.mustCall((conn) => { | |
| 48 | 48 | conn.on('data', (data) => recv += data); | |
| Back | FazBrowse Home | New Git URL |
0 commit comments