]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: decouple AWSv4 signature verification and payload fingerprint check.
authorRadoslaw Zarzynski <rzarzynski@mirantis.com>
Sat, 15 Apr 2017 20:54:56 +0000 (22:54 +0200)
committerRadoslaw Zarzynski <rzarzynski@mirantis.com>
Wed, 7 Jun 2017 10:43:16 +0000 (12:43 +0200)
Signed-off-by: Radoslaw Zarzynski <rzarzynski@mirantis.com>
src/rgw/rgw_rest_s3.cc

index accb76afd06097634f616d7ed6c0b69a78680dd7..a04e278755b2b247632d0609d0edc51fec6d4f01 100644 (file)
@@ -3428,16 +3428,6 @@ int RGW_Auth_S3::authorize_v4_complete(RGWRados *store, struct req_state *s, con
     expected_request_payload_hash = "UNSIGNED-PAYLOAD";
   }
 
-  /* craft canonical request */
-  std::string canonical_req_hash = \
-    rgw::auth::s3::get_v4_canonical_request_hash(s->cct,
-                                                 s->info.method,
-                                                 s->aws4_auth->canonical_uri,
-                                                 s->aws4_auth->canonical_qs,
-                                                 s->aws4_auth->canonical_hdrs,
-                                                 s->aws4_auth->signed_hdrs,
-                                                 expected_request_payload_hash);
-
   std::string payload_hash;
   if (unsigned_payload) {
     payload_hash = "UNSIGNED-PAYLOAD";
@@ -3463,46 +3453,6 @@ int RGW_Auth_S3::authorize_v4_complete(RGWRados *store, struct req_state *s, con
     }
   }
 
-  /*
-   * create a string to sign
-   *
-   * http://docs.aws.amazon.com/general/latest/gr/sigv4-create-string-to-sign.html
-   */
-
-  std::string string_to_sign = \
-    rgw::auth::s3::get_v4_string_to_sign(s->cct, "AWS4-HMAC-SHA256",
-                                         s->aws4_auth->date,
-                                         s->aws4_auth->credential_scope,
-                                         canonical_req_hash);
-
-  /*
-   * calculate the AWS signature
-   *
-   * http://docs.aws.amazon.com/general/latest/gr/sigv4-calculate-signature.html
-   */
-
-  const auto iter = s->user->access_keys.find(s->aws4_auth->access_key_id);
-  if (iter == std::end(s->user->access_keys)) {
-    ldout(s->cct, 10) << "ERROR: access key not encoded in user info" << dendl;
-    return -EPERM;
-  }
-  const RGWAccessKey& k = iter->second;
-
-  s->aws4_auth->signing_key = \
-    rgw::auth::s3::get_v4_signing_key(s->cct,
-                                      s->aws4_auth->credential_scope, k.key);
-  s->aws4_auth->new_signature = \
-    rgw::auth::s3::get_v4_signature(s->cct, s->aws4_auth->signing_key,
-                                    string_to_sign);
-
-
-  ldout(s->cct, 10) << "----------------------------- Verifying signatures" << dendl;
-  ldout(s->cct, 10) << "Signature     = " << s->aws4_auth->signature << dendl;
-  ldout(s->cct, 10) << "New Signature = " << s->aws4_auth->new_signature << dendl;
-  ldout(s->cct, 10) << "-----------------------------" << dendl;
-
-  s->aws4_auth->seed_signature = s->aws4_auth->new_signature;
-
   return 0;
 
 }
@@ -3610,6 +3560,71 @@ int RGW_Auth_S3::authorize_v4(RGWRados *store, struct req_state *s, bool force_b
     }
   }
 
+  const char *expected_request_payload_hash = s->info.env->get("HTTP_X_AMZ_CONTENT_SHA256");
+  if (!expected_request_payload_hash) {
+    /* In AWSv4 the hash of real, transfered payload IS NOT necessary to form
+     * a Canonical Request, and thus verify a Signature. x-amz-content-sha256
+     * header lets get the information very early -- before seeing first byte
+     * of HTTP body. As a consequence, we can decouple Signature verification
+     * from payload's fingerprint check. Although RadosGW doesn't do that for
+     * now, the situation will definitely change in the future.
+     *
+     * An HTTP client MUST send x-amz-content-sha256. AFAIK the single exception
+     * to that is the case of using Query Parameters for doing the auth In such
+     * scenario, the "UNSIGNED-PAYLOAD" literals are used instead. */
+    expected_request_payload_hash = "UNSIGNED-PAYLOAD";
+  }
+
+  /* craft canonical request */
+  std::string canonical_req_hash = \
+    rgw::auth::s3::get_v4_canonical_request_hash(s->cct,
+                                                 s->info.method,
+                                                 s->aws4_auth->canonical_uri,
+                                                 s->aws4_auth->canonical_qs,
+                                                 s->aws4_auth->canonical_hdrs,
+                                                 s->aws4_auth->signed_hdrs,
+                                                 expected_request_payload_hash);
+
+  /*
+   * create a string to sign
+   *
+   * http://docs.aws.amazon.com/general/latest/gr/sigv4-create-string-to-sign.html
+   */
+
+  std::string string_to_sign = \
+    rgw::auth::s3::get_v4_string_to_sign(s->cct, "AWS4-HMAC-SHA256",
+                                         s->aws4_auth->date,
+                                         s->aws4_auth->credential_scope,
+                                         canonical_req_hash);
+
+  /*
+   * calculate the AWS signature
+   *
+   * http://docs.aws.amazon.com/general/latest/gr/sigv4-calculate-signature.html
+   */
+
+  const auto iter = s->user->access_keys.find(s->aws4_auth->access_key_id);
+  if (iter == std::end(s->user->access_keys)) {
+    ldout(s->cct, 10) << "ERROR: access key not encoded in user info" << dendl;
+    return -EPERM;
+  }
+  const RGWAccessKey& k = iter->second;
+
+  s->aws4_auth->signing_key = \
+    rgw::auth::s3::get_v4_signing_key(s->cct,
+                                      s->aws4_auth->credential_scope, k.key);
+  s->aws4_auth->new_signature = \
+    rgw::auth::s3::get_v4_signature(s->cct, s->aws4_auth->signing_key,
+                                    string_to_sign);
+
+
+  ldout(s->cct, 10) << "----------------------------- Verifying signatures" << dendl;
+  ldout(s->cct, 10) << "Signature     = " << s->aws4_auth->signature << dendl;
+  ldout(s->cct, 10) << "New Signature = " << s->aws4_auth->new_signature << dendl;
+  ldout(s->cct, 10) << "-----------------------------" << dendl;
+
+  s->aws4_auth->seed_signature = s->aws4_auth->new_signature;
+
   /* from rfc2616 - 4.3 Message Body
    *
    * "The presence of a message-body in a request is signaled by the inclusion of a
@@ -3709,14 +3724,6 @@ int RGW_Auth_S3::authorize_v4(RGWRados *store, struct req_state *s, bool force_b
 
   }
 
-  map<string, RGWAccessKey>::iterator iter = s->user->access_keys.find(s->aws4_auth->access_key_id);
-  if (iter == s->user->access_keys.end()) {
-    dout(0) << "ERROR: access key not encoded in user info" << dendl;
-    return -EPERM;
-  }
-
-  RGWAccessKey& k = iter->second;
-
   if (!k.subuser.empty()) {
     map<string, RGWSubUser>::iterator uiter = s->user->subusers.find(k.subuser);
     if (uiter == s->user->subusers.end()) {