move s3 signing code to a different common file.
Signed-off-by: Yehuda Sadeh <yehuda@inktank.com>
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}
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\
--- /dev/null
+
+#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;
+}
+
+
--- /dev/null
+#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
#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"
}
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());
return rgw_http_error_to_errno(status);
}
-
#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
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 == '='));
}
-/*
- * 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
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);
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);
} 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) {