summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYehuda Sadeh <yehuda@inktank.com>2013-05-23 12:29:42 -0700
committerYehuda Sadeh <yehuda@inktank.com>2013-05-23 12:29:42 -0700
commitf2f73538d9017af3fec61201e894f69b7cbc3d9e (patch)
treed75a9c2c9200038482079e7ffa5b15131a514907
parentc812bb513aceb3be4ee858df36d3bbab45afccc0 (diff)
downloadceph-f2f73538d9017af3fec61201e894f69b7cbc3d9e.tar.gz
rgw: some code cleanup
move s3 signing code to a different common file. Signed-off-by: Yehuda Sadeh <yehuda@inktank.com>
-rw-r--r--src/Makefile.am2
-rw-r--r--src/rgw/rgw_auth_s3.cc137
-rw-r--r--src/rgw/rgw_auth_s3.h14
-rw-r--r--src/rgw/rgw_rest_client.cc44
-rw-r--r--src/rgw/rgw_rest_s3.cc134
5 files changed, 173 insertions, 158 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 360722e2b01..7762cbb50fc 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -398,6 +398,7 @@ librgw_a_SOURCES = \
rgw/rgw_env.cc \
rgw/rgw_cors.cc \
rgw/rgw_cors_s3.cc \
+ rgw/rgw_auth_s3.cc \
rgw/rgw_metadata.cc
librgw_a_CFLAGS = ${CRYPTO_CFLAGS} ${AM_CFLAGS}
librgw_a_CXXFLAGS = -Woverloaded-virtual ${AM_CXXFLAGS}
@@ -2076,6 +2077,7 @@ noinst_HEADERS = \
rgw/rgw_rest.h\
rgw/rgw_rest_swift.h\
rgw/rgw_rest_s3.h\
+ rgw/rgw_auth_s3.h\
rgw/rgw_rest_admin.h\
rgw/rgw_rest_usage.h\
rgw/rgw_rest_user.h\
diff --git a/src/rgw/rgw_auth_s3.cc b/src/rgw/rgw_auth_s3.cc
new file mode 100644
index 00000000000..e3c08e75526
--- /dev/null
+++ b/src/rgw/rgw_auth_s3.cc
@@ -0,0 +1,137 @@
+
+#include "common/armor.h"
+#include "rgw_common.h"
+
+#define dout_subsys ceph_subsys_rgw
+
+static const char *signed_subresources[] = {
+ "acl",
+ "lifecycle",
+ "location",
+ "logging",
+ "notification",
+ "partNumber",
+ "policy",
+ "requestPayment",
+ "torrent",
+ "uploadId",
+ "uploads",
+ "versionId",
+ "versioning",
+ "versions",
+ "website",
+ NULL
+};
+
+/*
+ * ?get the canonical amazon-style header for something?
+ */
+
+static void get_canon_amz_hdr(map<string, string>& meta_map, string& dest)
+{
+ dest = "";
+ map<string, string>::iterator iter;
+ for (iter = meta_map.begin(); iter != meta_map.end(); ++iter) {
+ dest.append(iter->first);
+ dest.append(":");
+ dest.append(iter->second);
+ dest.append("\n");
+ }
+}
+
+/*
+ * ?get the canonical representation of the object's location
+ */
+static void get_canon_resource(const char *request_uri, map<string, string>& sub_resources, string& dest)
+{
+ string s;
+
+ if (request_uri)
+ s.append(request_uri);
+
+ string append_str;
+
+ const char **p = signed_subresources;
+
+ for (; *p; ++p) {
+ map<string, string>::iterator iter = sub_resources.find(*p);
+ if (iter == sub_resources.end())
+ continue;
+
+ if (append_str.empty())
+ append_str.append("?");
+ else
+ append_str.append("&");
+ append_str.append(iter->first);
+ if (!iter->second.empty()) {
+ append_str.append("=");
+ append_str.append(iter->second);
+ }
+ }
+ if (!append_str.empty()) {
+ s.append(append_str);
+ }
+ dout(10) << "get_canon_resource(): dest=" << dest << dendl;
+
+ dest = s;
+}
+
+/*
+ * get the header authentication information required to
+ * compute a request's signature
+ */
+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)
+{
+ string dest;
+
+ if (method)
+ dest = method;
+ dest.append("\n");
+
+ if (content_md5) {
+ dest.append(content_md5);
+ }
+ dest.append("\n");
+
+ if (content_type)
+ dest.append(content_type);
+ dest.append("\n");
+
+ if (date)
+ dest.append(date);
+ dest.append("\n");
+
+ string canon_amz_hdr;
+ get_canon_amz_hdr(meta_map, canon_amz_hdr);
+ dest.append(canon_amz_hdr);
+
+ string canon_resource;
+ get_canon_resource(request_uri, sub_resources, canon_resource);
+
+ dest.append(canon_resource);
+
+ dest_str = dest;
+}
+
+int rgw_get_s3_header_digest(const string& auth_hdr, const string& key, string& dest)
+{
+ char hmac_sha1[CEPH_CRYPTO_HMACSHA1_DIGESTSIZE];
+ calc_hmac_sha1(key.c_str(), key.size(), auth_hdr.c_str(), auth_hdr.size(), hmac_sha1);
+
+ char b64[64]; /* 64 is really enough */
+ int ret = ceph_armor(b64, b64 + 64, hmac_sha1,
+ hmac_sha1 + CEPH_CRYPTO_HMACSHA1_DIGESTSIZE);
+ if (ret < 0) {
+ dout(10) << "ceph_armor failed" << dendl;
+ return ret;
+ }
+ b64[ret] = '\0';
+
+ dest = b64;
+
+ return 0;
+}
+
+
diff --git a/src/rgw/rgw_auth_s3.h b/src/rgw/rgw_auth_s3.h
new file mode 100644
index 00000000000..63813b91717
--- /dev/null
+++ b/src/rgw/rgw_auth_s3.h
@@ -0,0 +1,14 @@
+#ifndef CEPH_RGW_AUTH_S3_H
+#define CEPH_RGW_AUTH_S3_H
+
+
+#include "rgw_common.h"
+
+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);
+int rgw_get_s3_header_digest(const string& auth_hdr, const string& key, string& dest);
+
+
+
+#endif
diff --git a/src/rgw/rgw_rest_client.cc b/src/rgw/rgw_rest_client.cc
index d3caaa5c849..80d58388a89 100644
--- a/src/rgw/rgw_rest_client.cc
+++ b/src/rgw/rgw_rest_client.cc
@@ -1,5 +1,6 @@
#include "rgw_common.h"
#include "rgw_rest_client.h"
+#include "rgw_auth_s3.h"
#include "rgw_http_errors.h"
#include "common/ceph_crypto_cms.h"
@@ -64,46 +65,28 @@ int RGWRESTClient::execute(RGWAccessKey& key, const char *method, const char *re
}
new_url.append(new_resource);
- if (params.size()) {
- new_url.append("?");
-
- list<pair<string, string> >::iterator iter;
- for (iter = params.begin(); iter != params.end(); ++iter) {
- if (iter != params.begin())
- new_url.append("?");
- new_url.append(iter->first + "=" + iter->second);
- }
- }
-
utime_t tm = ceph_clock_now(cct);
stringstream s;
tm.gmtime(s);
string date_str = s.str();
headers.push_back(make_pair<string, string>("HTTP_DATE", date_str));
- string canonical_header = string(method) + " " +
- "\n" + /* CONTENT_MD5 */
- "\n" + /* CONTENT_TYPE */
- date_str + "\n" +
- "\n" + /* amz headers */
- new_resource;
+ string canonical_header;
+ map<string, string> meta_map;
+ map<string, string> sub_resources;
+ rgw_create_s3_canonical_header(method, NULL, NULL, date_str.c_str(),
+ meta_map, new_url.c_str(), sub_resources,
+ canonical_header);
- string& k = key.key;
-
- char hmac_sha1[CEPH_CRYPTO_HMACSHA1_DIGESTSIZE];
- calc_hmac_sha1(k.c_str(), k.size(), canonical_header.c_str(), canonical_header.size(), hmac_sha1);
-
-#define ARMOR_LEN 64
- char b64[ARMOR_LEN]; /* 64 is really enough */
- int ret = ceph_armor(b64, b64 + ARMOR_LEN, hmac_sha1,
- hmac_sha1 + CEPH_CRYPTO_HMACSHA1_DIGESTSIZE);
+ string digest;
+ int ret = rgw_get_s3_header_digest(canonical_header, key.key, digest);
if (ret < 0) {
- dout(10) << "ceph_armor failed" << dendl;
- return -EPERM;
+ return ret;
}
- b64[ret] = '\0';
- string auth_hdr = "AWS " + key.id + ":" + b64;
+ string auth_hdr = "AWS " + key.id + ":" + digest;
+
+ ldout(cct, 15) << "generated auth header: " << auth_hdr << dendl;
headers.push_back(make_pair<string, string>("AUTHORIZATION", auth_hdr));
int r = process(method, new_url.c_str());
@@ -113,4 +96,3 @@ int RGWRESTClient::execute(RGWAccessKey& key, const char *method, const char *re
return rgw_http_error_to_errno(status);
}
-
diff --git a/src/rgw/rgw_rest_s3.cc b/src/rgw/rgw_rest_s3.cc
index 51ce032678a..082b310f351 100644
--- a/src/rgw/rgw_rest_s3.cc
+++ b/src/rgw/rgw_rest_s3.cc
@@ -7,13 +7,12 @@
#include "rgw_rest.h"
#include "rgw_rest_s3.h"
+#include "rgw_auth_s3.h"
#include "rgw_acl.h"
#include "rgw_policy_s3.h"
#include "rgw_user.h"
#include "rgw_cors.h"
-#include "common/armor.h"
-
#include "rgw_client_io.h"
#define dout_subsys ceph_subsys_rgw
@@ -1901,78 +1900,6 @@ int RGWHandler_ObjStore_S3::init(RGWRados *store, struct req_state *s, RGWClient
return RGWHandler_ObjStore::init(store, s, cio);
}
-static const char *signed_subresources[] = {
- "acl",
- "lifecycle",
- "location",
- "logging",
- "notification",
- "partNumber",
- "policy",
- "requestPayment",
- "torrent",
- "uploadId",
- "uploads",
- "versionId",
- "versioning",
- "versions",
- "website",
- NULL
-};
-
-/*
- * ?get the canonical amazon-style header for something?
- */
-
-static void get_canon_amz_hdr(map<string, string>& meta_map, string& dest)
-{
- dest = "";
- map<string, string>::iterator iter;
- for (iter = meta_map.begin(); iter != meta_map.end(); ++iter) {
- dest.append(iter->first);
- dest.append(":");
- dest.append(iter->second);
- dest.append("\n");
- }
-}
-
-/*
- * ?get the canonical representation of the object's location
- */
-static void get_canon_resource(const char *request_uri, map<string, string>& sub_resources, string& dest)
-{
- string s;
-
- if (request_uri)
- s.append(request_uri);
-
- string append_str;
-
- const char **p = signed_subresources;
-
- for (; *p; ++p) {
- map<string, string>::iterator iter = sub_resources.find(*p);
- if (iter == sub_resources.end())
- continue;
-
- if (append_str.empty())
- append_str.append("?");
- else
- append_str.append("&");
- append_str.append(iter->first);
- if (!iter->second.empty()) {
- append_str.append("=");
- append_str.append(iter->second);
- }
- }
- if (!append_str.empty()) {
- s.append(append_str);
- }
- dout(10) << "get_canon_resource(): dest=" << dest << dendl;
-
- dest = s;
-}
-
static inline bool is_base64_for_content_md5(unsigned char c) {
return (isalnum(c) || isspace(c) || (c == '+') || (c == '/') || (c == '='));
}
@@ -1981,45 +1908,6 @@ static inline bool is_base64_for_content_md5(unsigned char c) {
* get the header authentication information required to
* compute a request's signature
*/
-void rgw_create_s3_auth_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)
-{
- string dest;
-
- if (method)
- dest = method;
- dest.append("\n");
-
- if (content_md5) {
- dest.append(content_md5);
- }
- dest.append("\n");
-
- if (content_type)
- dest.append(content_type);
- dest.append("\n");
-
- if (date)
- dest.append(date);
- dest.append("\n");
-
- string canon_amz_hdr;
- get_canon_amz_hdr(meta_map, canon_amz_hdr);
- dest.append(canon_amz_hdr);
-
- string canon_resource;
- get_canon_resource(request_uri, sub_resources, canon_resource);
-
- dest.append(canon_resource);
-
- dest_str = dest;
-}
-
-/*
- * 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");
@@ -2065,7 +1953,7 @@ static bool get_auth_header(req_info& info, utime_t& header_time, string& dest,
map<string, string>& meta_map = info.x_meta_map;
map<string, string>& sub_resources = info.args.get_sub_resources();
- rgw_create_s3_auth_header(info.method, content_md5, content_type, date.c_str(),
+ rgw_create_s3_canonical_header(info.method, content_md5, content_type, date.c_str(),
meta_map, info.request_uri.c_str(), sub_resources,
dest);
@@ -2147,8 +2035,6 @@ int RGW_Auth_S3::authorize(RGWRados *store, struct req_state *s)
return -EPERM;
}
RGWAccessKey& k = iter->second;
- const char *key = k.key.c_str();
- int key_len = k.key.size();
if (!k.subuser.empty()) {
map<string, RGWSubUser>::iterator uiter = s->user.subusers.find(k.subuser);
@@ -2161,23 +2047,17 @@ int RGW_Auth_S3::authorize(RGWRados *store, struct req_state *s)
} else
s->perm_mask = RGW_PERM_FULL_CONTROL;
- char hmac_sha1[CEPH_CRYPTO_HMACSHA1_DIGESTSIZE];
- calc_hmac_sha1(key, key_len, auth_hdr.c_str(), auth_hdr.size(), hmac_sha1);
-
- char b64[64]; /* 64 is really enough */
- int ret = ceph_armor(b64, b64 + 64, hmac_sha1,
- hmac_sha1 + CEPH_CRYPTO_HMACSHA1_DIGESTSIZE);
+ string digest;
+ int ret = rgw_get_s3_header_digest(auth_hdr, k.key, digest);
if (ret < 0) {
- dout(10) << "ceph_armor failed" << dendl;
return -EPERM;
}
- b64[ret] = '\0';
- dout(15) << "b64=" << b64 << dendl;
+ dout(15) << "calculated digest=" << digest << dendl;
dout(15) << "auth_sign=" << auth_sign << dendl;
- dout(15) << "compare=" << auth_sign.compare(b64) << dendl;
+ dout(15) << "compare=" << auth_sign.compare(digest) << dendl;
- if (auth_sign.compare(b64) != 0)
+ if (auth_sign != digest)
return -EPERM;
if (s->user.system) {