]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: implement form's signature verification in Swift's FormPost.
authorRadoslaw Zarzynski <rzarzynski@mirantis.com>
Wed, 21 Sep 2016 08:34:31 +0000 (10:34 +0200)
committerRadoslaw Zarzynski <rzarzynski@mirantis.com>
Mon, 24 Apr 2017 15:32:15 +0000 (17:32 +0200)
Signed-off-by: Radoslaw Zarzynski <rzarzynski@mirantis.com>
src/rgw/rgw_rest_swift.cc
src/rgw/rgw_rest_swift.h

index a5854b4cb61237c9b72b62b89cfe44717f885d74..069962319dadc48f5f1a4393c7b4988d1eaeb335 100644 (file)
@@ -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;
 }
 
index 8ab0e11b882cd08231e8142f9596346be3c13bd8..e67620296219fe6b1e5fde6639df72cea0c2c35c 100644 (file)
@@ -12,6 +12,8 @@
 #include "rgw_rest.h"
 #include "rgw_swift_auth.h"
 
+#include <boost/utility/string_ref.hpp>
+
 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;