/*
* create canonical request for signature version 4
*/
-std::string get_v4_canonical_request_hash(struct req_state* const s,
+std::string get_v4_canonical_request_hash(CephContext* cct,
+ const std::string& http_verb,
const std::string& canonical_uri,
const std::string& canonical_qs,
const std::string& canonical_hdrs,
const std::string& signed_hdrs,
- const std::string& request_payload,
- const bool unsigned_payload)
+ const std::string& request_payload_hash)
{
- string request_payload_hash;
-
- if (unsigned_payload) {
- request_payload_hash = "UNSIGNED-PAYLOAD";
- } else {
- if (s->aws4_auth_needs_complete) {
- request_payload_hash = AWS_AUTHv4_IO(s)->grab_aws4_sha256_hash();
- } else {
- if (s->aws4_auth_streaming_mode) {
- request_payload_hash = "STREAMING-AWS4-HMAC-SHA256-PAYLOAD";
- } else {
- request_payload_hash = \
- hash_string_sha256(request_payload.c_str(), request_payload.size());
- }
- }
- }
-
- s->aws4_auth->payload_hash = request_payload_hash;
-
- ldout(s->cct, 10) << "payload request hash = " << request_payload_hash << dendl;
+ ldout(cct, 10) << "payload request hash = " << request_payload_hash << dendl;
std::string canonical_req = \
- assemble_v4_canonical_request(s->info.method,
+ assemble_v4_canonical_request(http_verb.c_str(),
canonical_uri.c_str(),
canonical_qs.c_str(),
canonical_hdrs.c_str(),
std::string canonical_req_hash = \
hash_string_sha256(canonical_req.c_str(), canonical_req.size());
- ldout(s->cct, 10) << "canonical request = " << canonical_req << dendl;
- ldout(s->cct, 10) << "canonical request hash = " << canonical_req_hash << dendl;
+ ldout(cct, 10) << "canonical request = " << canonical_req << dendl;
+ ldout(cct, 10) << "canonical request hash = " << canonical_req_hash << dendl;
return canonical_req_hash;
}
std::string hash_string_sha256(const char* data, int len);
-std::string get_v4_canonical_request_hash(struct req_state* s,
+std::string get_v4_canonical_request_hash(CephContext* cct,
+ const std::string& http_verb,
const std::string& canonical_uri,
const std::string& canonical_qs,
const std::string& canonical_hdrs,
const std::string& signed_hdrs,
- const std::string& request_payload,
- bool unsigned_payload);
+ const std::string& request_payload_hash);
std::string get_v4_string_to_sign(CephContext* cct,
const std::string& algorithm,
int RGW_Auth_S3::authorize_v4_complete(RGWRados *store, struct req_state *s, const string& request_payload, bool unsigned_payload)
{
- size_t pos;
+ 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 */
- string canonical_req_hash = \
- rgw::auth::s3::get_v4_canonical_request_hash(s, s->aws4_auth->canonical_uri,
+ 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,
- request_payload, unsigned_payload);
+ expected_request_payload_hash);
- /* Validate x-amz-sha256 */
+ if (unsigned_payload) {
+ s->aws4_auth->payload_hash = "UNSIGNED-PAYLOAD";
+ } else {
+ if (s->aws4_auth_needs_complete) {
+ s->aws4_auth->payload_hash = AWS_AUTHv4_IO(s)->grab_aws4_sha256_hash();
+ } else {
+ if (s->aws4_auth_streaming_mode) {
+ s->aws4_auth->payload_hash = "STREAMING-AWS4-HMAC-SHA256-PAYLOAD";
+ } else {
+ s->aws4_auth->payload_hash = \
+ rgw::auth::s3::hash_string_sha256(request_payload.c_str(),
+ request_payload.size());
+ }
+ }
+ }
+ /* Validate x-amz-sha256 */
if (s->aws4_auth_needs_complete) {
- const char *expected_request_payload_hash = s->info.env->get("HTTP_X_AMZ_CONTENT_SHA256");
- if (expected_request_payload_hash &&
- s->aws4_auth->payload_hash.compare(expected_request_payload_hash) != 0) {
+ if (s->aws4_auth->payload_hash.compare(expected_request_payload_hash) != 0) {
ldout(s->cct, 10) << "ERROR: x-amz-content-sha256 does not match" << dendl;
return -ERR_AMZ_CONTENT_SHA256_MISMATCH;
}
string cs_aux = s->aws4_auth->credential_scope;
string date_cs = cs_aux;
- pos = date_cs.find("/");
+ size_t pos = date_cs.find("/");
date_cs = date_cs.substr(0, pos);
cs_aux = cs_aux.substr(pos + 1, cs_aux.length());