| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent ec56cbe commit 1ed0c77
4 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -192,6 +192,10 @@ circumstance of why the error occurred. `Error` objects capture a "stack trace" | |||
| 192 | 192 | detailing the point in the code at which the `Error` was instantiated, and may | |
| 193 | 193 | provide a text description of the error. | |
| 194 | 194 | ||
| 195 | + For crypto only, `Error` objects will include the OpenSSL error stack in a | ||
| 196 | + separate property called `opensslErrorStack` if it is available when the error | ||
| 197 | + is thrown. | ||
| 198 | + | ||
| 195 | 199 | All errors generated by Node.js, including all System and JavaScript errors, | |
| 196 | 200 | will either be instances of, or inherit from, the `Error` class. | |
| 197 | 201 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -225,6 +225,7 @@ class ModuleWrap; | |||
| 225 | 225 | V(onstreamclose_string, "onstreamclose") \ | |
| 226 | 226 | V(ontrailers_string, "ontrailers") \ | |
| 227 | 227 | V(onwrite_string, "onwrite") \ | |
| 228 | + V(openssl_error_stack, "opensslErrorStack") \ | ||
| 228 | 229 | V(output_string, "output") \ | |
| 229 | 230 | V(order_string, "order") \ | |
| 230 | 231 | V(owner_string, "owner") \ | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -255,13 +255,65 @@ void ThrowCryptoError(Environment* env, | |||
| 255 | 255 | unsigned long err, // NOLINT(runtime/int) | |
| 256 | 256 | const char* default_message = nullptr) { | |
| 257 | 257 | HandleScope scope(env->isolate()); | |
| 258 | + Local<String> message; | ||
| 259 | + | ||
| 258 | 260 | if (err != 0 || default_message == nullptr) { | |
| 259 | 261 | char errmsg[128] = { 0 }; | |
| 260 | 262 | ERR_error_string_n(err, errmsg, sizeof(errmsg)); | |
| 261 | - env->ThrowError(errmsg); | ||
| 263 | + message = String::NewFromUtf8(env->isolate(), errmsg, | ||
| 264 | + v8::NewStringType::kNormal) | ||
| 265 | + .ToLocalChecked(); | ||
| 262 | 266 | } else { | |
| 263 | - env->ThrowError(default_message); | ||
| 267 | + message = String::NewFromUtf8(env->isolate(), default_message, | ||
| 268 | + v8::NewStringType::kNormal) | ||
| 269 | + .ToLocalChecked(); | ||
| 270 | + } | ||
| 271 | + | ||
| 272 | + Local<Value> exception_v = Exception::Error(message); | ||
| 273 | + CHECK(!exception_v.IsEmpty()); | ||
| 274 | + Local<Object> exception = exception_v.As<Object>(); | ||
| 275 | + ERR_STATE* es = ERR_get_state(); | ||
| 276 | + | ||
| 277 | + if (es->bottom != es->top) { | ||
| 278 | + Local<Array> error_stack = Array::New(env->isolate()); | ||
| 279 | + int top = es->top; | ||
| 280 | + | ||
| 281 | + // Build the error_stack array to be added to opensslErrorStack property. | ||
| 282 | + for (unsigned int i = 0; es->bottom != es->top;) { | ||
| 283 | + unsigned long err_buf = es->err_buffer[es->top]; // NOLINT(runtime/int) | ||
| 284 | + // Only add error string if there is valid err_buffer. | ||
| 285 | + if (err_buf) { | ||
| 286 | + char tmp_str[256]; | ||
| 287 | + ERR_error_string_n(err_buf, tmp_str, sizeof(tmp_str)); | ||
| 288 | + error_stack->Set(env->context(), i, | ||
| 289 | + String::NewFromUtf8(env->isolate(), tmp_str, | ||
| 290 | + v8::NewStringType::kNormal) | ||
| 291 | + .ToLocalChecked()).FromJust(); | ||
| 292 | + // Only increment if we added to error_stack. | ||
| 293 | + i++; | ||
| 294 | + } | ||
| 295 | + | ||
| 296 | + // Since the ERR_STATE is a ring buffer, we need to use modular | ||
| 297 | + // arithmetic to loop back around in the case where bottom is after top. | ||
| 298 | + // Using ERR_NUM_ERRORS macro defined in openssl. | ||
| 299 | + es->top = (((es->top - 1) % ERR_NUM_ERRORS) + ERR_NUM_ERRORS) % | ||
| 300 | + ERR_NUM_ERRORS; | ||
| 301 | + } | ||
| 302 | + | ||
| 303 | + // Restore top. | ||
| 304 | + es->top = top; | ||
| 305 | + | ||
| 306 | + // Add the opensslErrorStack property to the exception object. | ||
| 307 | + // The new property will look like the following: | ||
| 308 | + // opensslErrorStack: [ | ||
| 309 | + // 'error:0906700D:PEM routines:PEM_ASN1_read_bio:ASN1 lib', | ||
| 310 | + // 'error:0D07803A:asn1 encoding routines:ASN1_ITEM_EX_D2I:nested asn1 err' | ||
| 311 | + // ] | ||
| 312 | + exception->Set(env->context(), env->openssl_error_stack(), error_stack) | ||
| 313 | + .FromJust(); | ||
| 264 | 314 | } | |
| 315 | + | ||
| 316 | + env->isolate()->ThrowException(exception); | ||
| 265 | 317 | } | |
| 266 | 318 | ||
| 267 | 319 | ||
@@ -4316,8 +4368,6 @@ SignBase::Error Verify::VerifyFinal(const char* key_pem, | |||
| 4316 | 4368 | if (!initialised_) | |
| 4317 | 4369 | return kSignNotInitialised; | |
| 4318 | 4370 | ||
| 4319 | - ClearErrorOnReturn clear_error_on_return; | ||
| 4320 | - | ||
| 4321 | 4371 | EVP_PKEY* pkey = nullptr; | |
| 4322 | 4372 | BIO* bp = nullptr; | |
| 4323 | 4373 | X509* x509 = nullptr; | |
@@ -4406,6 +4456,8 @@ SignBase::Error Verify::VerifyFinal(const char* key_pem, | |||
| 4406 | 4456 | void Verify::VerifyFinal(const FunctionCallbackInfo<Value>& args) { | |
| 4407 | 4457 | Environment* env = Environment::GetCurrent(args); | |
| 4408 | 4458 | ||
| 4459 | + ClearErrorOnReturn clear_error_on_return; | ||
| 4460 | + | ||
| 4409 | 4461 | Verify* verify; | |
| 4410 | 4462 | ASSIGN_OR_RETURN_UNWRAP(&verify, args.Holder()); | |
| 4411 | 4463 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -46,7 +46,14 @@ assert.throws(function() { | |||
| 46 | 46 | const context = credentials.context; | |
| 47 | 47 | const notcontext = { setOptions: context.setOptions, setKey: context.setKey }; | |
| 48 | 48 | tls.createSecureContext({ secureOptions: 1 }, notcontext); | |
| 49 | - }, /^TypeError: Illegal invocation$/); | ||
| 49 | + }, (err) => { | ||
| 50 | + // Throws TypeError, so there is no opensslErrorStack property. | ||
| 51 | + if ((err instanceof Error) && | ||
| 52 | + /^TypeError: Illegal invocation$/.test(err) && | ||
| 53 | + err.opensslErrorStack === undefined) { | ||
| 54 | + return true; | ||
| 55 | + } | ||
| 56 | + }); | ||
| 50 | 57 | ||
| 51 | 58 | // PFX tests | |
| 52 | 59 | assert.doesNotThrow(function() { | |
@@ -55,15 +62,36 @@ assert.doesNotThrow(function() { | |||
| 55 | 62 | ||
| 56 | 63 | assert.throws(function() { | |
| 57 | 64 | tls.createSecureContext({ pfx: certPfx }); | |
| 58 | - }, /^Error: mac verify failure$/); | ||
| 65 | + }, (err) => { | ||
| 66 | + // Throws general Error, so there is no opensslErrorStack property. | ||
| 67 | + if ((err instanceof Error) && | ||
| 68 | + /^Error: mac verify failure$/.test(err) && | ||
| 69 | + err.opensslErrorStack === undefined) { | ||
| 70 | + return true; | ||
| 71 | + } | ||
| 72 | + }); | ||
| 59 | 73 | ||
| 60 | 74 | assert.throws(function() { | |
| 61 | 75 | tls.createSecureContext({ pfx: certPfx, passphrase: 'test' }); | |
| 62 | - }, /^Error: mac verify failure$/); | ||
| 76 | + }, (err) => { | ||
| 77 | + // Throws general Error, so there is no opensslErrorStack property. | ||
| 78 | + if ((err instanceof Error) && | ||
| 79 | + /^Error: mac verify failure$/.test(err) && | ||
| 80 | + err.opensslErrorStack === undefined) { | ||
| 81 | + return true; | ||
| 82 | + } | ||
| 83 | + }); | ||
| 63 | 84 | ||
| 64 | 85 | assert.throws(function() { | |
| 65 | 86 | tls.createSecureContext({ pfx: 'sample', passphrase: 'test' }); | |
| 66 | - }, /^Error: not enough data$/); | ||
| 87 | + }, (err) => { | ||
| 88 | + // Throws general Error, so there is no opensslErrorStack property. | ||
| 89 | + if ((err instanceof Error) && | ||
| 90 | + /^Error: not enough data$/.test(err) && | ||
| 91 | + err.opensslErrorStack === undefined) { | ||
| 92 | + return true; | ||
| 93 | + } | ||
| 94 | + }); | ||
| 67 | 95 | ||
| 68 | 96 | ||
| 69 | 97 | // update() should only take buffers / strings | |
@@ -135,23 +163,62 @@ testImmutability(crypto.getCurves); | |||
| 135 | 163 | // throw, not assert in C++ land. | |
| 136 | 164 | assert.throws(function() { | |
| 137 | 165 | crypto.createCipher('aes192', 'test').update('0', 'hex'); | |
| 138 | - }, common.hasFipsCrypto ? /not supported in FIPS mode/ : /Bad input string/); | ||
| 166 | + }, (err) => { | ||
| 167 | + const errorMessage = | ||
| 168 | + common.hasFipsCrypto ? /not supported in FIPS mode/ : /Bad input string/; | ||
| 169 | + // Throws general Error, so there is no opensslErrorStack property. | ||
| 170 | + if ((err instanceof Error) && | ||
| 171 | + errorMessage.test(err) && | ||
| 172 | + err.opensslErrorStack === undefined) { | ||
| 173 | + return true; | ||
| 174 | + } | ||
| 175 | + }); | ||
| 139 | 176 | ||
| 140 | 177 | assert.throws(function() { | |
| 141 | 178 | crypto.createDecipher('aes192', 'test').update('0', 'hex'); | |
| 142 | - }, common.hasFipsCrypto ? /not supported in FIPS mode/ : /Bad input string/); | ||
| 179 | + }, (err) => { | ||
| 180 | + const errorMessage = | ||
| 181 | + common.hasFipsCrypto ? /not supported in FIPS mode/ : /Bad input string/; | ||
| 182 | + // Throws general Error, so there is no opensslErrorStack property. | ||
| 183 | + if ((err instanceof Error) && | ||
| 184 | + errorMessage.test(err) && | ||
| 185 | + err.opensslErrorStack === undefined) { | ||
| 186 | + return true; | ||
| 187 | + } | ||
| 188 | + }); | ||
| 143 | 189 | ||
| 144 | 190 | assert.throws(function() { | |
| 145 | 191 | crypto.createHash('sha1').update('0', 'hex'); | |
| 146 | - }, /^TypeError: Bad input string$/); | ||
| 192 | + }, (err) => { | ||
| 193 | + // Throws TypeError, so there is no opensslErrorStack property. | ||
| 194 | + if ((err instanceof Error) && | ||
| 195 | + /^TypeError: Bad input string$/.test(err) && | ||
| 196 | + err.opensslErrorStack === undefined) { | ||
| 197 | + return true; | ||
| 198 | + } | ||
| 199 | + }); | ||
| 147 | 200 | ||
| 148 | 201 | assert.throws(function() { | |
| 149 | 202 | crypto.createSign('SHA1').update('0', 'hex'); | |
| 150 | - }, /^TypeError: Bad input string$/); | ||
| 203 | + }, (err) => { | ||
| 204 | + // Throws TypeError, so there is no opensslErrorStack property. | ||
| 205 | + if ((err instanceof Error) && | ||
| 206 | + /^TypeError: Bad input string$/.test(err) && | ||
| 207 | + err.opensslErrorStack === undefined) { | ||
| 208 | + return true; | ||
| 209 | + } | ||
| 210 | + }); | ||
| 151 | 211 | ||
| 152 | 212 | assert.throws(function() { | |
| 153 | 213 | crypto.createVerify('SHA1').update('0', 'hex'); | |
| 154 | - }, /^TypeError: Bad input string$/); | ||
| 214 | + }, (err) => { | ||
| 215 | + // Throws TypeError, so there is no opensslErrorStack property. | ||
| 216 | + if ((err instanceof Error) && | ||
| 217 | + /^TypeError: Bad input string$/.test(err) && | ||
| 218 | + err.opensslErrorStack === undefined) { | ||
| 219 | + return true; | ||
| 220 | + } | ||
| 221 | + }); | ||
| 155 | 222 | ||
| 156 | 223 | assert.throws(function() { | |
| 157 | 224 | const priv = [ | |
@@ -164,7 +231,13 @@ assert.throws(function() { | |||
| 164 | 231 | '' | |
| 165 | 232 | ].join('\n'); | |
| 166 | 233 | crypto.createSign('SHA256').update('test').sign(priv); | |
| 167 | - }, /digest too big for rsa key$/); | ||
| 234 | + }, (err) => { | ||
| 235 | + if ((err instanceof Error) && | ||
| 236 | + /digest too big for rsa key$/.test(err) && | ||
| 237 | + err.opensslErrorStack === undefined) { | ||
| 238 | + return true; | ||
| 239 | + } | ||
| 240 | + }); | ||
| 168 | 241 | ||
| 169 | 242 | assert.throws(function() { | |
| 170 | 243 | // The correct header inside `test_bad_rsa_privkey.pem` should have been | |
@@ -180,14 +253,31 @@ assert.throws(function() { | |||
| 180 | 253 | 'ascii'); | |
| 181 | 254 | // this would inject errors onto OpenSSL's error stack | |
| 182 | 255 | crypto.createSign('sha1').sign(sha1_privateKey); | |
| 183 | - }, /asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag/); | ||
| 256 | + }, (err) => { | ||
| 257 | + // Throws crypto error, so there is an opensslErrorStack property. | ||
| 258 | + // The openSSL stack should have content. | ||
| 259 | + if ((err instanceof Error) && | ||
| 260 | + /asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag/.test(err) && | ||
| 261 | + err.opensslErrorStack !== undefined && | ||
| 262 | + Array.isArray(err.opensslErrorStack) && | ||
| 263 | + err.opensslErrorStack.length > 0) { | ||
| 264 | + return true; | ||
| 265 | + } | ||
| 266 | + }); | ||
| 184 | 267 | ||
| 185 | 268 | // Make sure memory isn't released before being returned | |
| 186 | 269 | console.log(crypto.randomBytes(16)); | |
| 187 | 270 | ||
| 188 | 271 | assert.throws(function() { | |
| 189 | 272 | tls.createSecureContext({ crl: 'not a CRL' }); | |
| 190 | - }, /^Error: Failed to parse CRL$/); | ||
| 273 | + }, (err) => { | ||
| 274 | + // Throws general error, so there is no opensslErrorStack property. | ||
| 275 | + if ((err instanceof Error) && | ||
| 276 | + /^Error: Failed to parse CRL$/.test(err) && | ||
| 277 | + err.opensslErrorStack === undefined) { | ||
| 278 | + return true; | ||
| 279 | + } | ||
| 280 | + }); | ||
| 191 | 281 | ||
| 192 | 282 | /** | |
| 193 | 283 | * Check if the stream function uses utf8 as a default encoding. | |
| Back | FazBrowse Home | New Git URL |
0 commit comments