From a4377a0843636eae0aaf698510fc6518582545db Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 8 Apr 2022 23:17:01 -0400 Subject: Reject incorrect base64 in HTTP auth In addition, to make sure that no call site ignores the invalid decoding status, make the pf_invalid argument mandatory. --- src/httprpc.cpp | 4 +++- src/test/base32_tests.cpp | 4 +++- src/test/base64_tests.cpp | 4 +++- src/util/strencodings.cpp | 12 ++++-------- src/util/strencodings.h | 8 ++++---- 5 files changed, 17 insertions(+), 15 deletions(-) diff --git a/src/httprpc.cpp b/src/httprpc.cpp index 5d0b59f7cb..5d62568343 100644 --- a/src/httprpc.cpp +++ b/src/httprpc.cpp @@ -132,7 +132,9 @@ static bool RPCAuthorized(const std::string& strAuth, std::string& strAuthUserna if (strAuth.substr(0, 6) != "Basic ") return false; std::string strUserPass64 = TrimString(strAuth.substr(6)); - std::string strUserPass = DecodeBase64(strUserPass64); + bool invalid; + std::string strUserPass = DecodeBase64(strUserPass64, &invalid); + if (invalid) return false; if (strUserPass.find(':') != std::string::npos) strAuthUsernameOut = strUserPass.substr(0, strUserPass.find(':')); diff --git a/src/test/base32_tests.cpp b/src/test/base32_tests.cpp index 5fab7f0d1e..8a44e65165 100644 --- a/src/test/base32_tests.cpp +++ b/src/test/base32_tests.cpp @@ -22,7 +22,9 @@ BOOST_AUTO_TEST_CASE(base32_testvectors) BOOST_CHECK_EQUAL(strEnc, vstrOut[i]); strEnc = EncodeBase32(vstrIn[i], false); BOOST_CHECK_EQUAL(strEnc, vstrOutNoPadding[i]); - std::string strDec = DecodeBase32(vstrOut[i]); + bool invalid; + std::string strDec = DecodeBase32(vstrOut[i], &invalid); + BOOST_CHECK(!invalid); BOOST_CHECK_EQUAL(strDec, vstrIn[i]); } diff --git a/src/test/base64_tests.cpp b/src/test/base64_tests.cpp index 6ee1b83691..04b5185653 100644 --- a/src/test/base64_tests.cpp +++ b/src/test/base64_tests.cpp @@ -19,7 +19,9 @@ BOOST_AUTO_TEST_CASE(base64_testvectors) { std::string strEnc = EncodeBase64(vstrIn[i]); BOOST_CHECK_EQUAL(strEnc, vstrOut[i]); - std::string strDec = DecodeBase64(strEnc); + bool invalid; + std::string strDec = DecodeBase64(strEnc, &invalid); + BOOST_CHECK(!invalid); BOOST_CHECK_EQUAL(strDec, vstrIn[i]); } diff --git a/src/util/strencodings.cpp b/src/util/strencodings.cpp index 6346bc0811..6b6644aa9f 100644 --- a/src/util/strencodings.cpp +++ b/src/util/strencodings.cpp @@ -167,7 +167,7 @@ std::vector DecodeBase64(const char* p, bool* pf_invalid) ++p; } valid = valid && (p - e) % 4 == 0 && p - q < 4; - if (pf_invalid) *pf_invalid = !valid; + *pf_invalid = !valid; return ret; } @@ -175,9 +175,7 @@ std::vector DecodeBase64(const char* p, bool* pf_invalid) std::string DecodeBase64(const std::string& str, bool* pf_invalid) { if (!ValidAsCString(str)) { - if (pf_invalid) { - *pf_invalid = true; - } + *pf_invalid = true; return {}; } std::vector vchRet = DecodeBase64(str.c_str(), pf_invalid); @@ -245,7 +243,7 @@ std::vector DecodeBase32(const char* p, bool* pf_invalid) ++p; } valid = valid && (p - e) % 8 == 0 && p - q < 8; - if (pf_invalid) *pf_invalid = !valid; + *pf_invalid = !valid; return ret; } @@ -253,9 +251,7 @@ std::vector DecodeBase32(const char* p, bool* pf_invalid) std::string DecodeBase32(const std::string& str, bool* pf_invalid) { if (!ValidAsCString(str)) { - if (pf_invalid) { - *pf_invalid = true; - } + *pf_invalid = true; return {}; } std::vector vchRet = DecodeBase32(str.c_str(), pf_invalid); diff --git a/src/util/strencodings.h b/src/util/strencodings.h index 82645c6bf0..c87b2d2415 100644 --- a/src/util/strencodings.h +++ b/src/util/strencodings.h @@ -64,13 +64,13 @@ bool IsHex(std::string_view str); * Return true if the string is a hex number, optionally prefixed with "0x" */ bool IsHexNumber(std::string_view str); -std::vector DecodeBase64(const char* p, bool* pf_invalid = nullptr); -std::string DecodeBase64(const std::string& str, bool* pf_invalid = nullptr); +std::vector DecodeBase64(const char* p, bool* pf_invalid); +std::string DecodeBase64(const std::string& str, bool* pf_invalid); std::string EncodeBase64(Span input); inline std::string EncodeBase64(Span input) { return EncodeBase64(MakeUCharSpan(input)); } inline std::string EncodeBase64(const std::string& str) { return EncodeBase64(MakeUCharSpan(str)); } -std::vector DecodeBase32(const char* p, bool* pf_invalid = nullptr); -std::string DecodeBase32(const std::string& str, bool* pf_invalid = nullptr); +std::vector DecodeBase32(const char* p, bool* pf_invalid); +std::string DecodeBase32(const std::string& str, bool* pf_invalid); /** * Base32 encode. -- cgit v1.2.3