-
Notifications
You must be signed in to change notification settings - Fork 143
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Improve error reporting in JsThemis (#384)
* Error reporting helpers 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. * Secure Message: use new error reporting functions * Secure Message: length and type checks for arguments * Secure Message: tests for empty keys and messages 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(). * Secure Cell: use new error reporting functions * Secure Cell: length and type checks for arguments * Secure Cell: tests for empty arguments * Improve error messages, simplify calls Use more descriptive error messages which suggestions on how to fix the error. * Return original Themis status code 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. * Retain status code for early errors 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. * Secure Session: use new error reporting functions * Secure Session: length and type checks for arguments * Secure Session: tests for invalid arguments * Secure Comparator: use new error reporting functions * Secure Comparator: length and type checks for arguments * Secure Comparator: tests for invalid arguments * Key generation: update error reporting and checks * Pin mocha to 5.2.0 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. * Avoid using deprecated NAN methods 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. * Secure Session: add checks to pubkey callback 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().
- Loading branch information
Showing
13 changed files
with
817 additions
and
87 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
/* | ||
* Copyright (c) 2019 Cossack Labs Limited | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
#include "errors.hpp" | ||
|
||
#include <string> | ||
|
||
#include <nan.h> | ||
#include <node.h> | ||
|
||
namespace jsthemis { | ||
|
||
static inline void ExportStatusCode(v8::Handle<v8::Object>& exports, const char* name, themis_status_t status) { | ||
exports->Set(Nan::New(name).ToLocalChecked(), Nan::New(status)); | ||
} | ||
|
||
void Errors::Init(v8::Handle<v8::Object> exports) { | ||
ExportStatusCode(exports, "SUCCESS", THEMIS_SUCCESS); | ||
ExportStatusCode(exports, "FAIL", THEMIS_FAIL); | ||
ExportStatusCode(exports, "INVALID_PARAMETER", THEMIS_INVALID_PARAMETER); | ||
ExportStatusCode(exports, "NO_MEMORY", THEMIS_NO_MEMORY); | ||
ExportStatusCode(exports, "BUFFER_TOO_SMALL", THEMIS_BUFFER_TOO_SMALL); | ||
ExportStatusCode(exports, "DATA_CORRUPT", THEMIS_DATA_CORRUPT); | ||
ExportStatusCode(exports, "INVALID_SIGNATURE", THEMIS_INVALID_SIGNATURE); | ||
ExportStatusCode(exports, "NOT_SUPPORTED", THEMIS_NOT_SUPPORTED); | ||
ExportStatusCode(exports, "SSESSION_KA_NOT_FINISHED", THEMIS_SSESSION_KA_NOT_FINISHED); | ||
ExportStatusCode(exports, "SSESSION_TRANSPORT_ERROR", THEMIS_SSESSION_TRANSPORT_ERROR); | ||
ExportStatusCode(exports, "SSESSION_GET_PUB_FOR_ID_CALLBACK_ERROR", THEMIS_SSESSION_GET_PUB_FOR_ID_CALLBACK_ERROR); | ||
ExportStatusCode(exports, "SCOMPARE_NOT_READY", THEMIS_SCOMPARE_NOT_READY); | ||
} | ||
|
||
static const char* ErrorDescription(themis_status_t status) { | ||
switch (status) { | ||
case THEMIS_SUCCESS: | ||
return "success"; | ||
case THEMIS_FAIL: | ||
return "failure"; | ||
case THEMIS_INVALID_PARAMETER: | ||
return "invalid parameter"; | ||
case THEMIS_NO_MEMORY: | ||
return "out of memory"; | ||
case THEMIS_BUFFER_TOO_SMALL: | ||
return "buffer too small"; | ||
case THEMIS_DATA_CORRUPT: | ||
return "corrupted data"; | ||
case THEMIS_INVALID_SIGNATURE: | ||
return "invalid signature"; | ||
case THEMIS_NOT_SUPPORTED: | ||
return "operation not supported"; | ||
default: | ||
return "unknown error"; | ||
} | ||
} | ||
|
||
static const char* ErrorDescriptionSecureSession(themis_status_t status) { | ||
switch (status) { | ||
case THEMIS_SSESSION_SEND_OUTPUT_TO_PEER: | ||
return "send key agreement data to peer"; | ||
case THEMIS_SSESSION_KA_NOT_FINISHED: | ||
return "key agreement not finished"; | ||
case THEMIS_SSESSION_TRANSPORT_ERROR: | ||
return "transport layer error"; | ||
case THEMIS_SSESSION_GET_PUB_FOR_ID_CALLBACK_ERROR: | ||
return "failed to get public key for ID"; | ||
default: | ||
return ErrorDescription(status); | ||
} | ||
} | ||
|
||
static const char* ErrorDescriptionSecureComparator(themis_status_t status) { | ||
switch (status) { | ||
case THEMIS_SCOMPARE_SEND_OUTPUT_TO_PEER: | ||
return "send comparison data to peer"; | ||
case THEMIS_SCOMPARE_NOT_READY: | ||
return "comparator not ready"; | ||
case THEMIS_SCOMPARE_MATCH: | ||
return "data matches"; | ||
case THEMIS_SCOMPARE_NO_MATCH: | ||
return "data does not match"; | ||
default: | ||
return ErrorDescription(status); | ||
} | ||
} | ||
|
||
static v8::Local<v8::Value> WithStatus(v8::Local<v8::Value> error, themis_status_t status) { | ||
v8::Local<v8::Object> object = error.As<v8::Object>(); | ||
object->Set(Nan::New("code").ToLocalChecked(), Nan::New(status)); | ||
return error; | ||
} | ||
|
||
void ThrowError(const char* domain, themis_status_t status) { | ||
std::string message; | ||
message += domain; | ||
message += ": "; | ||
message += ErrorDescription(status); | ||
Nan::ThrowError(WithStatus(Nan::Error(message.c_str()), status)); | ||
} | ||
|
||
void ThrowParameterError(const char* domain, const char* description) { | ||
std::string message; | ||
message += domain; | ||
message += ": "; | ||
message += description; | ||
Nan::ThrowError(WithStatus(Nan::Error(message.c_str()), THEMIS_INVALID_PARAMETER)); | ||
} | ||
|
||
void ThrowSecureSessionError(const char* domain, themis_status_t status) { | ||
std::string message; | ||
message += domain; | ||
message += ": "; | ||
message += ErrorDescriptionSecureSession(status); | ||
Nan::ThrowError(WithStatus(Nan::Error(message.c_str()), status)); | ||
} | ||
|
||
void ThrowSecureComparatorError(const char* domain, themis_status_t status) { | ||
std::string message; | ||
message += domain; | ||
message += ": "; | ||
message += ErrorDescriptionSecureComparator(status); | ||
Nan::ThrowError(WithStatus(Nan::Error(message.c_str()), status)); | ||
} | ||
|
||
} // namespace jsthemis |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
/* | ||
* Copyright (c) 2019 Cossack Labs Limited | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
#ifndef JSTHEMIS_ERRORS_HPP_ | ||
#define JSTHEMIS_ERRORS_HPP_ | ||
|
||
#include <nan.h> | ||
|
||
#include <themis/themis.h> | ||
|
||
namespace jsthemis { | ||
|
||
namespace Errors { | ||
|
||
void Init(v8::Handle<v8::Object> exports); | ||
|
||
} // namespace Errors | ||
|
||
void ThrowError(const char* domain, themis_status_t status); | ||
|
||
void ThrowParameterError(const char* domain, const char* description); | ||
|
||
void ThrowSecureSessionError(const char* domain, themis_status_t status); | ||
|
||
void ThrowSecureComparatorError(const char* domain, themis_status_t status); | ||
|
||
} // namespace jsthemis | ||
|
||
#endif /* JSTHEMIS_ERRORS_HPP_ */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.