summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYehuda Sadeh <yehuda@inktank.com>2013-05-23 13:09:08 -0700
committerYehuda Sadeh <yehuda@inktank.com>2013-05-23 13:09:08 -0700
commit0c805b6c771bff259239458ccd5431543005c842 (patch)
treec82f4db08997bd9f0e1595cf3dc22e53b4b9a69d
parentf2f73538d9017af3fec61201e894f69b7cbc3d9e (diff)
downloadceph-0c805b6c771bff259239458ccd5431543005c842.tar.gz
rgw: rest_client, forward requests
Signed-off-by: Yehuda Sadeh <yehuda@inktank.com>
-rw-r--r--src/rgw/rgw_auth_s3.cc58
-rw-r--r--src/rgw/rgw_auth_s3.h1
-rw-r--r--src/rgw/rgw_common.h4
-rw-r--r--src/rgw/rgw_env.cc12
-rw-r--r--src/rgw/rgw_rest_client.cc56
-rw-r--r--src/rgw/rgw_rest_client.h1
-rw-r--r--src/rgw/rgw_rest_s3.cc61
7 files changed, 129 insertions, 64 deletions
diff --git a/src/rgw/rgw_auth_s3.cc b/src/rgw/rgw_auth_s3.cc
index e3c08e75526..89cc80d3421 100644
--- a/src/rgw/rgw_auth_s3.cc
+++ b/src/rgw/rgw_auth_s3.cc
@@ -134,4 +134,62 @@ int rgw_get_s3_header_digest(const string& auth_hdr, const string& key, string&
return 0;
}
+static inline bool is_base64_for_content_md5(unsigned char c) {
+ return (isalnum(c) || isspace(c) || (c == '+') || (c == '/') || (c == '='));
+}
+
+/*
+ * get the header authentication information required to
+ * compute a request's signature
+ */
+bool rgw_create_s3_canonical_header(req_info& info, utime_t& header_time, string& dest, bool qsr)
+{
+ const char *content_md5 = info.env->get("HTTP_CONTENT_MD5");
+ if (content_md5) {
+ for (const char *p = content_md5; *p; p++) {
+ if (!is_base64_for_content_md5(*p)) {
+ dout(0) << "NOTICE: bad content-md5 provided (not base64), aborting request p=" << *p << " " << (int)*p << dendl;
+ return false;
+ }
+ }
+ }
+ const char *content_type = info.env->get("CONTENT_TYPE");
+
+ string date;
+ if (qsr) {
+ date = info.args.get("Expires");
+ } else {
+ const char *str = info.env->get("HTTP_DATE");
+ const char *req_date = str;
+ if (str) {
+ date = str;
+ } else {
+ req_date = info.env->get("HTTP_X_AMZ_DATE");
+ if (!req_date) {
+ dout(0) << "NOTICE: missing date for auth header" << dendl;
+ return false;
+ }
+ }
+
+ struct tm t;
+ if (!parse_rfc2616(req_date, &t)) {
+ dout(0) << "NOTICE: failed to parse date for auth header" << dendl;
+ return false;
+ }
+ if (t.tm_year < 70) {
+ dout(0) << "NOTICE: bad date (predates epoch): " << req_date << dendl;
+ return false;
+ }
+ header_time = utime_t(timegm(&t), 0);
+ }
+
+ map<string, string>& meta_map = info.x_meta_map;
+ map<string, string>& sub_resources = info.args.get_sub_resources();
+
+ rgw_create_s3_canonical_header(info.method, content_md5, content_type, date.c_str(),
+ meta_map, info.request_uri.c_str(), sub_resources,
+ dest);
+
+ return true;
+}
diff --git a/src/rgw/rgw_auth_s3.h b/src/rgw/rgw_auth_s3.h
index 63813b91717..c8bfbc92c06 100644
--- a/src/rgw/rgw_auth_s3.h
+++ b/src/rgw/rgw_auth_s3.h
@@ -7,6 +7,7 @@
void rgw_create_s3_canonical_header(const char *method, const char *content_md5, const char *content_type, const char *date,
map<string, string>& meta_map, const char *request_uri, map<string, string>& sub_resources,
string& dest_str);
+bool rgw_create_s3_canonical_header(req_info& info, utime_t& header_time, string& dest, bool qsr);
int rgw_get_s3_header_digest(const string& auth_hdr, const string& key, string& dest);
diff --git a/src/rgw/rgw_common.h b/src/rgw/rgw_common.h
index dc1b0a13bb4..162e4932ff2 100644
--- a/src/rgw/rgw_common.h
+++ b/src/rgw/rgw_common.h
@@ -259,6 +259,10 @@ public:
size_t get_size(const char *name, size_t def_val = 0);
bool exists(const char *name);
bool exists_prefix(const char *prefix);
+
+ void remove(const char *name);
+ void set(const char *name, const char *val);
+ std::map<string, string>& get_map() { return env_map; }
};
class RGWConf {
diff --git a/src/rgw/rgw_env.cc b/src/rgw/rgw_env.cc
index e23fa257d1b..78ac0d41d7a 100644
--- a/src/rgw/rgw_env.cc
+++ b/src/rgw/rgw_env.cc
@@ -92,6 +92,18 @@ bool RGWEnv::exists_prefix(const char *prefix)
return (strncmp(iter->first.c_str(), prefix, strlen(prefix)) == 0);
}
+void RGWEnv::set(const char *name, const char *val)
+{
+ env_map[name] = val;
+}
+
+void RGWEnv::remove(const char *name)
+{
+ map<string, string>::iterator iter = env_map.find(name);
+ if (iter != env_map.end())
+ env_map.erase(iter);
+}
+
void RGWConf::init(CephContext *cct, RGWEnv *env)
{
enable_ops_log = cct->_conf->rgw_enable_ops_log;
diff --git a/src/rgw/rgw_rest_client.cc b/src/rgw/rgw_rest_client.cc
index 80d58388a89..c19a71be617 100644
--- a/src/rgw/rgw_rest_client.cc
+++ b/src/rgw/rgw_rest_client.cc
@@ -52,6 +52,14 @@ int RGWRESTClient::read_header(void *ptr, size_t len)
return 0;
}
+static void get_new_date_str(CephContext *cct, string& date_str)
+{
+ utime_t tm = ceph_clock_now(cct);
+ stringstream s;
+ tm.gmtime(s);
+ date_str = s.str();
+}
+
int RGWRESTClient::execute(RGWAccessKey& key, const char *method, const char *resource)
{
string new_url = url;
@@ -65,10 +73,8 @@ int RGWRESTClient::execute(RGWAccessKey& key, const char *method, const char *re
}
new_url.append(new_resource);
- utime_t tm = ceph_clock_now(cct);
- stringstream s;
- tm.gmtime(s);
- string date_str = s.str();
+ string date_str;
+ get_new_date_str(cct, date_str);
headers.push_back(make_pair<string, string>("HTTP_DATE", date_str));
string canonical_header;
@@ -96,3 +102,45 @@ int RGWRESTClient::execute(RGWAccessKey& key, const char *method, const char *re
return rgw_http_error_to_errno(status);
}
+int RGWRESTClient::forward_request(RGWAccessKey& key, req_info& info)
+{
+
+ RGWEnv new_env = *info.env; /* copy environment */
+
+ string date_str;
+ get_new_date_str(cct, date_str);
+ new_env.set("HTTP_DATE", date_str.c_str());
+
+ req_info new_info(info);
+ new_info.env = &new_env;
+
+ map<string, string>& m = new_env.get_map();
+
+ string canonical_header;
+ utime_t header_time;
+ if (!rgw_create_s3_canonical_header(new_info, header_time, canonical_header, false)) {
+ ldout(cct, 0) << "failed to create canonical s3 header" << dendl;
+ return -EINVAL;
+ }
+
+ string digest;
+ int ret = rgw_get_s3_header_digest(canonical_header, key.key, digest);
+ if (ret < 0) {
+ return ret;
+ }
+
+ string auth_hdr = "AWS " + key.id + ":" + digest;
+ ldout(cct, 15) << "generated auth header: " << auth_hdr << dendl;
+
+ m["AUTHORIZATION"] = auth_hdr;
+
+ map<string, string>::iterator iter;
+ for (iter = m.begin(); iter != m.end(); ++iter) {
+ headers.push_back(make_pair<string, string>(iter->first, iter->second));
+ }
+
+ int r = process(new_info.method, new_info.request_uri.c_str());
+ if (r < 0)
+ return r;
+
+ return rgw_http_error_to_errno(status);}
diff --git a/src/rgw/rgw_rest_client.h b/src/rgw/rgw_rest_client.h
index 95e1f28697d..a117bb12a77 100644
--- a/src/rgw/rgw_rest_client.h
+++ b/src/rgw/rgw_rest_client.h
@@ -28,6 +28,7 @@ public:
int read_header(void *ptr, size_t len);
int execute(RGWAccessKey& key, const char *method, const char *resource);
+ int forward_request(RGWAccessKey& key, req_info& info);
};
diff --git a/src/rgw/rgw_rest_s3.cc b/src/rgw/rgw_rest_s3.cc
index 082b310f351..00305b54d2b 100644
--- a/src/rgw/rgw_rest_s3.cc
+++ b/src/rgw/rgw_rest_s3.cc
@@ -1900,65 +1900,6 @@ int RGWHandler_ObjStore_S3::init(RGWRados *store, struct req_state *s, RGWClient
return RGWHandler_ObjStore::init(store, s, cio);
}
-static inline bool is_base64_for_content_md5(unsigned char c) {
- return (isalnum(c) || isspace(c) || (c == '+') || (c == '/') || (c == '='));
-}
-
-/*
- * get the header authentication information required to
- * compute a request's signature
- */
-static bool get_auth_header(req_info& info, utime_t& header_time, string& dest, bool qsr)
-{
- const char *content_md5 = info.env->get("HTTP_CONTENT_MD5");
- if (content_md5) {
- for (const char *p = content_md5; *p; p++) {
- if (!is_base64_for_content_md5(*p)) {
- dout(0) << "NOTICE: bad content-md5 provided (not base64), aborting request p=" << *p << " " << (int)*p << dendl;
- return false;
- }
- }
- }
-
- const char *content_type = info.env->get("CONTENT_TYPE");
-
- string date;
- if (qsr) {
- date = info.args.get("Expires");
- } else {
- const char *str = info.env->get("HTTP_DATE");
- const char *req_date = str;
- if (str) {
- date = str;
- } else {
- req_date = info.env->get("HTTP_X_AMZ_DATE");
- if (!req_date) {
- dout(0) << "NOTICE: missing date for auth header" << dendl;
- return false;
- }
- }
-
- struct tm t;
- if (!parse_rfc2616(req_date, &t)) {
- dout(0) << "NOTICE: failed to parse date for auth header" << dendl;
- return false;
- }
- if (t.tm_year < 70) {
- dout(0) << "NOTICE: bad date (predates epoch): " << req_date << dendl;
- return false;
- }
- header_time = utime_t(timegm(&t), 0);
- }
-
- map<string, string>& meta_map = info.x_meta_map;
- map<string, string>& sub_resources = info.args.get_sub_resources();
-
- rgw_create_s3_canonical_header(info.method, content_md5, content_type, date.c_str(),
- meta_map, info.request_uri.c_str(), sub_resources,
- dest);
-
- return true;
-}
/*
* verify that a signed request comes from the keyholder
@@ -2015,7 +1956,7 @@ int RGW_Auth_S3::authorize(RGWRados *store, struct req_state *s)
/* now verify signature */
string auth_hdr;
- if (!get_auth_header(s->info, s->header_time, auth_hdr, qsr)) {
+ if (!rgw_create_s3_canonical_header(s->info, s->header_time, auth_hdr, qsr)) {
dout(10) << "failed to create auth header\n" << auth_hdr << dendl;
return -EPERM;
}