Fix out-of-bounds access in three_parts. Fix mishandling of non-null terminated string_views in jwt_set::case_compare. Address several conversion and unreachability warnings

This commit is contained in:
Dennis Hezel 2022-05-13 19:13:38 +02:00
parent 0d662241da
commit 6c22d941a0
6 changed files with 11 additions and 33 deletions

View file

@ -358,7 +358,7 @@ struct HMACSign
unsigned char* res = HMAC(Hasher{}(), unsigned char* res = HMAC(Hasher{}(),
key.data(), key.data(),
key.length(), static_cast<int>(key.length()),
reinterpret_cast<const unsigned char*>(data.data()), reinterpret_cast<const unsigned char*>(data.data()),
data.length(), data.length(),
reinterpret_cast<unsigned char*>(&sign[0]), reinterpret_cast<unsigned char*>(&sign[0]),

View file

@ -38,7 +38,7 @@ verify_result_t HMACSign<Hasher>::verify(
unsigned char* res = HMAC(Hasher{}(), unsigned char* res = HMAC(Hasher{}(),
key.data(), key.data(),
key.length(), static_cast<int>(key.length()),
reinterpret_cast<const unsigned char*>(head.data()), reinterpret_cast<const unsigned char*>(head.data()),
head.length(), head.length(),
enc_buf, enc_buf,
@ -79,7 +79,7 @@ verify_result_t PEMSign<Hasher>::verify(
std::string dec_sig = base64_uri_decode(jwt_sign.data(), jwt_sign.length()); std::string dec_sig = base64_uri_decode(jwt_sign.data(), jwt_sign.length());
BIO_uptr bufkey{ BIO_uptr bufkey{
BIO_new_mem_buf((void*)key.data(), key.length()), BIO_new_mem_buf((void*)key.data(), static_cast<int>(key.length())),
bio_deletor}; bio_deletor};
if (!bufkey) { if (!bufkey) {
@ -180,7 +180,7 @@ EVP_PKEY* PEMSign<Hasher>::load_key(
ec.clear(); ec.clear();
BIO_uptr bio_ptr{ BIO_uptr bio_ptr{
BIO_new_mem_buf((void*)key.data(), key.length()), BIO_new_mem_buf((void*)key.data(), static_cast<int>(key.length())),
bio_deletor}; bio_deletor};
if (!bio_ptr) { if (!bio_ptr) {
@ -276,7 +276,7 @@ std::string PEMSign<Hasher>::public_key_ser(
EC_SIG_uptr ec_sig{d2i_ECDSA_SIG(nullptr, EC_SIG_uptr ec_sig{d2i_ECDSA_SIG(nullptr,
(const unsigned char**)&char_ptr, (const unsigned char**)&char_ptr,
sign.length()), static_cast<long>(sign.length())),
ec_sig_deletor}; ec_sig_deletor};
if (!ec_sig) { if (!ec_sig) {

View file

@ -52,7 +52,6 @@ struct AlgorithmErrCategory: std::error_category
return "invalid key"; return "invalid key";
}; };
return "unknown algorithm error"; return "unknown algorithm error";
assert (0 && "Code not reached");
} }
}; };
@ -89,7 +88,6 @@ struct DecodeErrorCategory: std::error_category
return "key not required for NONE algorithm"; return "key not required for NONE algorithm";
}; };
return "unknown decode error"; return "unknown decode error";
assert (0 && "Code not reached");
} }
}; };
@ -128,7 +126,6 @@ struct VerificationErrorCategory: std::error_category
return "type conversion error"; return "type conversion error";
}; };
return "unknown verification error"; return "unknown verification error";
assert (0 && "Code not reached");
} }
}; };

View file

@ -70,7 +70,7 @@ inline void jwt_header::decode(const jwt::string_view enc_str, std::error_code&
try { try {
payload_ = json_t::parse(std::move(json_str)); payload_ = json_t::parse(std::move(json_str));
} catch(const std::exception& e) { } catch(const std::exception&) {
ec = DecodeErrc::JsonParseError; ec = DecodeErrc::JsonParseError;
return; return;
} }
@ -130,7 +130,7 @@ inline void jwt_payload::decode(const jwt::string_view enc_str, std::error_code&
std::string json_str = base64_decode(enc_str); std::string json_str = base64_decode(enc_str);
try { try {
payload_ = json_t::parse(std::move(json_str)); payload_ = json_t::parse(std::move(json_str));
} catch(const std::exception& e) { } catch(const std::exception&) {
ec = DecodeErrc::JsonParseError; ec = DecodeErrc::JsonParseError;
return; return;
} }
@ -530,7 +530,7 @@ jwt_object::three_parts(const jwt::string_view enc_str)
result[1] = jwt::string_view{&enc_str[fpos + 1], spos - fpos - 1}; result[1] = jwt::string_view{&enc_str[fpos + 1], spos - fpos - 1};
if (spos != enc_str.length()) { if (spos + 1 != enc_str.length()) {
result[2] = jwt::string_view{&enc_str[spos + 1], enc_str.length() - spos - 1}; result[2] = jwt::string_view{&enc_str[spos + 1], enc_str.length() - spos - 1};
} }
@ -711,7 +711,7 @@ jwt_object decode(const jwt::string_view enc_str,
if (dparams.verify) { if (dparams.verify) {
try { try {
ec = obj.verify(dparams, algos); ec = obj.verify(dparams, algos);
} catch (const json_ns::detail::type_error& e) { } catch (const json_ns::detail::type_error&) {
ec = VerificationErrc::TypeConversionError; ec = VerificationErrc::TypeConversionError;
} }

View file

@ -72,7 +72,6 @@ inline enum type str_to_type(const jwt::string_view typ) noexcept
else if(!strcasecmp(typ.data(), "none")) return type::NONE; else if(!strcasecmp(typ.data(), "none")) return type::NONE;
JWT_NOT_REACHED("Code not reached"); JWT_NOT_REACHED("Code not reached");
return type::NONE;
} }
@ -130,7 +129,6 @@ inline jwt::string_view reg_claims_to_str(SCOPED_ENUM registered_claims claim) n
default: assert (0 && "Not a registered claim"); default: assert (0 && "Not a registered claim");
}; };
JWT_NOT_REACHED("Code not reached"); JWT_NOT_REACHED("Code not reached");
return "";
} }
/** /**
@ -147,27 +145,9 @@ struct jwt_set
{ {
using is_transparent = std::true_type; using is_transparent = std::true_type;
bool operator()(const std::string& lhs, const std::string& rhs) const
{
int ret = strcmp(lhs.c_str(), rhs.c_str());
return (ret < 0);
}
bool operator()(const jwt::string_view lhs, const jwt::string_view rhs) const bool operator()(const jwt::string_view lhs, const jwt::string_view rhs) const
{ {
int ret = strcmp(lhs.data(), rhs.data()); int ret = lhs.compare(rhs);
return (ret < 0);
}
bool operator()(const std::string& lhs, const jwt::string_view rhs) const
{
int ret = strcmp(lhs.data(), rhs.data());
return (ret < 0);
}
bool operator()(const jwt::string_view lhs, const std::string& rhs) const
{
int ret = strcmp(lhs.data(), rhs.data());
return (ret < 0); return (ret < 0);
} }
}; };

View file

@ -138,6 +138,7 @@ public: // Exposed APIs
/// Element Access Member Functions /// Element Access Member Functions
const_reference operator[](size_type idx) const noexcept const_reference operator[](size_type idx) const noexcept
{ {
assert(idx < len_ && "string_view subscript out of range");
return data_[idx]; return data_[idx];
} }