From: Marcus Watts Date: Mon, 22 Aug 2022 07:37:48 +0000 (-0400) Subject: rgw: tempurl signature fixes: also support sha256 and sha512 in formpost X-Git-Tag: v19.3.0~100^2~2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=86c2c9a0aa6fc709022b4beb4fcd456c1320e03a;p=ceph.git rgw: tempurl signature fixes: also support sha256 and sha512 in formpost In openstack swift, formpost and tempurl share the same signature logic, so both now support sha1 / sha256 / sha512. Here are changes to ceph's formpost logic to match what swift does. Most of the guts of the signature logic are moved from .h to .cc because this logic is only useful to the actual formpost code. Fixes: https://tracker.ceph.com/issues/56564 Signed-off-by: Marcus Watts --- diff --git a/src/rgw/rgw_rest_swift.cc b/src/rgw/rgw_rest_swift.cc index 46f02805cd1b..cc75b8146524 100644 --- a/src/rgw/rgw_rest_swift.cc +++ b/src/rgw/rgw_rest_swift.cc @@ -42,6 +42,109 @@ using namespace std; +template +class FormPostSignatureT: public rgw::auth::swift::FormatSignature +{ + using UCHARPTR = const unsigned char*; + using base_t = rgw::auth::swift::SignatureHelperT; + using format_signature_t = rgw::auth::swift::FormatSignature; +public: + const char* calc(const std::string& key, + const std::string_view& path_info, + const std::string_view& redirect, + const std::string_view& max_file_size, + const std::string_view& max_file_count, + const std::string_view& expires) { + HASHFLAVOR hmac((UCHARPTR) key.data(), key.size()); + + hmac.Update((UCHARPTR) path_info.data(), path_info.size()); + hmac.Update((UCHARPTR) "\n", 1); + + hmac.Update((UCHARPTR) redirect.data(), redirect.size()); + hmac.Update((UCHARPTR) "\n", 1); + + hmac.Update((UCHARPTR) max_file_size.data(), max_file_size.size()); + hmac.Update((UCHARPTR) "\n", 1); + + hmac.Update((UCHARPTR) max_file_count.data(), max_file_count.size()); + hmac.Update((UCHARPTR) "\n", 1); + + hmac.Update((UCHARPTR) expires.data(), expires.size()); + + hmac.Final(base_t::dest); + + return format_signature_t::result(); + } +}; +class RGWFormPost::SignatureHelper { +public: + virtual ~SignatureHelper() {}; + virtual const char* calc(const std::string& key, + const std::string_view& path_info, + const std::string_view& redirect, + const std::string_view& max_file_size, + const std::string_view& max_file_count, + const std::string_view& expires) { + return nullptr; + }; + virtual const char* get_signature() const { + return nullptr; + }; + virtual bool is_equal_to(const std::string& rhs) { + return false; + }; + static std::unique_ptr get_sig_helper(std::string_view x); +}; +template +class RGWFormPost::SignatureHelper_x : public RGWFormPost::SignatureHelper +{ + friend RGWFormPost; +private: + FormPostSignatureT d; +public: + ~SignatureHelper_x() { }; + SignatureHelper_x() {}; + virtual const char* calc(const std::string& key, + const std::string_view& path_info, + const std::string_view& redirect, + const std::string_view& max_file_size, + const std::string_view& max_file_count, + const std::string_view& expires) { + return d.calc(key,path_info,redirect, + max_file_size,max_file_count,expires) ; + }; + virtual const char* get_signature() const { + return d.get_signature(); + }; + virtual bool is_equal_to(const std::string& rhs) { + return d.is_equal_to(rhs); + }; +}; + +std::unique_ptr RGWFormPost::SignatureHelper::get_sig_helper(std::string_view x) { + size_t pos = x.find(':'); + if (pos == x.npos || pos <= 0) { + switch(x.length()) { + case CEPH_CRYPTO_HMACSHA1_DIGESTSIZE*2: + return std::make_unique>(); + case CEPH_CRYPTO_HMACSHA256_DIGESTSIZE*2: + return std::make_unique>(); + case CEPH_CRYPTO_HMACSHA512_DIGESTSIZE*2: + return std::make_unique>(); + } + return std::make_unique(); + } + std::string_view type { x.substr(0,pos) }; + if (type == "sha1") { + return std::make_unique>(); + } else if (type == "sha256") { + return std::make_unique>(); + } else if (type == "sha512") { + return std::make_unique>(); + } + return std::make_unique(); +}; + int RGWListBuckets_ObjStore_SWIFT::get_params(optional_yield y) { prefix = s->info.args.get("prefix"); @@ -2034,6 +2137,7 @@ bool RGWFormPost::is_non_expired() bool RGWFormPost::is_integral() { const std::string form_signature = get_part_str(ctrl_parts, "signature"); + bool r = false; try { get_owner_info(s, s->user->get_info()); @@ -2051,28 +2155,31 @@ bool RGWFormPost::is_integral() continue; } - SignatureHelper sig_helper; - sig_helper.calc(temp_url_key, + auto sig_helper{ RGWFormPost::SignatureHelper::get_sig_helper(form_signature) }; + sig_helper->calc(temp_url_key, s->info.request_uri, get_part_str(ctrl_parts, "redirect"), get_part_str(ctrl_parts, "max_file_size", "0"), get_part_str(ctrl_parts, "max_file_count", "0"), get_part_str(ctrl_parts, "expires", "0")); - const auto local_sig = sig_helper.get_signature(); + const char* local_sig = sig_helper->get_signature(); + if (!local_sig) local_sig = "???"; ldpp_dout(this, 20) << "FormPost signature [" << temp_url_key_num << "]" << " (calculated): " << local_sig << dendl; - if (sig_helper.is_equal_to(form_signature)) { - return true; - } else { + r = sig_helper->is_equal_to(form_signature); + if (!r) { ldpp_dout(this, 5) << "FormPost's signature mismatch: " << local_sig << " != " << form_signature << dendl; } + if (r) { + break; + } } - return false; + return r; } void RGWFormPost::get_owner_info(const req_state* const s, diff --git a/src/rgw/rgw_rest_swift.h b/src/rgw/rgw_rest_swift.h index 08b5a77dabbe..154a069d73ff 100644 --- a/src/rgw/rgw_rest_swift.h +++ b/src/rgw/rgw_rest_swift.h @@ -263,6 +263,8 @@ class RGWFormPost : public RGWPostObj_ObjStore { bool stream_done = false; class SignatureHelper; + using BadSignatureHelper = SignatureHelper; + template class SignatureHelper_x; public: RGWFormPost() = default; ~RGWFormPost() = default; @@ -278,64 +280,6 @@ public: static bool is_formpost_req(req_state* const s); }; -class RGWFormPost::SignatureHelper -{ -private: - static constexpr uint32_t output_size = - CEPH_CRYPTO_HMACSHA1_DIGESTSIZE * 2 + 1; - - unsigned char dest[CEPH_CRYPTO_HMACSHA1_DIGESTSIZE]; // 20 - char dest_str[output_size]; - -public: - SignatureHelper() = default; - - const char* calc(const std::string& key, - const std::string_view& path_info, - const std::string_view& redirect, - const std::string_view& max_file_size, - const std::string_view& max_file_count, - const std::string_view& expires) { - using ceph::crypto::HMACSHA1; - using UCHARPTR = const unsigned char*; - - HMACSHA1 hmac((UCHARPTR) key.data(), key.size()); - - hmac.Update((UCHARPTR) path_info.data(), path_info.size()); - hmac.Update((UCHARPTR) "\n", 1); - - hmac.Update((UCHARPTR) redirect.data(), redirect.size()); - hmac.Update((UCHARPTR) "\n", 1); - - hmac.Update((UCHARPTR) max_file_size.data(), max_file_size.size()); - hmac.Update((UCHARPTR) "\n", 1); - - hmac.Update((UCHARPTR) max_file_count.data(), max_file_count.size()); - hmac.Update((UCHARPTR) "\n", 1); - - hmac.Update((UCHARPTR) expires.data(), expires.size()); - - hmac.Final(dest); - - buf_to_hex((UCHARPTR) dest, sizeof(dest), dest_str); - - return dest_str; - } - - const char* get_signature() const { - return dest_str; - } - - bool is_equal_to(const std::string& rhs) const { - /* never allow out-of-range exception */ - if (rhs.size() < (output_size - 1)) { - return false; - } - return rhs.compare(0 /* pos */, output_size, dest_str) == 0; - } - -}; /* RGWFormPost::SignatureHelper */ - class RGWSwiftWebsiteHandler { rgw::sal::Driver* const driver;