diff options
author | caleb miles <caselim@gmail.com> | 2012-10-11 19:00:48 +0200 |
---|---|---|
committer | Yehuda Sadeh <yehuda@inktank.com> | 2012-10-23 19:44:18 +0200 |
commit | 7bb3504d3f0974e9863f536e9af0ce8889d6888f (patch) | |
tree | e23d63c9b437251b8efd01b75da824187fa40d06 /src | |
parent | rgw: implement POST key can use ${filename} (diff) | |
download | ceph-7bb3504d3f0974e9863f536e9af0ce8889d6888f.tar.xz ceph-7bb3504d3f0974e9863f536e9af0ce8889d6888f.zip |
rgw: handle expiration and content length policy conditions.
Signed-off-by: caleb miles <caleb.miles@inktank.com>
Signed-off-by: Yehuda Sadeh <yehuda@inktank.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/rgw/rgw_op.cc | 8 | ||||
-rw-r--r-- | src/rgw/rgw_op.h | 2 | ||||
-rw-r--r-- | src/rgw/rgw_policy_s3.cc | 65 | ||||
-rw-r--r-- | src/rgw/rgw_policy_s3.h | 12 | ||||
-rw-r--r-- | src/rgw/rgw_rest_s3.cc | 6 | ||||
-rw-r--r-- | src/rgw/rgw_rest_s3.h | 1 |
6 files changed, 85 insertions, 9 deletions
diff --git a/src/rgw/rgw_op.cc b/src/rgw/rgw_op.cc index 9111c5f2998..0b1f7f6b502 100644 --- a/src/rgw/rgw_op.cc +++ b/src/rgw/rgw_op.cc @@ -1313,7 +1313,7 @@ void RGWPostObj::execute() unsigned char m[CEPH_CRYPTO_MD5_DIGESTSIZE]; MD5 hash; bufferlist bl, aclbl; - int len; + int len = 0; ret = verify_params(); if (ret < 0) @@ -1356,8 +1356,14 @@ void RGWPostObj::execute() goto done; ofs += len; + + if (ofs > max_allowable_content_length) + goto done; } + if (len < min_allowable_content_length) + goto done; + s->obj_size = ofs; hash.Final(m); diff --git a/src/rgw/rgw_op.h b/src/rgw/rgw_op.h index e41d189aa75..e9334384e7e 100644 --- a/src/rgw/rgw_op.h +++ b/src/rgw/rgw_op.h @@ -310,6 +310,8 @@ class RGWPostObj : public RGWOp { friend class RGWPutObjProcessor; protected: + int min_allowable_content_length; + int max_allowable_content_length; int ret; int len; off_t ofs; diff --git a/src/rgw/rgw_policy_s3.cc b/src/rgw/rgw_policy_s3.cc index b0fc78524b2..dbe291c2cc7 100644 --- a/src/rgw/rgw_policy_s3.cc +++ b/src/rgw/rgw_policy_s3.cc @@ -105,13 +105,49 @@ RGWPolicy::~RGWPolicy() } } +uint64_t RGWPolicy::get_current_epoch() +{ + uint64_t current_epoch = 0; + time_t local_time = ceph_clock_now(NULL).sec(); + struct tm *gmt_time_struct = gmtime(&local_time); + + current_epoch = timegm(gmt_time_struct); + + +// string gmt_time_string = asctime(gmt_time_struct); + +// parse_date(gmt_time_string, ¤t_epoch, NULL, NULL); + + return current_epoch; +} + +void RGWPolicy::set_expires(utime_t& e) +{ + time_t e_time = e.sec(); + struct tm *gmt_time_struct = gmtime(&e_time); + string gmt_time_string = asctime(gmt_time_struct); + parse_date(gmt_time_string, &expires, NULL, NULL); +} + +void RGWPolicy::set_expires(string& e) +{ + parse_date(e, &expires, NULL, NULL); +} + int RGWPolicy::add_condition(const string& op, const string& first, const string& second) { RGWPolicyCondition *cond = NULL; - if (stringcasecmp(op, "eq") == 0) + if (stringcasecmp(op, "eq") == 0) { cond = new RGWPolicyCondition_StrEqual; - else if (stringcasecmp(op, "starts-with") == 0) + } else if (stringcasecmp(op, "starts-with") == 0) { cond = new RGWPolicyCondition_StrStartsWith; + } else if (stringcasecmp(op, "content-length-range") == 0) { + stringstream min_string(first); + stringstream max_string(second); + + if ( !(min_string >> min_length) || !(max_string >> max_length) ) + return -EINVAL; + } if (!cond) return -EINVAL; @@ -166,11 +202,31 @@ int RGWPolicy::from_json(bufferlist& bl) if (!parser.parse(bl.c_str(), bl.length())) return -EINVAL; - JSONObjIter iter = parser.find_first("conditions"); + // as no time was included in the request, we hope that the user has included a short timeout + JSONObjIter iter = parser.find_first("expiration"); if (iter.end()) - return 0; + return -EINVAL; // change to a "no expiration" error following S3 JSONObj *obj = *iter; + string expiration_string = obj->get_data(); + set_expires(expiration_string); + + uint64_t current_epoch = get_current_epoch(); + if (current_epoch == 0) { + dout(0) << "NOTICE: failed to get current epoch!" << dendl; + return -EINVAL; + } + + if (expires < current_epoch) { + dout(0) << "NOTICE: policy calculated as expired: " << expiration_string << dendl; + return -EINVAL; // change to condition about expired policy following S3 + } + + iter = parser.find_first("conditions"); + if (iter.end()) + return -EINVAL; // change to a "no conditions" error following S3 + + obj = *iter; iter = obj->find_first(); for (; !iter.end(); ++iter) { @@ -187,6 +243,7 @@ int RGWPolicy::from_json(bufferlist& bl) } if (i != 3 || !aiter.end()) /* we expect exactly 3 arguments here */ return -EINVAL; + add_condition(v[0], v[1], v[2]); } else { add_simple_check(child->get_name(), child->get_data()); diff --git a/src/rgw/rgw_policy_s3.h b/src/rgw/rgw_policy_s3.h index 97cb3ed6a61..77fa13dc293 100644 --- a/src/rgw/rgw_policy_s3.h +++ b/src/rgw/rgw_policy_s3.h @@ -24,15 +24,21 @@ class RGWPolicyCondition; class RGWPolicy { - utime_t expires; + uint64_t expires; std::list<RGWPolicyCondition *> conditions; std::list<pair<std::string, std::string> > var_checks; std::map<std::string, bool, ltstr_nocase> checked_vars; public: - RGWPolicy() {} + int min_length; + int max_length; + + RGWPolicy() : expires(0), min_length(-1), max_length(-1) {} ~RGWPolicy(); - void set_expires(utime_t& e) { expires = e; } + + uint64_t get_current_epoch(); + void set_expires(utime_t& e); + void set_expires(string& e); void set_var_checked(const std::string& var) { checked_vars[var] = true; diff --git a/src/rgw/rgw_rest_s3.cc b/src/rgw/rgw_rest_s3.cc index a6e9414a416..333a55c02fc 100644 --- a/src/rgw/rgw_rest_s3.cc +++ b/src/rgw/rgw_rest_s3.cc @@ -804,6 +804,11 @@ int RGWPostObj_ObjStore_S3::get_params() if (r < 0) return r; + if (post_policy.min_length > -1 && post_policy.max_length > -1) { + min_allowable_content_length = post_policy.min_length; + max_allowable_content_length = post_policy.max_length; + } + return 0; } @@ -867,7 +872,6 @@ int RGWPostObj_ObjStore_S3::get_policy() ldout(s->cct, 0) << "POST policy: " << decoded_policy.c_str() << dendl; - RGWPolicy post_policy; int r = post_policy.from_json(decoded_policy); if (r < 0) { ldout(s->cct, 0) << "failed to parse policy" << dendl; diff --git a/src/rgw/rgw_rest_s3.h b/src/rgw/rgw_rest_s3.h index de5edd26afa..25e67bbf52d 100644 --- a/src/rgw/rgw_rest_s3.h +++ b/src/rgw/rgw_rest_s3.h @@ -100,6 +100,7 @@ class RGWPostObj_ObjStore_S3 : public RGWPostObj_ObjStore { bufferlist in_data; map<string, post_form_part, const ltstr_nocase> parts; RGWPolicyEnv env; + RGWPolicy post_policy; int read_with_boundary(bufferlist& bl, uint64_t max, bool check_eol, bool *reached_boundary, |