From: Yehuda Sadeh Date: Thu, 19 May 2016 22:02:21 +0000 (-0700) Subject: rgw: rework aws4 header parsing X-Git-Tag: v11.0.0~355^2~1 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=e3618c87026b5ced8ef81adbcafc7f9b34f2d48d;p=ceph.git rgw: rework aws4 header parsing Fixes: #15940 Signed-off-by: Yehuda Sadeh --- diff --git a/src/rgw/rgw_rest_s3.cc b/src/rgw/rgw_rest_s3.cc index 463b4b10603f..1605a04dd324 100644 --- a/src/rgw/rgw_rest_s3.cc +++ b/src/rgw/rgw_rest_s3.cc @@ -3202,6 +3202,8 @@ static void aws4_uri_encode(const string& src, string& dst) } } +static std::array aws4_presigned_required_keys = { "Credential", "SignedHeaders", "Signature" }; + /* * handle v4 signatures (rados auth only) */ @@ -3281,84 +3283,42 @@ int RGW_Auth_S3::authorize_v4(RGWRados *store, struct req_state *s) /* ------------------------- handle Credential header */ using_qs = false; - s->aws4_auth->credential = s->http_auth; + + string auth_str = s->http_auth; + #define AWS4_HMAC_SHA256_STR "AWS4-HMAC-SHA256" #define CREDENTIALS_PREFIX_LEN (sizeof(AWS4_HMAC_SHA256_STR) - 1) uint64_t min_len = CREDENTIALS_PREFIX_LEN + 1; - if (s->aws4_auth->credential.length() < min_len) { + if (auth_str.length() < min_len) { ldout(store->ctx(), 10) << "credentials string is too short" << dendl; return -EINVAL; } - s->aws4_auth->credential = s->aws4_auth->credential.substr(min_len, s->aws4_auth->credential.length()); - - pos = s->aws4_auth->credential.find("Credential"); - if (pos == std::string::npos) { - return -EINVAL; - } - - s->aws4_auth->credential = s->aws4_auth->credential.substr(pos, s->aws4_auth->credential.find(",")); - - s->aws4_auth->credential = s->aws4_auth->credential.substr(pos + 1, s->aws4_auth->credential.length()); - - pos = s->aws4_auth->credential.find("="); - - s->aws4_auth->credential = s->aws4_auth->credential.substr(pos + 1, s->aws4_auth->credential.length()); - - /* ------------------------- handle SignedHeaders header */ - - s->aws4_auth->signedheaders = s->http_auth; - - s->aws4_auth->signedheaders = s->aws4_auth->signedheaders.substr(min_len, s->aws4_auth->signedheaders.length()); - - pos = s->aws4_auth->signedheaders.find("SignedHeaders"); - if (pos == std::string::npos) { - return -EINVAL; - } - - s->aws4_auth->signedheaders = s->aws4_auth->signedheaders.substr(pos, s->aws4_auth->signedheaders.length()); - - pos = s->aws4_auth->signedheaders.find(","); - if (pos == std::string::npos) { - return -EINVAL; - } - - s->aws4_auth->signedheaders = s->aws4_auth->signedheaders.substr(0, pos); - - pos = s->aws4_auth->signedheaders.find("="); - if (pos == std::string::npos) { - return -EINVAL; - } - - s->aws4_auth->signedheaders = s->aws4_auth->signedheaders.substr(pos + 1, s->aws4_auth->signedheaders.length()); - - /* host;user-agent;x-amz-content-sha256;x-amz-date */ - dout(10) << "v4 signedheaders format = " << s->aws4_auth->signedheaders << dendl; - - /* ------------------------- handle Signature header */ - - s->aws4_auth->signature = s->http_auth; - - if (s->aws4_auth->signature.size() < min_len) { - ldout(store->ctx(), 10) << "signature string is too short" << dendl; - return -EINVAL; - } + list auth_list; + get_str_list(auth_str.substr(min_len), ",", auth_list); - s->aws4_auth->signature = s->aws4_auth->signature.substr(min_len, s->aws4_auth->signature.length()); + map kv; - pos = s->aws4_auth->signature.find("Signature"); - if (pos == std::string::npos) { - return -EINVAL; + for (string& s : auth_list) { + string key, val; + int ret = parse_key_value(s, key, val); + if (ret < 0) { + ldout(store->ctx(), 10) << "NOTICE: failed to parse auth header (s=" << s << ")" << dendl; + return -EINVAL; + } + kv[key] = val; } - s->aws4_auth->signature = s->aws4_auth->signature.substr(pos, s->aws4_auth->signature.length()); - - pos = s->aws4_auth->signature.find("="); - if (pos == std::string::npos) { - return -EINVAL; + for (string& k : aws4_presigned_required_keys) { + if (kv.find(k) == kv.end()) { + ldout(store->ctx(), 10) << "NOTICE: auth header missing key: " << k << dendl; + return -EINVAL; + } } - s->aws4_auth->signature = s->aws4_auth->signature.substr(pos + 1, s->aws4_auth->signature.length()); + s->aws4_auth->credential = kv["Credential"]; + s->aws4_auth->signedheaders = kv["SignedHeaders"]; + s->aws4_auth->signature = kv["Signature"]; /* sig hex str */ dout(10) << "v4 signature format = " << s->aws4_auth->signature << dendl;