From: Radoslaw Zarzynski Date: Wed, 21 Sep 2016 08:34:31 +0000 (+0200) Subject: rgw: implement form's signature verification in Swift's FormPost. X-Git-Tag: v12.0.3~99^2~11 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=607b2baea5a769a9664465c60877f6c90bd9e9f7;p=ceph.git rgw: implement form's signature verification in Swift's FormPost. Signed-off-by: Radoslaw Zarzynski --- diff --git a/src/rgw/rgw_rest_swift.cc b/src/rgw/rgw_rest_swift.cc index a5854b4cb6123..069962319dadc 100644 --- a/src/rgw/rgw_rest_swift.cc +++ b/src/rgw/rgw_rest_swift.cc @@ -1743,6 +1743,42 @@ bool RGWFormPost::is_expired(const std::string& expires) return false; } +bool RGWFormPost::is_integral() +{ + const std::string form_signature = get_part_str(ctrl_parts, "signature"); + + for (const auto& kv : s->user->temp_url_keys) { + const int temp_url_key_num = kv.first; + const string& temp_url_key = kv.second; + + if (temp_url_key.empty()) { + continue; + } + + SignatureHelper sig_helper; + 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(); + + ldout(s->cct, 20) << "FormPost signature [" << temp_url_key_num << "]" + << " (calculated): " << local_sig << dendl; + + if (sig_helper.is_equal_to(form_signature)) { + return true; + } else { + ldout(s->cct, 5) << "FormPost's signature mismatch: " + << local_sig << " != " << form_signature << dendl; + } + } + + return false; +} + int RGWFormPost::get_params() { /* The parentt class extracts boundary info from the Content-Type. */ @@ -1816,6 +1852,11 @@ int RGWFormPost::get_params() return -EACCES; } + if (! is_integral()) { + err_msg = "FormPost: Invalid Signature"; + return -EACCES; + } + return ! current_data_part ? -EINVAL : 0; } diff --git a/src/rgw/rgw_rest_swift.h b/src/rgw/rgw_rest_swift.h index 8ab0e11b882cd..e67620296219f 100644 --- a/src/rgw/rgw_rest_swift.h +++ b/src/rgw/rgw_rest_swift.h @@ -12,6 +12,8 @@ #include "rgw_rest.h" #include "rgw_swift_auth.h" +#include + class RGWGetObj_ObjStore_SWIFT : public RGWGetObj_ObjStore { int custom_http_ret = 0; public: @@ -241,6 +243,7 @@ public: class RGWFormPost : public RGWPostObj_ObjStore { std::string get_current_filename() const override; bool is_next_file_to_upload() override; + bool is_integral(); static bool is_expired(const std::string& expires); parts_collection_t ctrl_parts; @@ -248,6 +251,7 @@ class RGWFormPost : public RGWPostObj_ObjStore { std::string prefix; bool stream_done = false; + class SignatureHelper; public: RGWFormPost() = default; ~RGWFormPost() = default; @@ -263,6 +267,64 @@ 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 boost::string_ref& path_info, + const boost::string_ref& redirect, + const boost::string_ref& max_file_size, + const boost::string_ref& max_file_count, + const boost::string_ref& 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 { RGWRados* const store;