]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: fix date checks
authorYehuda Sadeh <yehuda@hq.newdream.net>
Thu, 28 Jul 2011 21:03:20 +0000 (14:03 -0700)
committerYehuda Sadeh <yehuda@hq.newdream.net>
Thu, 28 Jul 2011 21:03:38 +0000 (14:03 -0700)
src/rgw/rgw_common.h
src/rgw/rgw_main.cc
src/rgw/rgw_op.h
src/rgw/rgw_os_auth.cc
src/rgw/rgw_os_auth.h
src/rgw/rgw_rest.cc
src/rgw/rgw_rest.h
src/rgw/rgw_rest_os.cc
src/rgw/rgw_rest_os.h
src/rgw/rgw_rest_s3.cc
src/rgw/rgw_rest_s3.h

index e688fba6f54f328b907ee573994b30766823b0bc..f17f454c2970ca26b5c8bad39dc134b09b4a1259 100644 (file)
@@ -101,7 +101,7 @@ extern string rgw_root_bucket;
 #define ERR_NO_SUCH_UPLOAD      2009
 #define ERR_REQUEST_TIMEOUT     2010
 #define ERR_LENGTH_REQUIRED     2011
-
+#define ERR_REQUEST_TIME_SKEWED 2012
 #define ERR_USER_SUSPENDED      2100
 
 typedef void *RGWAccessHandle;
@@ -409,6 +409,7 @@ struct req_state {
    uint64_t obj_size;
    bool should_log;
    uint32_t perm_mask;
+   utime_t header_time;
 
    XMLArgs args;
 
index 67542c5a3a5e74365242e294144683f0349ba093..21b9b9eaab97cdff42f4102b7ce3c80ddc89480e 100644 (file)
@@ -163,9 +163,10 @@ void RGWProcess::handle_request(FCGX_Request *fcgx)
     goto done;
   }
 
-  if (!handler->authorize()) {
+  ret = handler->authorize();
+  if (ret < 0) {
     RGW_LOG(10) << "failed to authorize request" << dendl;
-    abort_early(s, -EPERM);
+    abort_early(s, ret);
     goto done;
   }
   if (s->user.suspended) {
index 97d63d06322643a86a5c706e2f5dc27a0ee9197f..d0dcbb4771755b5006809b65533b7325506d1701 100644 (file)
@@ -561,7 +561,7 @@ public:
   virtual RGWOp *get_op() = 0;
   virtual void put_op(RGWOp *op) = 0;
   virtual int read_permissions() = 0;
-  virtual bool authorize() = 0;
+  virtual int authorize() = 0;
 };
 
 #endif
index dcdf705269582ac8010d5899103102b7ae403af8..0416a45405dd1a698156fce07ddc8f53b826953c 100644 (file)
@@ -170,9 +170,9 @@ done:
   end_header(s);
 }
 
-bool RGWHandler_OS_Auth::authorize()
+int RGWHandler_OS_Auth::authorize()
 {
-  return true;
+  return 0;
 }
 
 RGWOp *RGWHandler_OS_Auth::get_op()
index f40784715c8c6812301059727664895004ce803a..4a31b3dca5ceba680adb4544a7b03272a0d3ed29 100644 (file)
@@ -23,7 +23,7 @@ public:
   RGWOp *get_op();
   void put_op(RGWOp *op);
 
-  bool authorize();
+  int authorize();
   int read_permissions() { return 0; }
 };
 
index d159bc968b5daacdfc20a9d234573a05f998fcb4..71c80324316a54e88ffc4930f46b647dcc87a7fe 100644 (file)
@@ -41,6 +41,7 @@ const static struct rgw_html_errors RGW_HTML_ERRORS[] = {
     { EACCES, 403, "AccessDenied" },
     { EPERM, 403, "AccessDenied" },
     { ERR_USER_SUSPENDED, 403, "UserSuspended" },
+    { ERR_REQUEST_TIME_SKEWED, 403, "RequestTimeTooSkewed" },
     { ENOENT, 404, "NoSuchKey" },
     { ERR_NO_SUCH_BUCKET, 404, "NoSuchBucket" },
     { ERR_NO_SUCH_UPLOAD, 404, "NoSuchUpload" },
index 9094b079bde7ecff56a29df4b627a5db69dd03de..5bac7e744708bc6a54e09be7405d1fd5efb9917e 100644 (file)
@@ -144,7 +144,7 @@ public:
   void put_op(RGWOp *op);
 
   static int preprocess(struct req_state *s, FCGX_Request *fcgx);
-  virtual bool authorize() = 0;
+  virtual int authorize() = 0;
 };
 
 class RGWHandler_REST_OS;
index ad7bcd208009f13f2d1fd89518c5f70c65ad5980..23354d4394408df3cb5a445c7bb7fc0f231f90d6 100644 (file)
@@ -289,7 +289,11 @@ RGWOp *RGWHandler_REST_OS::get_delete_op()
   return NULL;
 }
 
-bool RGWHandler_REST_OS::authorize()
+int RGWHandler_REST_OS::authorize()
 {
-  return rgw_verify_os_token(s);
+  bool authorized = rgw_verify_os_token(s);
+  if (!authorized)
+    return -EPERM;
+
+  return 0;
 }
index 86b24a95b32b8e2e047c0af2322777c64d4eac44..3c5c346c345f8b1611dbf6dba22369ab9b49f2f2 100644 (file)
@@ -110,7 +110,7 @@ public:
   RGWHandler_REST_OS() : RGWHandler_REST() {}
   virtual ~RGWHandler_REST_OS() {}
 
-  bool authorize();
+  int authorize();
 };
 
 #endif
index 0885e990673b39d5d2f0ffe718492b8fe82143cb..37172d9ae8ae67a4768d7fbf310abb5a71a499c9 100644 (file)
@@ -598,6 +598,11 @@ static bool get_auth_header(struct req_state *s, string& dest, bool qsr)
       RGW_LOG(0) << "failed to parse date for auth header" << dendl;
       return false;
     }
+    if (t.tm_year < 70) {
+      RGW_LOG(0) << "bad date (predates epoch): " << req_date << dendl;
+      return false;
+    }
+    s->header_time = utime_t(mktime(&t) + t.tm_gmtoff, 0);
   }
 
   if (date.size())
@@ -619,12 +624,15 @@ static bool get_auth_header(struct req_state *s, string& dest, bool qsr)
  * verify that a signed request comes from the keyholder
  * by checking the signature against our locally-computed version
  */
-bool RGWHandler_REST_S3::authorize()
+int RGWHandler_REST_S3::authorize()
 {
   bool qsr = false;
   string auth_id;
   string auth_sign;
 
+  time_t now;
+  time(&now);
+
   if (!s->http_auth || !(*s->http_auth)) {
     auth_id = s->args.get("AWSAccessKeyId");
     if (auth_id.size()) {
@@ -632,25 +640,23 @@ bool RGWHandler_REST_S3::authorize()
 
       string date = s->args.get("Expires");
       time_t exp = atoll(date.c_str());
-      time_t now;
-      time(&now);
       if (now >= exp)
-        return false;
+        return -EPERM;
 
       qsr = true;
     } else {
       /* anonymous access */
       rgw_get_anon_user(s->user);
       s->perm_mask = RGW_PERM_FULL_CONTROL;
-      return true;
+      return 0;
     }
   } else {
     if (strncmp(s->http_auth, "AWS ", 4))
-      return false;
+      return -EPERM;
     string auth_str(s->http_auth + 4);
     int pos = auth_str.find(':');
     if (pos < 0)
-      return false;
+      return -EPERM;
 
     auth_id = auth_str.substr(0, pos);
     auth_sign = auth_str.substr(pos + 1);
@@ -659,7 +665,7 @@ bool RGWHandler_REST_S3::authorize()
   /* first get the user info */
   if (rgw_get_user_info_by_access_key(auth_id, s->user) < 0) {
     RGW_LOG(5) << "error reading user info, uid=" << auth_id << " can't authenticate" << dendl;
-    return false;
+    return -EPERM;
   }
 
   /* now verify signature */
@@ -667,16 +673,22 @@ bool RGWHandler_REST_S3::authorize()
   string auth_hdr;
   if (!get_auth_header(s, auth_hdr, qsr)) {
     RGW_LOG(10) << "failed to create auth header\n" << auth_hdr << dendl;
-    return false;
+    return -EPERM;
   }
   RGW_LOG(10) << "auth_hdr:\n" << auth_hdr << dendl;
 
-  
+  time_t req_sec = s->header_time.sec();
+  if (req_sec < now - RGW_AUTH_GRACE_MINS * 60 ||
+      req_sec > now + RGW_AUTH_GRACE_MINS * 60) {
+    RGW_LOG(0) << "req_sec=" << req_sec << " 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;
+    RGW_LOG(0) << "request time skew too big now=" << utime_t(now, 0) << " req_time=" << s->header_time << dendl;
+    return -ERR_REQUEST_TIME_SKEWED;
+  }
 
   map<string, RGWAccessKey>::iterator iter = s->user.access_keys.find(auth_id);
   if (iter == s->user.access_keys.end()) {
     RGW_LOG(0) << "ERROR: access key not encoded in user info" << dendl;
-    return false;
+    return -EPERM;
   }
   RGWAccessKey& k = iter->second;
   const char *key = k.key.c_str();
@@ -686,7 +698,7 @@ bool RGWHandler_REST_S3::authorize()
     map<string, RGWSubUser>::iterator uiter = s->user.subusers.find(k.subuser);
     if (uiter == s->user.subusers.end()) {
       RGW_LOG(0) << "ERROR: could not find subuser: " << k.subuser << dendl;
-      return false;
+      return -EPERM;
     }
     RGWSubUser& subuser = uiter->second;
     s->perm_mask = subuser.perm_mask;
@@ -701,14 +713,17 @@ bool RGWHandler_REST_S3::authorize()
                       hmac_sha1 + CEPH_CRYPTO_HMACSHA1_DIGESTSIZE);
   if (ret < 0) {
     RGW_LOG(10) << "ceph_armor failed" << dendl;
-    return false;
+    return -EPERM;
   }
   b64[ret] = '\0';
 
   RGW_LOG(15) << "b64=" << b64 << dendl;
   RGW_LOG(15) << "auth_sign=" << auth_sign << dendl;
   RGW_LOG(15) << "compare=" << auth_sign.compare(b64) << dendl;
-  return (auth_sign.compare(b64) == 0);
+  if (auth_sign.compare(b64) != 0)
+    return -EPERM;
+
+  return  0;
 }
 
 
index fa1a0c99a277dba030983af23311b59d89dade6e..2079376b537f592aeb377ad84dfe4f2b9ccc90d5 100644 (file)
@@ -4,6 +4,8 @@
 
 #include "rgw_op.h"
 
+#define RGW_AUTH_GRACE_MINS 15
+
 class RGWGetObj_REST_S3 : public RGWGetObj_REST
 {
 public:
@@ -145,7 +147,7 @@ public:
   RGWHandler_REST_S3() : RGWHandler_REST() {}
   virtual ~RGWHandler_REST_S3() {}
 
-  bool authorize();
+  int authorize();
 };
 
 #endif