summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYehuda Sadeh <yehuda@inktank.com>2012-10-09 11:24:46 -0700
committerYehuda Sadeh <yehuda@inktank.com>2012-10-23 10:43:09 -0700
commitccd757f019e4012a5c0ecde0ae623b7126964d35 (patch)
tree6a035d3b23629521bc9545859db850b506a44fd8
parent5b90d10bc25372f8a0b34f1c958daa9ec42b0518 (diff)
downloadceph-ccd757f019e4012a5c0ecde0ae623b7126964d35.tar.gz
rgw: add policy decoding code
merge in changes from commit 57668c14 by caleb Signed-off-by: Yehuda Sadeh <yehuda@inktank.com>
-rw-r--r--src/rgw/rgw_rest_s3.cc113
-rw-r--r--src/rgw/rgw_rest_s3.h5
2 files changed, 112 insertions, 6 deletions
diff --git a/src/rgw/rgw_rest_s3.cc b/src/rgw/rgw_rest_s3.cc
index cac98396b06..0850fd425d9 100644
--- a/src/rgw/rgw_rest_s3.cc
+++ b/src/rgw/rgw_rest_s3.cc
@@ -8,6 +8,7 @@
#include "rgw_rest.h"
#include "rgw_rest_s3.h"
#include "rgw_acl.h"
+#include "rgw_policy_s3.h"
#include "common/armor.h"
@@ -655,6 +656,16 @@ bool RGWPostObj_ObjStore_S3::part_str(const string& name, string *val)
return true;
}
+bool RGWPostObj_ObjStore_S3::part_bl(const string& name, bufferlist *pbl)
+{
+ map<string, struct post_form_part, ltstr_nocase>::iterator iter = parts.find(name);
+ if (iter == parts.end())
+ return false;
+
+ *pbl = iter->second.data;
+ return true;
+}
+
int RGWPostObj_ObjStore_S3::get_params()
{
string temp_line;
@@ -692,6 +703,9 @@ int RGWPostObj_ObjStore_S3::get_params()
}
}
+ ldout(s->cct, 20) << "adding bucket to policy env: " << s->bucket.name << dendl;
+ env.add_var("bucket", s->bucket.name);
+
map<string, string>::iterator iter = params.find("boundary");
if (iter == params.end())
return -EINVAL;
@@ -707,13 +721,13 @@ int RGWPostObj_ObjStore_S3::get_params()
if (r < 0)
return r;
- if (s->cct->_conf->subsys.should_gather(ceph_subsys_rgw, 20)) {
+ map<string, struct post_part_field>::iterator piter;
+ for (piter = part.fields.begin(); piter != part.fields.end(); ++piter) {
ldout(s->cct, 20) << "read part header: name=" << part.name << " content_type=" << part.content_type << dendl;
- ldout(s->cct, 20) << "params:" << dendl;
- map<string, struct post_part_field>::iterator piter;
- for (piter = part.fields.begin(); piter != part.fields.end(); ++piter) {
- ldout(s->cct, 20) << "name=" << piter->first << dendl;
- ldout(s->cct, 20) << "val=" << piter->second.val << dendl;
+ ldout(s->cct, 20) << "name=" << piter->first << dendl;
+ ldout(s->cct, 20) << "val=" << piter->second.val << dendl;
+ if (s->cct->_conf->subsys.should_gather(ceph_subsys_rgw, 20)) {
+ ldout(s->cct, 20) << "params:" << dendl;
map<string, string>& params = piter->second.params;
for (iter = params.begin(); iter != params.end(); ++iter) {
ldout(s->cct, 20) << " " << iter->first << " -> " << iter->second << dendl;
@@ -736,12 +750,15 @@ int RGWPostObj_ObjStore_S3::get_params()
return -EINVAL;
}
parts[part.name] = part;
+ string part_str(part.data.c_str(), part.data.length());
+ env.add_var(part.name, part_str);
} while (!done);
if (!part_str("key", &s->object_str))
return -EINVAL;
part_str("Content-Type", &content_type);
+ env.add_var("Content-Type", content_type);
map<string, struct post_form_part, ltstr_nocase>::iterator piter = parts.upper_bound(RGW_AMZ_META_PREFIX);
for (; piter != parts.end(); ++piter) {
@@ -762,6 +779,90 @@ int RGWPostObj_ObjStore_S3::get_params()
attrs[attr_name] = attr_bl;
}
+ int r = get_policy();
+ if (r < 0)
+ return r;
+
+ return 0;
+}
+
+int RGWPostObj_ObjStore_S3::get_policy()
+{
+ bufferlist encoded_policy;
+ string uid;
+
+ if (part_bl("policy", &encoded_policy)) {
+
+ // check that the signature matches the encoded policy
+ string s3_access_key;
+ if (!part_str("AWSAccessKeyId", &s3_access_key)) {
+ ldout(s->cct, 0) << "No S3 access key found!" << dendl;
+ return -EINVAL;
+ }
+ string signature_str;
+ if (!part_str("signature", &signature_str)) {
+ ldout(s->cct, 0) << "No signature found!" << dendl;
+ return -EINVAL;
+ }
+
+ RGWUserInfo user_info;
+
+ ret = rgw_get_user_info_by_access_key(store, s3_access_key, user_info);
+ if (ret < 0) {
+ ldout(s->cct, 0) << "User lookup failed!" << dendl;
+ return -EINVAL;
+ }
+
+ map<string, RGWAccessKey> access_keys = user_info.access_keys;
+
+ map<string, RGWAccessKey>::const_iterator iter = access_keys.begin();
+ string s3_secret_key = (iter->second).key;
+
+ char calc_signature[CEPH_CRYPTO_HMACSHA1_DIGESTSIZE];
+
+ calc_hmac_sha1(s3_secret_key.c_str(), s3_secret_key.size(), encoded_policy.c_str(), encoded_policy.length(), calc_signature);
+ bufferlist encoded_hmac;
+ bufferlist raw_hmac;
+ raw_hmac.append(calc_signature, CEPH_CRYPTO_HMACSHA1_DIGESTSIZE);
+ raw_hmac.encode_base64(encoded_hmac);
+ encoded_hmac.append((char)0); /* null terminate */
+
+ if (signature_str.compare(encoded_hmac.c_str()) != 0) {
+ ldout(s->cct, 0) << "Signature verification failed!" << dendl;
+ ldout(s->cct, 0) << "expected: " << signature_str.c_str() << dendl;
+ ldout(s->cct, 0) << "got: " << encoded_hmac.c_str() << dendl;
+ return -EINVAL;
+ }
+ ldout(s->cct, 0) << "Successful Signature Verification!" << dendl;
+ bufferlist decoded_policy;
+ try {
+ decoded_policy.decode_base64(encoded_policy);
+ } catch (buffer::error& err) {
+ ldout(s->cct, 0) << "failed to decode_base64 policy" << dendl;
+ return -EINVAL;
+ }
+
+ decoded_policy.append('\0'); // NULL terminate
+
+ 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;
+ return -EINVAL;
+ }
+
+ if (!post_policy.check(&env)) {
+ ldout(s->cct, 0) << "policy check failed" << dendl;
+ return -EINVAL;
+ }
+
+ s->user = user_info;
+ } else {
+ ldout(s->cct, 0) << "No attached policy found!" << dendl;
+ }
+
string canned_acl;
part_str("acl", &canned_acl);
diff --git a/src/rgw/rgw_rest_s3.h b/src/rgw/rgw_rest_s3.h
index 964e1d9722a..6839c8928cc 100644
--- a/src/rgw/rgw_rest_s3.h
+++ b/src/rgw/rgw_rest_s3.h
@@ -5,6 +5,7 @@
#include "rgw_op.h"
#include "rgw_html_errors.h"
#include "rgw_acl_s3.h"
+#include "rgw_policy_s3.h"
#define RGW_AUTH_GRACE_MINS 15
@@ -105,6 +106,7 @@ class RGWPostObj_ObjStore_S3 : public RGWPostObj_ObjStore {
string boundary;
bufferlist in_data;
map<string, post_form_part, const ltstr_nocase> parts;
+ RGWPolicyEnv env;
int read_with_boundary(bufferlist& bl, uint64_t max, bool check_eol,
bool *reached_boundary,
@@ -118,6 +120,9 @@ class RGWPostObj_ObjStore_S3 : public RGWPostObj_ObjStore {
int read_form_part_header(struct post_form_part *part,
bool *done);
bool part_str(const string& name, string *val);
+ bool part_bl(const string& name, bufferlist *pbl);
+
+ int get_policy();
public:
RGWPostObj_ObjStore_S3() {}
~RGWPostObj_ObjStore_S3() {}