Skip to content

Commit

Permalink
src: move x509 error code and reason to ncrypto
Browse files Browse the repository at this point in the history
  • Loading branch information
jasnell committed Dec 31, 2024
1 parent 7b5bf07 commit 946c40a
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 55 deletions.
47 changes: 47 additions & 0 deletions deps/ncrypto/ncrypto.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1071,6 +1071,53 @@ X509Pointer X509Pointer::IssuerFrom(const SSL_CTX* ctx, const X509View& cert) {
X509Pointer X509Pointer::PeerFrom(const SSLPointer& ssl) {
return X509Pointer(SSL_get_peer_certificate(ssl.get()));
}

// When adding or removing errors below, please also update the list in the API
// documentation. See the "OpenSSL Error Codes" section of doc/api/errors.md
// Also *please* update the respective section in doc/api/tls.md as well
std::string_view X509Pointer::ErrorCode(int32_t err) { // NOLINT(runtime/int)
#define CASE(CODE) \
case X509_V_ERR_##CODE: \
return #CODE;
switch (err) {
CASE(UNABLE_TO_GET_ISSUER_CERT)
CASE(UNABLE_TO_GET_CRL)
CASE(UNABLE_TO_DECRYPT_CERT_SIGNATURE)
CASE(UNABLE_TO_DECRYPT_CRL_SIGNATURE)
CASE(UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY)
CASE(CERT_SIGNATURE_FAILURE)
CASE(CRL_SIGNATURE_FAILURE)
CASE(CERT_NOT_YET_VALID)
CASE(CERT_HAS_EXPIRED)
CASE(CRL_NOT_YET_VALID)
CASE(CRL_HAS_EXPIRED)
CASE(ERROR_IN_CERT_NOT_BEFORE_FIELD)
CASE(ERROR_IN_CERT_NOT_AFTER_FIELD)
CASE(ERROR_IN_CRL_LAST_UPDATE_FIELD)
CASE(ERROR_IN_CRL_NEXT_UPDATE_FIELD)
CASE(OUT_OF_MEM)
CASE(DEPTH_ZERO_SELF_SIGNED_CERT)
CASE(SELF_SIGNED_CERT_IN_CHAIN)
CASE(UNABLE_TO_GET_ISSUER_CERT_LOCALLY)
CASE(UNABLE_TO_VERIFY_LEAF_SIGNATURE)
CASE(CERT_CHAIN_TOO_LONG)
CASE(CERT_REVOKED)
CASE(INVALID_CA)
CASE(PATH_LENGTH_EXCEEDED)
CASE(INVALID_PURPOSE)
CASE(CERT_UNTRUSTED)
CASE(CERT_REJECTED)
CASE(HOSTNAME_MISMATCH)
}
#undef CASE
return "UNSPECIFIED";
}

std::string_view X509Pointer::ErrorReason(int32_t err) {
if (err == X509_V_OK) return "";
return X509_verify_cert_error_string(err);
}

// ============================================================================
// BIOPointer

Expand Down
3 changes: 3 additions & 0 deletions deps/ncrypto/ncrypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -637,6 +637,9 @@ class X509Pointer final {
X509View view() const;
operator X509View() const { return view(); }

static std::string_view ErrorCode(int32_t err);
static std::string_view ErrorReason(int32_t err);

private:
DeleteFnPtr<X509, X509_free> cert_;
};
Expand Down
51 changes: 5 additions & 46 deletions src/crypto/crypto_common.cc
Original file line number Diff line number Diff line change
Expand Up @@ -144,58 +144,17 @@ bool SetGroups(SecureContext* sc, const char* groups) {
return SSL_CTX_set1_groups_list(sc->ctx().get(), groups) == 1;
}

// When adding or removing errors below, please also update the list in the API
// documentation. See the "OpenSSL Error Codes" section of doc/api/errors.md
const char* X509ErrorCode(long err) { // NOLINT(runtime/int)
const char* code = "UNSPECIFIED";
#define CASE_X509_ERR(CODE) case X509_V_ERR_##CODE: code = #CODE; break;
switch (err) {
// if you modify anything in here, *please* update the respective section in
// doc/api/tls.md as well
CASE_X509_ERR(UNABLE_TO_GET_ISSUER_CERT)
CASE_X509_ERR(UNABLE_TO_GET_CRL)
CASE_X509_ERR(UNABLE_TO_DECRYPT_CERT_SIGNATURE)
CASE_X509_ERR(UNABLE_TO_DECRYPT_CRL_SIGNATURE)
CASE_X509_ERR(UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY)
CASE_X509_ERR(CERT_SIGNATURE_FAILURE)
CASE_X509_ERR(CRL_SIGNATURE_FAILURE)
CASE_X509_ERR(CERT_NOT_YET_VALID)
CASE_X509_ERR(CERT_HAS_EXPIRED)
CASE_X509_ERR(CRL_NOT_YET_VALID)
CASE_X509_ERR(CRL_HAS_EXPIRED)
CASE_X509_ERR(ERROR_IN_CERT_NOT_BEFORE_FIELD)
CASE_X509_ERR(ERROR_IN_CERT_NOT_AFTER_FIELD)
CASE_X509_ERR(ERROR_IN_CRL_LAST_UPDATE_FIELD)
CASE_X509_ERR(ERROR_IN_CRL_NEXT_UPDATE_FIELD)
CASE_X509_ERR(OUT_OF_MEM)
CASE_X509_ERR(DEPTH_ZERO_SELF_SIGNED_CERT)
CASE_X509_ERR(SELF_SIGNED_CERT_IN_CHAIN)
CASE_X509_ERR(UNABLE_TO_GET_ISSUER_CERT_LOCALLY)
CASE_X509_ERR(UNABLE_TO_VERIFY_LEAF_SIGNATURE)
CASE_X509_ERR(CERT_CHAIN_TOO_LONG)
CASE_X509_ERR(CERT_REVOKED)
CASE_X509_ERR(INVALID_CA)
CASE_X509_ERR(PATH_LENGTH_EXCEEDED)
CASE_X509_ERR(INVALID_PURPOSE)
CASE_X509_ERR(CERT_UNTRUSTED)
CASE_X509_ERR(CERT_REJECTED)
CASE_X509_ERR(HOSTNAME_MISMATCH)
}
#undef CASE_X509_ERR
return code;
}

MaybeLocal<Value> GetValidationErrorReason(Environment* env, int err) {
if (err == 0)
return Undefined(env->isolate());
const char* reason = X509_verify_cert_error_string(err);
return OneByteString(env->isolate(), reason);
auto reason = X509Pointer::ErrorReason(err);
if (reason == "") return Undefined(env->isolate());
return OneByteString(env->isolate(), reason.data(), reason.length());
}

MaybeLocal<Value> GetValidationErrorCode(Environment* env, int err) {
if (err == 0)
return Undefined(env->isolate());
return OneByteString(env->isolate(), X509ErrorCode(err));
auto error = X509Pointer::ErrorCode(err);
return OneByteString(env->isolate(), error.data(), error.length());
}

MaybeLocal<Value> GetCert(Environment* env, const SSLPointer& ssl) {
Expand Down
2 changes: 0 additions & 2 deletions src/crypto/crypto_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,6 @@ v8::MaybeLocal<v8::Array> GetClientHelloCiphers(

bool SetGroups(SecureContext* sc, const char* groups);

const char* X509ErrorCode(long err); // NOLINT(runtime/int)

v8::MaybeLocal<v8::Value> GetValidationErrorReason(Environment* env, int err);

v8::MaybeLocal<v8::Value> GetValidationErrorCode(Environment* env, int err);
Expand Down
19 changes: 12 additions & 7 deletions src/crypto/crypto_tls.cc
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,7 @@ std::string GetBIOError() {
static_cast<void*>(&ret));
return ret;
}

} // namespace

TLSWrap::TLSWrap(Environment* env,
Expand Down Expand Up @@ -1844,15 +1845,19 @@ void TLSWrap::VerifyError(const FunctionCallbackInfo<Value>& args) {
if (x509_verify_error == X509_V_OK)
return args.GetReturnValue().SetNull();

const char* reason = X509_verify_cert_error_string(x509_verify_error);
const char* code = X509ErrorCode(x509_verify_error);
Local<Value> reason;
if (!GetValidationErrorReason(env, x509_verify_error).ToLocal(&reason)) {
return;
}
if (reason->IsUndefined()) [[unlikely]]
return;

Local<Object> error =
Exception::Error(OneByteString(env->isolate(), reason))
->ToObject(env->isolate()->GetCurrentContext())
.FromMaybe(Local<Object>());
Local<Object> error = Exception::Error(reason.As<v8::String>())
->ToObject(env->isolate()->GetCurrentContext())
.FromMaybe(Local<Object>());

if (Set(env, error, env->code_string(), code))
auto code = X509Pointer::ErrorCode(x509_verify_error);
if (Set(env, error, env->code_string(), code.data()))
args.GetReturnValue().Set(error);
}

Expand Down

0 comments on commit 946c40a

Please sign in to comment.