]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: decompose rgw::auth::s3::parse_credentials regarding the query string handling.
authorRadoslaw Zarzynski <rzarzynski@mirantis.com>
Sat, 15 Apr 2017 22:13:16 +0000 (00:13 +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_auth_s3.cc

index 9b41b43cb8644703465f4aba1eb674443f0d741a..4b38098302a87ff660b430dd3e9c0df005964467 100644 (file)
@@ -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<string> auth_list;
-    get_str_list(auth_str.substr(min_len), ",", auth_list);
+  list<string> auth_list;
+  get_str_list(auth_str.substr(min_len), ",", auth_list);
 
-    map<string, string> kv;
+  map<string, string> 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<string, 3> aws4_presigned_required_keys = {
-      "Credential",
-      "SignedHeaders",
-      "Signature"
-    };
+  static std::array<string, 3> 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 */