]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: TempURL in radosgw behaves now like its Swift's counterpart. 12619/head
authorRadoslaw Zarzynski <rzarzynski@mirantis.com>
Fri, 4 Mar 2016 15:30:50 +0000 (16:30 +0100)
committerMichal Koutný <mkoutny@suse.com>
Tue, 3 Jan 2017 17:10:11 +0000 (18:10 +0100)
Signed-off-by: Radoslaw Zarzynski <rzarzynski@mirantis.com>
(cherry picked from commit a1ea7180969dcbaf88dfcc1bfafb17e82639df64)

Conflicts:
src/rgw/rgw_swift.cc
  - replace C++11 constructs,
    - s->info.method is actually unconditional member of
      allowed_methods, which was opaqued by C++11 ctors
  - drop temp_url_make_content_disp() which has no use with
    hammer's req_state

src/rgw/rgw_swift.cc

index 09fb9b7b92845af379b7bf4961996ed170ebfe77..3bebcb5b8d7d0e372c9a29a71e6a0088b0170a4a 100644 (file)
@@ -539,6 +539,25 @@ int RGWSwift::validate_keystone_token(RGWRados *store, const string& token, stru
   return 0;
 }
 
+static string temp_url_gen_sig(const string& key,
+                               const string& method,
+                               const string& path,
+                               const string& expires)
+{
+  const string str = method + "\n" + expires + "\n" + path;
+  //dout(20) << "temp url signature (plain text): " << str << dendl;
+
+  /* unsigned */ char dest[CEPH_CRYPTO_HMACSHA1_DIGESTSIZE];
+  calc_hmac_sha1(key.c_str(), key.size(),
+                 str.c_str(), str.size(),
+                 dest);
+
+  char dest_str[CEPH_CRYPTO_HMACSHA1_DIGESTSIZE * 2 + 1];
+  buf_to_hex((const unsigned char *)dest, sizeof(dest), dest_str);
+
+  return dest_str;
+}
+
 int authenticate_temp_url(RGWRados *store, req_state *s)
 {
   /* temp url requires bucket and object specified in the requets */
@@ -589,32 +608,55 @@ int authenticate_temp_url(RGWRados *store, req_state *s)
     return -EPERM;
   }
 
-  /* strip the swift prefix from the uri */
-  int pos = g_conf->rgw_swift_url_prefix.find_last_not_of('/') + 1;
-  string object_path = s->info.request_uri.substr(pos + 1);
-  string str = string(s->info.method) + "\n" + temp_url_expires + "\n" + object_path;
+  /* We need to verify two paths because of compliance with Swift, Tempest
+   * and old versions of RadosGW. The second item will have the prefix
+   * of Swift API entry point removed. */
+  const size_t pos = g_conf->rgw_swift_url_prefix.find_last_not_of('/') + 1;
+  vector<string> allowed_paths;
+  allowed_paths.push_back(s->info.request_uri);
+  allowed_paths.push_back(s->info.request_uri.substr(pos + 1));
 
-  dout(20) << "temp url signature (plain text): " << str << dendl;
+  vector<string> allowed_methods;
+  allowed_methods.push_back(s->info.method);
+  if (strcmp("HEAD", s->info.method) == 0) {
+    /* HEAD requests are specially handled. */
+    allowed_methods.push_back("PUT");
+    allowed_methods.push_back("GET");
+  }
 
-  map<int, string>::iterator iter;
-  for (iter = s->user.temp_url_keys.begin(); iter != s->user.temp_url_keys.end(); ++iter) {
-    string& temp_url_key = iter->second;
+  /* Need to try each combination of keys, allowed path and methods. */
+  map<int, string>::const_iterator key_iter;
+  for (key_iter = s->user.temp_url_keys.begin(); key_iter != s->user.temp_url_keys.end(); ++key_iter) {
+    const int temp_url_key_num = key_iter->first;
+    const string& temp_url_key = key_iter->second;
 
-    if (temp_url_key.empty())
+    if (temp_url_key.empty()) {
       continue;
+    }
 
-    char dest[CEPH_CRYPTO_HMACSHA1_DIGESTSIZE];
-    calc_hmac_sha1(temp_url_key.c_str(), temp_url_key.size(),
-                   str.c_str(), str.size(), dest);
-
-    char dest_str[CEPH_CRYPTO_HMACSHA1_DIGESTSIZE * 2 + 1];
-    buf_to_hex((const unsigned char *)dest, sizeof(dest), dest_str);
-    dout(20) << "temp url signature [" << iter->first << "] (calculated): " << dest_str << dendl;
-
-    if (dest_str != temp_url_sig) {
-      dout(5) << "temp url signature mismatch: " << dest_str << " != " << temp_url_sig << dendl;
-    } else {
-      return 0;
+    vector<string>::const_iterator path_iter;
+    for (path_iter = allowed_paths.begin(); path_iter != allowed_paths.end(); ++path_iter) {
+      vector<string>::const_iterator method_iter;
+      for (method_iter = allowed_methods.begin(); method_iter != allowed_methods.end(); ++method_iter) {
+        const string local_sig = temp_url_gen_sig(temp_url_key,
+                                                  *method_iter, *path_iter,
+                                                  temp_url_expires);
+
+        dout(20) << "temp url signature [" << temp_url_key_num
+                 << "] (calculated): " << local_sig
+                 << dendl;
+
+        if (local_sig != temp_url_sig) {
+          dout(5) << "temp url signature mismatch: " << local_sig
+                  << " != "
+                  << temp_url_sig
+                  << dendl;
+        } else {
+          dout(20) << "temp url signature match: " << local_sig
+                   << dendl;
+          return 0;
+        }
+      }
     }
   }