diff options
author | Yehuda Sadeh <yehuda@inktank.com> | 2013-05-23 12:29:42 -0700 |
---|---|---|
committer | Yehuda Sadeh <yehuda@inktank.com> | 2013-05-23 12:29:42 -0700 |
commit | f2f73538d9017af3fec61201e894f69b7cbc3d9e (patch) | |
tree | d75a9c2c9200038482079e7ffa5b15131a514907 | |
parent | c812bb513aceb3be4ee858df36d3bbab45afccc0 (diff) | |
download | ceph-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.am | 2 | ||||
-rw-r--r-- | src/rgw/rgw_auth_s3.cc | 137 | ||||
-rw-r--r-- | src/rgw/rgw_auth_s3.h | 14 | ||||
-rw-r--r-- | src/rgw/rgw_rest_client.cc | 44 | ||||
-rw-r--r-- | src/rgw/rgw_rest_s3.cc | 134 |
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) { |