From: Radoslaw Zarzynski Date: Sat, 15 Apr 2017 22:13:16 +0000 (+0200) Subject: rgw: decompose rgw::auth::s3::parse_credentials regarding the query string handling. X-Git-Tag: v12.1.0~155^2~47 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=fe4ef87d1774a1fa91282ad8111bcfdc960d1f65;p=ceph.git rgw: decompose rgw::auth::s3::parse_credentials regarding the query string handling. Signed-off-by: Radoslaw Zarzynski --- diff --git a/src/rgw/rgw_auth_s3.cc b/src/rgw/rgw_auth_s3.cc index 9b41b43cb864..4b38098302a8 100644 --- a/src/rgw/rgw_auth_s3.cc +++ b/src/rgw/rgw_auth_s3.cc @@ -245,142 +245,167 @@ namespace s3 { /* FIXME(rzarzynski): duplicated from rgw_rest_s3.h. */ #define RGW_AUTH_GRACE_MINS 15 -int parse_credentials(const req_info& info, /* in */ - std::string& credential, /* out */ - std::string& signedheaders, /* out */ - std::string& signature, /* out */ - std::string& date, /* out */ - bool& using_qs) /* out */ +static inline int parse_v4_credentials_qs(const req_info& info, /* in */ + std::string& credential, /* out */ + std::string& signedheaders, /* out */ + std::string& signature, /* out */ + std::string& date) /* out */ { - /* used for pre-signatured url, We shouldn't return -ERR_REQUEST_TIME_SKEWED when - current time <= X-Amz-Expires */ - bool qsr = false; + /* auth ships with req params ... */ - uint64_t now_req = 0; - uint64_t now = ceph_clock_now(); + /* look for required params */ + credential = info.args.get("X-Amz-Credential"); + if (credential.size() == 0) { + return -EPERM; + } - const char* http_auth = info.env->get("HTTP_AUTHORIZATION"); - if ((!http_auth) || !(*http_auth)) { + date = info.args.get("X-Amz-Date"); + struct tm date_t; + if (!parse_iso8601(date.c_str(), &date_t, NULL, false)) + return -EPERM; - /* auth ships with req params ... */ + /* Used for pre-signatured url, We shouldn't return -ERR_REQUEST_TIME_SKEWED + * when current time <= X-Amz-Expires */ + bool qsr = false; - /* look for required params */ + uint64_t now_req = 0; + uint64_t now = ceph_clock_now(); - using_qs = true; - credential = info.args.get("X-Amz-Credential"); - if (credential.size() == 0) { + std::string expires = info.args.get("X-Amz-Expires"); + if (!expires.empty()) { + /* X-Amz-Expires provides the time period, in seconds, for which + the generated presigned URL is valid. The minimum value + you can set is 1, and the maximum is 604800 (seven days) */ + time_t exp = atoll(expires.c_str()); + if ((exp < 1) || (exp > 7*24*60*60)) { + dout(10) << "NOTICE: exp out of range, exp = " << exp << dendl; return -EPERM; } - - date = info.args.get("X-Amz-Date"); - struct tm date_t; - if (!parse_iso8601(date.c_str(), &date_t, NULL, false)) + /* handle expiration in epoch time */ + now_req = (uint64_t)internal_timegm(&date_t); + if (now >= now_req + exp) { + dout(10) << "NOTICE: now = " << now << ", now_req = " << now_req << ", exp = " << exp << dendl; return -EPERM; - - std::string expires = info.args.get("X-Amz-Expires"); - if (!expires.empty()) { - /* X-Amz-Expires provides the time period, in seconds, for which - the generated presigned URL is valid. The minimum value - you can set is 1, and the maximum is 604800 (seven days) */ - time_t exp = atoll(expires.c_str()); - if ((exp < 1) || (exp > 7*24*60*60)) { - dout(10) << "NOTICE: exp out of range, exp = " << exp << dendl; - return -EPERM; - } - /* handle expiration in epoch time */ - now_req = (uint64_t)internal_timegm(&date_t); - if (now >= now_req + exp) { - dout(10) << "NOTICE: now = " << now << ", now_req = " << now_req << ", exp = " << exp << dendl; - return -EPERM; - } - qsr = true; - } - - if ((now_req < now - RGW_AUTH_GRACE_MINS * 60 || - now_req > now + RGW_AUTH_GRACE_MINS * 60) && !qsr) { - dout(10) << "NOTICE: request time skew too big." << dendl; - dout(10) << "now_req = " << now_req << " now = " << now - << "; now - RGW_AUTH_GRACE_MINS=" - << now - RGW_AUTH_GRACE_MINS * 60 - << "; now + RGW_AUTH_GRACE_MINS=" - << now + RGW_AUTH_GRACE_MINS * 60 << dendl; - return -ERR_REQUEST_TIME_SKEWED; } + qsr = true; + } - signedheaders = info.args.get("X-Amz-SignedHeaders"); - if (signedheaders.size() == 0) { - return -EPERM; - } + if ((now_req < now - RGW_AUTH_GRACE_MINS * 60 || + now_req > now + RGW_AUTH_GRACE_MINS * 60) && !qsr) { + dout(10) << "NOTICE: request time skew too big." << dendl; + dout(10) << "now_req = " << now_req << " now = " << now + << "; now - RGW_AUTH_GRACE_MINS=" + << now - RGW_AUTH_GRACE_MINS * 60 + << "; now + RGW_AUTH_GRACE_MINS=" + << now + RGW_AUTH_GRACE_MINS * 60 << dendl; + return -ERR_REQUEST_TIME_SKEWED; + } - signature = info.args.get("X-Amz-Signature"); - if (signature.size() == 0) { - return -EPERM; - } + signedheaders = info.args.get("X-Amz-SignedHeaders"); + if (signedheaders.size() == 0) { + return -EPERM; + } - } else { + signature = info.args.get("X-Amz-Signature"); + if (signature.size() == 0) { + return -EPERM; + } - /* auth ships in headers ... */ + return 0; +} - /* ------------------------- handle Credential header */ +static inline int parse_v4_credentials_hdrs(const req_info& info, /* in */ + std::string& credential, /* out */ + std::string& signedheaders, /* out */ + std::string& signature, /* out */ + std::string& date) /* out */ +{ + /* auth ships in headers ... */ - using_qs = false; + /* ------------------------- handle Credential header */ - string auth_str = http_auth; + const char* const http_auth = info.env->get("HTTP_AUTHORIZATION"); + string auth_str = 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 (auth_str.length() < min_len) { - dout(10) << "credentials string is too short" << dendl; - return -EINVAL; - } + uint64_t min_len = CREDENTIALS_PREFIX_LEN + 1; + if (auth_str.length() < min_len) { + dout(10) << "credentials string is too short" << dendl; + return -EINVAL; + } - list auth_list; - get_str_list(auth_str.substr(min_len), ",", auth_list); + list auth_list; + get_str_list(auth_str.substr(min_len), ",", auth_list); - map kv; + map kv; - for (string& s : auth_list) { - string key, val; - int ret = parse_key_value(s, key, val); - if (ret < 0) { - dout(10) << "NOTICE: failed to parse auth header (s=" << s << ")" << dendl; - return -EINVAL; - } - kv[key] = std::move(val); + for (string& s : auth_list) { + string key, val; + int ret = parse_key_value(s, key, val); + if (ret < 0) { + dout(10) << "NOTICE: failed to parse auth header (s=" << s << ")" << dendl; + return -EINVAL; } + kv[key] = std::move(val); + } - static std::array aws4_presigned_required_keys = { - "Credential", - "SignedHeaders", - "Signature" - }; + static std::array aws4_presigned_required_keys = { + "Credential", + "SignedHeaders", + "Signature" + }; - for (string& k : aws4_presigned_required_keys) { - if (kv.find(k) == kv.end()) { - dout(10) << "NOTICE: auth header missing key: " << k << dendl; - return -EINVAL; - } + for (string& k : aws4_presigned_required_keys) { + if (kv.find(k) == kv.end()) { + dout(10) << "NOTICE: auth header missing key: " << k << dendl; + return -EINVAL; } + } - credential = std::move(kv["Credential"]); - signedheaders = std::move(kv["SignedHeaders"]); - signature = std::move(kv["Signature"]); + credential = std::move(kv["Credential"]); + signedheaders = std::move(kv["SignedHeaders"]); + signature = std::move(kv["Signature"]); - /* sig hex str */ - dout(10) << "v4 signature format = " << signature << dendl; + /* sig hex str */ + dout(10) << "v4 signature format = " << signature << dendl; - /* ------------------------- handle x-amz-date header */ + /* ------------------------- handle x-amz-date header */ - /* grab date */ + /* grab date */ - const char *d = info.env->get("HTTP_X_AMZ_DATE"); - struct tm t; - if (!parse_iso8601(d, &t, NULL, false)) { - dout(10) << "error reading date via http_x_amz_date" << dendl; - return -EACCES; - } - date = d; + const char *d = info.env->get("HTTP_X_AMZ_DATE"); + struct tm t; + if (!parse_iso8601(d, &t, NULL, false)) { + dout(10) << "error reading date via http_x_amz_date" << dendl; + return -EACCES; + } + date = d; + + return 0; +} + +int parse_credentials(const req_info& info, /* in */ + std::string& credential, /* out */ + std::string& signedheaders, /* out */ + std::string& signature, /* out */ + std::string& date, /* out */ + bool& using_qs) /* out */ +{ + int ret; + const char* const http_auth = info.env->get("HTTP_AUTHORIZATION"); + + using_qs = http_auth == nullptr || http_auth[0] == '\0'; + if (using_qs) { + ret = parse_v4_credentials_qs(info, credential, signedheaders, + signature, date); + } else { + ret = parse_v4_credentials_hdrs(info, credential, signedheaders, + signature, date); + } + + if (ret < 0) { + return ret; } /* AKIAIVKTAZLOCF43WNQD/AAAAMMDD/region/host/aws4_request */