-
Notifications
You must be signed in to change notification settings - Fork 144
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve error reporting in JsThemis #384
Conversation
Add some functions to help with error reporting. They provided unified error message format and convert Themis status code into human-readable strings. Secure Session and Secure Comparator code are handled separately because some of their values overlap with generic codes.
Keys and messages must be non-empty. Themis does check for that but it returns a generic 'invalid parameter' error. Perform early checks and report more accurate errors. Furthermore, check the argument count and their types and report appropriate errors as well. Otherwise we risk crashing node.js process due to assertion failure in node::Buffer::Data().
You can consider this WIP, but the new GitHub feature does not seem to work for us for some reason. I plan to add more error checks to other places as well (Secure Cell and Session also do not like empty inputs, as I recall). The error messages are changed from gerund (failed decrypting) to infinitive (failed to decrypt) so that they are more closely related to method names. For example, the method is called |
@@ -45,6 +46,21 @@ namespace jsthemis { | |||
|
|||
void SecureMessage::New(const Nan::FunctionCallbackInfo<v8::Value>& args) { | |||
if (args.IsConstructCall()) { | |||
if(args.Length()<2){ | |||
ThrowError("Secure Message constructor", THEMIS_INVALID_PARAMETER, "missing private and public key"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what about to move these strings with error description to error.h and store them as constants accessible from client's code? it helps to:
- use 1 constant name and value for 1+ usage as a description
- change text in one place for all usages
- compare error string from client's code and to allow distinguish one error from other (THEMIS_INVALID_PARAMETER was returned for public or private key)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mmm... I'm not really a fan of storing developer-visible human-readable strings in separate files far from their actual usage because as a developer I'd rather see "missing private and public key"
in the code immediately where the error is reported rather than some cryptic constant THEMIS_SECURE_MESSAGE_ARGUMENT_COUNT_KEYS
. (Error codes are a different story.)
If I have an error message then grepping for its substrings will lead directly to the source code rather than to the errors.hpp
where I'd have to do another search for the intermediate constant usage.
I also don't imagine our users handling these errors based on human-readable strings. That's a bad practice. If anything, I'd export all those themis_status_t
constants and added a proper exception type with some status
property which then can be programmatically compared to error code constants.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't like to distinguish error types by string literals too but it's okay to compare some constant values if environment doesn't have any way to use explicit user's exception. as I understand now we return general Exception with some error message - https://github.com/cossacklabs/themis/pull/384/files#diff-55a946083bac69602385c43c0a35e717R83
How user can check in runtime that this error related to incorrect/empty private key and create custom message for user without pass error from our library as is? for example
try {
// use secure message with invalid private key
} catch (err) {
if err.message == jsthemis.INVALID_PRIVATE_KEY {
alert('you uploaded empty file for private key')
}
}
instead
try {
// use secure message with invalid private key
} catch (err) {
alert(err.message); // message == 'secure message: invalid parameter'
}
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Uh... well... currently this is impossible to do consistently with any wrapper in any language. The core library (at best) reports THEMIS_INVALID_PARAMETER and then the user code has to check itself which parameter is invalid, why it is so, and maybe show an appropriate message to the end user in their preferred language.
If machine-readable errors are important I'd suggest to plan a more broad improvement starting from the core: introduce new error codes like THEMIS_INVALID_PRIVATE_KEY, start using them in the core code instead of generic THEMIS_INVALID_PARAMETER, and then update the error reporting across language wrappers. That way we'd be consistent with error reporting.
There's a number of an open questions there. For example, do we need more detailed codes for various reasons why the private key can be invalid? It can be empty, malformed, valid but of unexpected type, does not match the public key, etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As for this PR, I'd rather not export any new API unless we're sure that it's the right thing and going to support it.
Currently the users of JsThemis do not have an official blessed way to distinguish between Themis errors. However, as developers they may read the documentation, read the error messages they observe during testing, and do something about that on their application level. This PR does not change that fundamentally, but it improves the error messages which makes it a bit easier for developers to guess what's wrong with the way they use Themis.
I think that comparing human-readable error messages is not a good API and we should not start supporting it since 0.11. I'd suggest to keep the current status quo, and maybe introduce a better support for error handling in 0.12+
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I support @Lagovas – it's important to improve text messages, but it would be nice to allow users to distinguish errors by checking error code / error name as well.
From what I see, it's typical for NaN to throw errors as strings only:
https://github.com/nodejs/nan/blob/master/test/cpp/error.cpp
However can we propagate error number as well?
Maybe smth similar to
static NAN_INLINE(void NanThrowError(
const char *msg,
const int errorNumber)) {
NanThrowError(NanError(msg, errorNumber));
}
(inspired by http://res.wisedu.com/FS/mockserver/node_modules/nan/nan.h and https://git.visteon.com/external/nan/commit/c1ab008e7d9151a133ad7cd84a8443409e471dcb#7de2fb2c0f5228eb2fbf733d63d9d3203ec08371_350_357)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, it seems that we can use this approach. Then the exception will have an additional property code
which will contain Themis error code. We should also export error code constants from our module. This should make it possible to handle errors like this:
try {
// use Themis
}
catch (e) {
if (e.code == jsthemis.INVALID_PARAMETER) {
// handle error
}
}
Rename "empty" variable to use distinct names across the tests because this "this" thing in JavaScript is magic.
@@ -45,6 +46,21 @@ namespace jsthemis { | |||
|
|||
void SecureMessage::New(const Nan::FunctionCallbackInfo<v8::Value>& args) { | |||
if (args.IsConstructCall()) { | |||
if(args.Length()<2){ | |||
ThrowError("Secure Message constructor", THEMIS_INVALID_PARAMETER, "missing private and public key"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I support @Lagovas – it's important to improve text messages, but it would be nice to allow users to distinguish errors by checking error code / error name as well.
From what I see, it's typical for NaN to throw errors as strings only:
https://github.com/nodejs/nan/blob/master/test/cpp/error.cpp
However can we propagate error number as well?
Maybe smth similar to
static NAN_INLINE(void NanThrowError(
const char *msg,
const int errorNumber)) {
NanThrowError(NanError(msg, errorNumber));
}
(inspired by http://res.wisedu.com/FS/mockserver/node_modules/nan/nan.h and https://git.visteon.com/external/nan/commit/c1ab008e7d9151a133ad7cd84a8443409e471dcb#7de2fb2c0f5228eb2fbf733d63d9d3203ec08371_350_357)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really love new wording and these checks!
Suggested few improvements here and there
Co-Authored-By: ilammy <[email protected]>
Co-Authored-By: ilammy <[email protected]>
Use more descriptive error messages which suggestions on how to fix the error. Drop the superfluous error code parameter which is always the same. We're going to use these short forms only for parameter validation anyway.
We're going to improve the exception error messages so remove all these hardcoded "invalid parameter" strings for now. We'll replace that with some error verification callback later.
If we have a status code, add it as a "code" property to the Error object we throw. Verify the code in tests where appropriate.
@vixentael, I've updated some error messages to include more instructions and information. @Lagovas, @vixentael, error objects now contain Please review the list and naming: themis/src/wrappers/themis/jsthemis/errors.cpp Lines 30 to 43 in 27fe0dc
This is new API surface and we will have to live with these names later. I did not export all errors, only the ones which are likely to be of some use (e.g., THEMIS_SSESSION_SEND_OUTPUT_TO_PEER is not exported as it should not be visible to the users). |
Add THEMIS_INVALID_PARAMETER status code to all early parameter checks that we perform. Now all Themis errors will have a "code" property. Rename the helper function accordinly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great job!
I really like how useful error messages became
This should be it. I have added the same checks to Secure Session and Secure Comparator API where appropriate. Now (I hope) all JsThemis functions validate their argument count, types, and values. It was a surprise, but key pair construction required checks as well. It was possible to construct a key pair with empty private or public keys, but the key pairs are useful only for Secure Messages where both components have to be non-empty. Thus constructing a key pair with an empty key is considered an error now. |
Recently released mocha 6.0.0 is not compatible with Node in our CI environment. Pin the version to ^5.2.0 while it is still available.
Amazing news. Recently released mocha 6.0.0 does not seem to be compatible with Node version on our CI. And it breaks our JavaScript tests. I guess I'll pin the version to 5.2.0 that we have been using until now. |
Call() method on callbacks has been deprecated, it is suggested to use Nan::Call() function for synchronous calls. Do this to avoid warnings about using deprecated API, who knows when it's going to be removed.
It turned out that public key callback did not have enough checks and could crash Node process if the user returns unexpected value from it. Add type checks for result: an array is okay, null and undefined are explicit "not found" values, anything else is also considered "not found" but with a different error code (the exact value does not matter at the moment). Also add a length check to avoid buffer overflow when doing memcpy().
During a dependency downgrade I have noticed that JsThemis triggers a deprecation warning during native addon compilation. I've replaced the deprecated method call with its recommended replacement. That also focused my attention on Secure Session callback which was missing type and length checks. Now it has checks and does not cause Node crashes. Please let it be a green build 🤞 |
Commit 6caa83c contains local changes which were not intended to be committed. Revert them.
As I remember THEMIS_SSESSION_SEND_OUTPUT_TO_PEER used as correct status for Secure Session handshake and tell a user that it needs to be sent to another peer |
@Lagovas, JsThemis makes Secure Session more convenient for the user: Lines 68 to 76 in 6a6b540
The user is expected to send the data to the peer if the data is not |
Yay! Thank you, @vixentael @Lagovas, for very valuable input on this PR. |
The users are confused with non-descriptive errors like
Secure Message failed decrypting
, let's tell them more about what's wrong:And we get this: