* Try to validate S3 auth against keystone s3token interface
*/
std::pair<boost::optional<rgw::keystone::TokenEnvelope>, int>
-EC2Engine::get_from_keystone(const std::string& access_key_id,
+EC2Engine::get_from_keystone(const boost::string_view& access_key_id,
const std::string& string_to_sign,
- const std::string& signature) const
+ const boost::string_view& signature) const
{
/* prepare keystone url */
std::string keystone_url = config.get_endpoint_url();
JSONFormatter credentials(false);
credentials.open_object_section("");
credentials.open_object_section("credentials");
- credentials.dump_string("access", access_key_id);
+ credentials.dump_string("access", sview2cstr(access_key_id).data());
credentials.dump_string("token", rgw::to_base64(string_to_sign));
- credentials.dump_string("signature", signature);
+ credentials.dump_string("signature", sview2cstr(signature).data());
credentials.close_section();
credentials.close_section();
}
rgw::auth::Engine::result_t EC2Engine::authenticate(
- const std::string& access_key_id,
- const std::string& signature,
+ const boost::string_view& access_key_id,
+ const boost::string_view& signature,
const std::string& string_to_sign,
const signature_factory_t& signature_factory,
const completer_factory_t& completer_factory,
#include <utility>
#include <boost/optional.hpp>
+#include <boost/utility/string_view.hpp>
#include "rgw_auth.h"
#include "rgw_rest_s3.h"
const std::vector<std::string>& admin_roles
) const noexcept;
std::pair<boost::optional<token_envelope_t>, int>
- get_from_keystone(const std::string& access_key_id,
+ get_from_keystone(const boost::string_view& access_key_id,
const std::string& string_to_sign,
- const std::string& signature) const;
- result_t authenticate(const std::string& access_key_id,
- const std::string& signature,
+ const boost::string_view& signature) const;
+ result_t authenticate(const boost::string_view& access_key_id,
+ const boost::string_view& signature,
const std::string& string_to_sign,
const signature_factory_t& signature_factory,
const completer_factory_t& completer_factory,
#include "rgw_rest.h"
#include "rgw_crypt_sanitize.h"
-#include "include/str_list.h"
#include <boost/utility/string_view.hpp>
#define dout_context g_ceph_context
/* FIXME(rzarzynski): duplicated from rgw_rest_s3.h. */
#define RGW_AUTH_GRACE_MINS 15
-static inline int parse_v4_credentials_qs(const req_info& info, /* in */
- std::string& credential, /* out */
- std::string& signedheaders, /* out */
- std::string& signature, /* out */
- std::string& date) /* out */
+static inline int parse_v4_query_string(const req_info& info, /* in */
+ boost::string_view& credential, /* out */
+ boost::string_view& signedheaders, /* out */
+ boost::string_view& signature, /* out */
+ boost::string_view& date) /* out */
{
/* auth ships with req params ... */
date = info.args.get("X-Amz-Date");
struct tm date_t;
- if (!parse_iso8601(date.c_str(), &date_t, NULL, false))
+ if (!parse_iso8601(sview2cstr(date).data(), &date_t, nullptr, false)) {
return -EPERM;
+ }
/* Used for pre-signatured url, We shouldn't return -ERR_REQUEST_TIME_SKEWED
* when current time <= X-Amz-Expires */
uint64_t now_req = 0;
uint64_t now = ceph_clock_now();
- std::string expires = info.args.get("X-Amz-Expires");
+ boost::string_view expires = info.args.get("X-Amz-Expires");
if (!expires.empty()) {
/* X-Amz-Expires provides the time period, in seconds, for which
the generated presigned URL is valid. The minimum value
you can set is 1, and the maximum is 604800 (seven days) */
- time_t exp = atoll(expires.c_str());
+ time_t exp = atoll(expires.data());
if ((exp < 1) || (exp > 7*24*60*60)) {
dout(10) << "NOTICE: exp out of range, exp = " << exp << dendl;
return -EPERM;
return 0;
}
-static inline int parse_v4_credentials_hdrs(const req_info& info, /* in */
- std::string& credential, /* out */
- std::string& signedheaders, /* out */
- std::string& signature, /* out */
- std::string& date) /* out */
+namespace {
+static bool get_next_token(const boost::string_view& s,
+ size_t& pos,
+ const char* const delims,
+ boost::string_view& token)
{
- /* auth ships in headers ... */
+ const size_t start = s.find_first_not_of(delims, pos);
+ if (start == boost::string_view::npos) {
+ pos = s.size();
+ return false;
+ }
- /* ------------------------- handle Credential header */
+ size_t end = s.find_first_of(delims, start);
+ if (end != boost::string_view::npos)
+ pos = end + 1;
+ else {
+ pos = end = s.size();
+ }
- const char* const http_auth = info.env->get("HTTP_AUTHORIZATION");
- string auth_str = http_auth;
+ token = s.substr(start, end - start);
+ return true;
+}
- constexpr size_t min_len = strlen(AWS4_HMAC_SHA256_STR) + 1;
- if (auth_str.length() < min_len) {
- dout(10) << "credentials string is too short" << dendl;
- return -EINVAL;
+std::vector<boost::string_view> get_str_vec(const boost::string_view& str,
+ const char* const delims)
+{
+ std::vector<boost::string_view> str_vec;
+
+ size_t pos = 0;
+ boost::string_view token;
+ while (pos < str.size()) {
+ if (get_next_token(str, pos, delims, token)) {
+ if (token.size() > 0) {
+ str_vec.push_back(token);
+ }
+ }
}
- list<string> auth_list;
- get_str_list(auth_str.substr(min_len), ",", auth_list);
+ return str_vec;
+}
- map<string, string> kv;
+std::vector<boost::string_view> get_str_vec(const boost::string_view& str)
+{
+ const char delims[] = ";,= \t";
+ return get_str_vec(str, delims);
+}
+};
- for (string& s : auth_list) {
- string key, val;
- int ret = parse_key_value(s, key, val);
- if (ret < 0) {
- dout(10) << "NOTICE: failed to parse auth header (s=" << s << ")" << dendl;
+static inline int parse_v4_auth_header(const req_info& info, /* in */
+ boost::string_view& credential, /* out */
+ boost::string_view& signedheaders, /* out */
+ boost::string_view& signature, /* out */
+ boost::string_view& date) /* out */
+{
+ boost::string_view input(info.env->get("HTTP_AUTHORIZATION", ""));
+ try {
+ input = input.substr(::strlen(AWS4_HMAC_SHA256_STR) + 1);
+ } catch (std::out_of_range&) {
+ /* We should never ever run into this situation as the presence of
+ * AWS4_HMAC_SHA256_STR had been verified earlier. */
+ dout(10) << "credentials string is too short" << dendl;
+ return -EINVAL;
+ }
+
+ std::map<boost::string_view, boost::string_view> kv;
+ for (const auto& s : get_str_vec(input, ",")) {
+ const auto parsed_pair = parse_key_value(s);
+ if (parsed_pair) {
+ kv[parsed_pair->first] = parsed_pair->second;
+ } else {
+ dout(10) << "NOTICE: failed to parse auth header (s=" << s << ")"
+ << dendl;
return -EINVAL;
}
- kv[key] = std::move(val);
}
- static std::array<string, 3> aws4_presigned_required_keys = {
+ static const std::array<boost::string_view, 3> required_keys = {
"Credential",
"SignedHeaders",
"Signature"
};
- for (string& k : aws4_presigned_required_keys) {
- if (kv.find(k) == kv.end()) {
+ /* Ensure that the presigned required keys are really there. */
+ for (const auto& k : required_keys) {
+ if (kv.find(k) == std::end(kv)) {
dout(10) << "NOTICE: auth header missing key: " << k << dendl;
return -EINVAL;
}
}
- credential = std::move(kv["Credential"]);
- signedheaders = std::move(kv["SignedHeaders"]);
- signature = std::move(kv["Signature"]);
+ credential = kv["Credential"];
+ signedheaders = kv["SignedHeaders"];
+ signature = kv["Signature"];
/* sig hex str */
dout(10) << "v4 signature format = " << signature << dendl;
return 0;
}
-int parse_credentials(const req_info& info, /* in */
- std::string& access_key_id, /* out */
- std::string& credential_scope, /* out */
- std::string& signedheaders, /* out */
- std::string& signature, /* out */
- std::string& date, /* out */
- bool& using_qs) /* out */
+int parse_credentials(const req_info& info, /* in */
+ boost::string_view& access_key_id, /* out */
+ boost::string_view& credential_scope, /* out */
+ boost::string_view& signedheaders, /* out */
+ boost::string_view& signature, /* out */
+ boost::string_view& date, /* out */
+ bool& using_qs) /* out */
{
const char* const http_auth = info.env->get("HTTP_AUTHORIZATION");
using_qs = http_auth == nullptr || http_auth[0] == '\0';
int ret;
- std::string credential;
+ boost::string_view credential;
if (using_qs) {
- ret = parse_v4_credentials_qs(info, credential, signedheaders,
- signature, date);
+ ret = parse_v4_query_string(info, credential, signedheaders,
+ signature, date);
} else {
- ret = parse_v4_credentials_hdrs(info, credential, signedheaders,
- signature, date);
+ ret = parse_v4_auth_header(info, credential, signedheaders,
+ signature, date);
}
if (ret < 0) {
boost::optional<std::string>
get_v4_canonical_headers(const req_info& info,
- const std::string& signedheaders,
+ const boost::string_view& signedheaders,
const bool using_qs,
const bool force_boto2_compat)
{
map<string, string> canonical_hdrs_map;
- istringstream sh(signedheaders);
+ istringstream sh(signedheaders.to_string());
string token;
string port = info.env->get("SERVER_PORT", "");
string secure_port = info.env->get("SERVER_PORT_SECURE", "");
const std::string& canonical_uri,
const std::string& canonical_qs,
const std::string& canonical_hdrs,
- const std::string& signed_hdrs,
+ const boost::string_view& signed_hdrs,
const boost::string_view& request_payload_hash)
{
ldout(cct, 10) << "payload request hash = " << request_payload_hash << dendl;
.append("\n")
.append(canonical_hdrs)
.append("\n")
- .append(signed_hdrs)
+ .append(signed_hdrs.data(), signed_hdrs.length())
.append("\n")
.append(request_payload_hash.data(), request_payload_hash.length());
{
std::string string_to_sign = "AWS4-HMAC-SHA256-PAYLOAD\n";
- string_to_sign.append(date + "\n");
- string_to_sign.append(credential_scope + "\n");
- string_to_sign.append(prev_chunk_signature + "\n");
- string_to_sign.append(std::string(AWS4_EMPTY_PAYLOAD_HASH) + "\n");
+ string_to_sign.append(date.data(), date.length());
+ string_to_sign.append("\n");
+ string_to_sign.append(credential_scope.data(), credential_scope.length());
+ string_to_sign.append("\n");
+ string_to_sign.append(prev_chunk_signature);
+ string_to_sign.append("\n");
+ string_to_sign.append(AWS4_EMPTY_PAYLOAD_HASH, strlen(AWS4_EMPTY_PAYLOAD_HASH));
+ string_to_sign.append("\n");
string_to_sign.append(payload_hash);
ldout(cct, 20) << "AWSv4ComplMulti: string_to_sign=\n" << string_to_sign
rgw::auth::Completer::cmplptr_t
AWSv4ComplMulti::create(const req_state* const s,
- std::string date,
- std::string credential_scope,
- std::string seed_signature,
+ boost::string_view date,
+ boost::string_view credential_scope,
+ boost::string_view seed_signature,
const boost::optional<std::string>& secret_key)
{
if (!secret_key) {
CephContext* const cct;
- /* TODO(rzarzynski): move to boost::string_ref. This should be just fine
- * as (all?) parameters here are actually views over req_info. */
- const std::string date;
- const std::string credential_scope;
+ const boost::string_view date;
+ const boost::string_view credential_scope;
const signing_key_t signing_key;
class ChunkMeta {
signature(signature.to_string()) {
}
- ChunkMeta(const boost::string_ref signature)
+ ChunkMeta(const boost::string_view& signature)
: signature(signature.to_string()) {
}
/* Factory: create an object representing metadata of first, initial chunk
* in a stream. */
- static ChunkMeta create_first(const boost::string_ref seed_signature) {
+ static ChunkMeta create_first(const boost::string_view& seed_signature) {
return ChunkMeta(seed_signature);
}
/* We need the constructor to be public because of the std::make_shared that
* is employed by the create() method. */
AWSv4ComplMulti(const req_state* const s,
- std::string date,
- std::string credential_scope,
- std::string seed_signature,
+ boost::string_view date,
+ boost::string_view credential_scope,
+ boost::string_view seed_signature,
const signing_key_t& signing_key)
: io_base_t(nullptr),
cct(s->cct),
/* Factories. */
static cmplptr_t create(const req_state* s,
- std::string date,
- std::string credential_scope,
- std::string seed_signature,
+ boost::string_view date,
+ boost::string_view credential_scope,
+ boost::string_view seed_signature,
const boost::optional<std::string>& secret_key);
};
static constexpr char AWS4_EMPTY_PAYLOAD_HASH[] = \
"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855";
-int parse_credentials(const req_info& info, /* in */
- std::string& access_key_id, /* out */
- std::string& credential_scope, /* out */
- std::string& signedheaders, /* out */
- std::string& signature, /* out */
- std::string& date, /* out */
- bool& using_qs); /* out */
+int parse_credentials(const req_info& info, /* in */
+ boost::string_view& access_key_id, /* out */
+ boost::string_view& credential_scope, /* out */
+ boost::string_view& signedheaders, /* out */
+ boost::string_view& signature, /* out */
+ boost::string_view& date, /* out */
+ bool& using_qs); /* out */
static inline std::string get_v4_canonical_uri(const req_info& info) {
/* The code should normalize according to RFC 3986 but S3 does NOT do path
std::string get_v4_canonical_qs(const req_info& info, bool using_qs);
-boost::optional<std::string> get_v4_canonical_headers(const req_info& info,
- const std::string& signedheaders,
- bool using_qs,
- bool force_boto2_compat);
+boost::optional<std::string>
+get_v4_canonical_headers(const req_info& info,
+ const boost::string_view& signedheaders,
+ bool using_qs,
+ bool force_boto2_compat);
extern sha256_digest_t
get_v4_canon_req_hash(CephContext* cct,
const std::string& canonical_uri,
const std::string& canonical_qs,
const std::string& canonical_hdrs,
- const std::string& signed_hdrs,
+ const boost::string_view& signed_hdrs,
const boost::string_view& request_payload_hash);
std::string get_v4_string_to_sign(CephContext* cct,
#define RGW_B64_H
#include <boost/utility/string_ref.hpp>
+#include <boost/utility/string_view.hpp>
#include <boost/archive/iterators/base64_from_binary.hpp>
#include <boost/archive/iterators/binary_from_base64.hpp>
#include <boost/archive/iterators/insert_linebreaks.hpp>
* A header-only Base64 encoder built on boost::archive. The
* formula is based on a class poposed for inclusion in boost in
* 2011 by Denis Shevchenko (abandoned), updated slightly
- * (e.g., uses boost::string_ref).
+ * (e.g., uses boost::string_view).
*
* Also, wrap_width added as template argument, based on
* feedback from Marcus.
*/
template<int wrap_width = std::numeric_limits<int>::max()>
- inline std::string to_base64(boost::string_ref sref)
+ inline std::string to_base64(boost::string_view sview)
{
using namespace boost::archive::iterators;
// output must be =padded modulo 3
- auto psize = sref.size();
+ auto psize = sview.size();
while ((psize % 3) != 0) {
++psize;
}
insert_linebreaks<
base64_from_binary<
transform_width<
- boost::string_ref::const_iterator
+ boost::string_view::const_iterator
,6,8>
>
,wrap_width
> b64_iter;
- std::string outstr(b64_iter(sref.data()),
- b64_iter(sref.data() + sref.size()));
+ std::string outstr(b64_iter(sview.data()),
+ b64_iter(sview.data() + sview.size()));
// pad outstr with '=' to a length that is a multiple of 3
- for (size_t ix = 0; ix < (psize-sref.size()); ++ix)
+ for (size_t ix = 0; ix < (psize-sview.size()); ++ix)
outstr.push_back('=');
return outstr;
}
- inline std::string from_base64(boost::string_ref sref)
+ inline std::string from_base64(boost::string_view sview)
{
using namespace boost::archive::iterators;
- if (sref.empty())
+ if (sview.empty())
return std::string();
/* MIME-compliant input will have line-breaks, so we have to
* filter WS */
transform_width<
binary_from_base64<
remove_whitespace<
- boost::string_ref::const_iterator>>
+ boost::string_view::const_iterator>>
,8,6
> b64_iter;
- while (sref.back() == '=')
- sref.remove_suffix(1);
+ while (sview.back() == '=')
+ sview.remove_suffix(1);
- std::string outstr(b64_iter(sref.data()),
- b64_iter(sref.data() + sref.size()));
+ std::string outstr(b64_iter(sview.data()),
+ b64_iter(sview.data() + sview.size()));
return outstr;
}
-
} /* namespace */
#endif /* RGW_B64_H */
dst = src.substr(start, end - start + 1);
}
+static boost::string_view trim_whitespace(const boost::string_view& src)
+{
+ const char* spacestr = " \t\n\r\f\v";
+ const size_t start = src.find_first_not_of(spacestr);
+ if (start == boost::string_view::npos) {
+ return boost::string_view();
+ }
+
+ const size_t end = src.find_last_not_of(spacestr);
+ return src.substr(start, end - start + 1);
+}
static bool check_str_end(const char *s)
{
if (!s)
dout(0) << "parse_iso8601 failed" << dendl;
return false;
}
- string str;
- trim_whitespace(p, str);
+ const boost::string_view str = trim_whitespace(p);
int len = str.size();
if (len == 0 || (len == 1 && str[0] == 'Z'))
return false;
uint32_t ms;
- string nsstr = str.substr(1, len - 2);
- int r = stringtoul(nsstr, &ms);
+ boost::string_view nsstr = str.substr(1, len - 2);
+ int r = stringtoul(nsstr.to_string(), &ms);
if (r < 0)
return false;
return parse_key_value(in_str, "=", key,val);
}
+boost::optional<std::pair<boost::string_view, boost::string_view>>
+parse_key_value(const boost::string_view& in_str,
+ const boost::string_view& delim)
+{
+ const size_t pos = in_str.find(delim);
+ if (pos == boost::string_view::npos) {
+ return boost::none;
+ }
+
+ const auto key = trim_whitespace(in_str.substr(0, pos));
+ const auto val = trim_whitespace(in_str.substr(pos + 1));
+
+ return std::make_pair(key, val);
+}
+
+boost::optional<std::pair<boost::string_view, boost::string_view>>
+parse_key_value(const boost::string_view& in_str)
+{
+ return parse_key_value(in_str, "=");
+}
+
int parse_time(const char *time_str, real_time *time)
{
struct tm tm;
return src.substr(start, end - start + 1);
}
-boost::string_ref rgw_trim_whitespace(const boost::string_ref& src)
+boost::string_view rgw_trim_whitespace(const boost::string_view& src)
{
- boost::string_ref res = src;
+ boost::string_view res = src;
while (res.size() > 0 && std::isspace(res.front())) {
res.remove_prefix(1);
{
int pos = cap.find('=');
if (pos >= 0) {
- trim_whitespace(cap.substr(0, pos), type);
+ type = trim_whitespace(cap.substr(0, pos)).to_string();
}
if (!is_valid_cap_type(type))
extern void parse_csv_string(const string& ival, vector<string>& ovals);
extern int parse_key_value(string& in_str, string& key, string& val);
extern int parse_key_value(string& in_str, const char *delim, string& key, string& val);
+
+extern boost::optional<std::pair<boost::string_view, boost::string_view>>
+parse_key_value(const boost::string_view& in_str,
+ const boost::string_view& delim);
+extern boost::optional<std::pair<boost::string_view, boost::string_view>>
+parse_key_value(const boost::string_view& in_str);
+
+
/** time parsing */
extern int parse_time(const char *time_str, real_time *time);
extern bool parse_rfc2616(const char *s, struct tm *t);
extern bool parse_iso8601(const char *s, struct tm *t, uint32_t *pns = NULL, bool extended_format = true);
extern string rgw_trim_whitespace(const string& src);
-extern boost::string_ref rgw_trim_whitespace(const boost::string_ref& src);
+extern boost::string_view rgw_trim_whitespace(const boost::string_view& src);
extern string rgw_trim_quotes(const string& val);
extern void rgw_to_iso8601(const real_time& t, char *dest, int buf_size);
#include <rgw/rgw_b64.h>
#include <rgw/rgw_rest_s3.h>
#include "include/assert.h"
-#include <boost/utility/string_ref.hpp>
+#include <boost/utility/string_view.hpp>
#include <rgw/rgw_keystone.h>
#include "include/str_map.h"
#include "crypto/crypto_accel.h"
}
static int request_key_from_barbican(CephContext *cct,
- boost::string_ref key_id,
- boost::string_ref key_selector,
+ boost::string_view key_id,
+ boost::string_view key_selector,
const std::string& barbican_token,
std::string& actual_key) {
std::string secret_url;
}
static int get_actual_key_from_kms(CephContext *cct,
- boost::string_ref key_id,
- boost::string_ref key_selector,
+ boost::string_view key_id,
+ boost::string_view key_selector,
std::string& actual_key)
{
int res = 0;
static inline void set_attr(map<string, bufferlist>& attrs,
const char* key,
- boost::string_ref value)
+ boost::string_view value)
{
bufferlist bl;
bl.append(value.data(), value.size());
{"HTTP_X_AMZ_SERVER_SIDE_ENCRYPTION_AWS_KMS_KEY_ID", "x-amz-server-side-encryption-aws-kms-key-id"},
};
-static boost::string_ref get_crypt_attribute(
+static boost::string_view get_crypt_attribute(
RGWEnv* env,
std::map<std::string,
RGWPostObj_ObjStore::post_form_part,
auto iter
= parts->find(crypt_options[option].post_part_name);
if (iter == parts->end())
- return boost::string_ref();
+ return boost::string_view();
bufferlist& data = iter->second.data;
- boost::string_ref str = boost::string_ref(data.c_str(), data.length());
+ boost::string_view str = boost::string_view(data.c_str(), data.length());
return rgw_trim_whitespace(str);
} else {
const char* hdr = env->get(crypt_options[option].http_header_name, nullptr);
if (hdr != nullptr) {
- return boost::string_ref(hdr);
+ return boost::string_view(hdr);
} else {
- return boost::string_ref();
+ return boost::string_view();
}
}
}
int res = 0;
crypt_http_responses.clear();
{
- boost::string_ref req_sse_ca =
+ boost::string_view req_sse_ca =
get_crypt_attribute(s->info.env, parts, X_AMZ_SERVER_SIDE_ENCRYPTION_CUSTOMER_ALGORITHM);
if (! req_sse_ca.empty()) {
if (req_sse_ca != "AES256") {
if (key_bin.size() != AES_256_CBC::AES_256_KEYSIZE) {
return -ERR_INVALID_REQUEST;
}
- boost::string_ref keymd5 =
+ boost::string_view keymd5 =
get_crypt_attribute(s->info.env, parts, X_AMZ_SERVER_SIDE_ENCRYPTION_CUSTOMER_KEY_MD5);
std::string keymd5_bin = from_base64(keymd5);
if (keymd5_bin.size() != CEPH_CRYPTO_MD5_DIGESTSIZE) {
return 0;
}
/* AMAZON server side encryption with KMS (key management service) */
- boost::string_ref req_sse =
+ boost::string_view req_sse =
get_crypt_attribute(s->info.env, parts, X_AMZ_SERVER_SIDE_ENCRYPTION);
if (! req_sse.empty()) {
if (req_sse != "aws:kms") {
!s->info.env->exists("SERVER_PORT_SECURE")) {
return -ERR_INVALID_REQUEST;
}
- boost::string_ref key_id =
+ boost::string_view key_id =
get_crypt_attribute(s->info.env, parts, X_AMZ_SERVER_SIDE_ENCRYPTION_AWS_KMS_KEY_ID);
if (key_id.empty()) {
return -ERR_INVALID_ACCESS_KEY;
#include <rgw/rgw_op.h>
#include <rgw/rgw_rest.h>
#include <rgw/rgw_rest_s3.h>
-#include <boost/utility/string_ref.hpp>
+#include <boost/utility/string_view.hpp>
/**
* \brief Interface for block encryption methods
}
static inline
-std::string v4_signature(const std::string& credential_scope,
+std::string v4_signature(const boost::string_view& credential_scope,
CephContext* const cct,
const boost::string_view& secret_key,
/* FIXME: const. */
bool using_qs) const
{
- std::string access_key_id;
- std::string signed_hdrs;
+ boost::string_view access_key_id;
+ boost::string_view signed_hdrs;
- std::string date;
- std::string credential_scope;
- std::string client_signature;
+ boost::string_view date;
+ boost::string_view credential_scope;
+ boost::string_view client_signature;
int ret = rgw::auth::s3::parse_credentials(s->info,
access_key_id,
std::move(canonical_uri),
std::move(canonical_qs),
std::move(*canonical_headers),
- std::move(signed_hdrs),
+ signed_hdrs,
exp_payload_hash);
auto string_to_sign = \
* aws4_auth_needs_complete and aws4_auth_streaming_mode are set to false
* by default. We don't need to change that. */
if (is_v4_payload_unsigned(exp_payload_hash) || is_v4_payload_empty(s)) {
- return std::make_tuple(std::move(access_key_id),
- std::move(client_signature),
+ return std::make_tuple(access_key_id,
+ client_signature,
std::move(string_to_sign),
sig_factory,
null_completer_factory);
const auto cmpl_factory = std::bind(AWSv4ComplSingle::create,
s,
std::placeholders::_1);
- return std::make_tuple(std::move(access_key_id),
- std::move(client_signature),
+ return std::make_tuple(access_key_id,
+ client_signature,
std::move(string_to_sign),
sig_factory,
cmpl_factory);
* for CanonReq. */
const auto cmpl_factory = std::bind(AWSv4ComplMulti::create,
s,
- std::move(date),
- std::move(credential_scope),
+ date,
+ credential_scope,
client_signature,
std::placeholders::_1);
- return std::make_tuple(std::move(access_key_id),
- std::move(client_signature),
+ return std::make_tuple(access_key_id,
+ client_signature,
std::move(string_to_sign),
sig_factory,
cmpl_factory);
AWSVerAbstractor::completer_factory_t>
AWSGeneralAbstractor::get_auth_data_v2(const req_state* const s) const
{
- std::string access_key_id;
- std::string signature;
+ boost::string_view access_key_id;
+ boost::string_view signature;
bool qsr = false;
const char* http_auth = s->info.env->get("HTTP_AUTHORIZATION");
signature = s->info.args.get("Signature");
qsr = true;
- std::string expires = s->info.args.get("Expires");
+ boost::string_view expires = s->info.args.get("Expires");
if (! expires.empty()) {
- const time_t exp = atoll(expires.c_str());
+ /* It looks we have the guarantee that expires is a null-terminated,
+ * and thus string_view::data() can be safely used. */
+ const time_t exp = atoll(expires.data());
time_t now;
time(&now);
}
} else {
/* The "Authorization" HTTP header is being used. */
- const std::string auth_str(http_auth + strlen("AWS "));
+ const boost::string_view auth_str(http_auth + strlen("AWS "));
const size_t pos = auth_str.rfind(':');
- if (pos != std::string::npos) {
+ if (pos != boost::string_view::npos) {
access_key_id = auth_str.substr(0, pos);
signature = auth_str.substr(pos + 1);
}
AWSVerAbstractor::completer_factory_t>
AWSBrowserUploadAbstractor::get_auth_data_v4(const req_state* const s) const
{
- const std::string& credential = s->auth.s3_postobj_creds.x_amz_credential;
+ const boost::string_view credential = s->auth.s3_postobj_creds.x_amz_credential;
/* grab access key id */
const size_t pos = credential.find("/");
- const std::string access_key_id = credential.substr(0, pos);
+ const boost::string_view access_key_id = credential.substr(0, pos);
dout(10) << "access key id = " << access_key_id << dendl;
/* grab credential scope */
- const std::string credential_scope = credential.substr(pos + 1);
+ const boost::string_view credential_scope = credential.substr(pos + 1);
dout(10) << "credential scope = " << credential_scope << dendl;
const auto sig_factory = std::bind(v4_signature,
rgw::auth::Engine::result_t
rgw::auth::s3::LDAPEngine::authenticate(
- const std::string& access_key_id,
- const std::string& signature,
+ const boost::string_view& access_key_id,
+ const boost::string_view& signature,
const std::string& string_to_sign,
const signature_factory_t& signature_factory,
const completer_factory_t& completer_factory,
/* LocalEndgine */
rgw::auth::Engine::result_t
rgw::auth::s3::LocalEngine::authenticate(
- const std::string& access_key_id,
- const std::string& signature,
+ const boost::string_view& _access_key_id,
+ const boost::string_view& signature,
const std::string& string_to_sign,
const signature_factory_t& signature_factory,
const completer_factory_t& completer_factory,
{
/* get the user info */
RGWUserInfo user_info;
+ /* TODO(rzarzynski): we need to have string-view taking variant. */
+ const std::string access_key_id = _access_key_id.to_string();
if (rgw_get_user_info_by_access_key(store, access_key_id, user_info) < 0) {
ldout(cct, 5) << "error reading user info, uid=" << access_key_id
<< " can't authenticate" << dendl;
#include <mutex>
+#include <boost/utility/string_view.hpp>
+
#include "rgw_op.h"
#include "rgw_rest.h"
#include "rgw_http_errors.h"
public:
virtual ~VersionAbstractor() {};
- using access_key_id_t = std::string;
- using signature_t = std::string;
+ using access_key_id_t = boost::string_view;
+ using signature_t = boost::string_view;
using string_to_sign_t = std::string;
/* Transformation for crafting the AWS signature at server side which is
/* TODO(rzarzynski): clean up. We've too many input parameter hee. Also
* the signature get_auth_data() of VersionAbstractor is too complicated.
* Replace these thing with a simple, dedicated structure. */
- virtual result_t authenticate(const std::string& access_key_id,
- const std::string& signature,
+ virtual result_t authenticate(const boost::string_view& access_key_id,
+ const boost::string_view& signature,
const std::string& string_to_sign,
const signature_factory_t& signature_factory,
const completer_factory_t& completer_factory,
public:
result_t authenticate(const req_state* const s) const final {
- std::string access_key_id;
- std::string signature;
+ boost::string_view access_key_id;
+ boost::string_view signature;
std::string string_to_sign;
VersionAbstractor::signature_factory_t signature_factory;
acl_strategy_t get_acl_strategy() const;
auth_info_t get_creds_info(const rgw::RGWToken& token) const noexcept;
- result_t authenticate(const std::string& access_key_id,
- const std::string& signature,
+ result_t authenticate(const boost::string_view& access_key_id,
+ const boost::string_view& signature,
const std::string& string_to_sign,
const signature_factory_t& signature_factory,
const completer_factory_t& completer_factory,
RGWRados* const store;
const rgw::auth::LocalApplier::Factory* const apl_factory;
- result_t authenticate(const std::string& access_key_id,
- const std::string& signature,
+ result_t authenticate(const boost::string_view& access_key_id,
+ const boost::string_view& signature,
const std::string& string_to_sign,
const signature_factory_t& signature_factory,
const completer_factory_t& completer_factory,
#include <stdlib.h>
#include <limits.h>
+#include <boost/container/small_vector.hpp>
+#include <boost/utility/string_view.hpp>
struct ltstr_nocase
{
bool operator()(const string& s1, const string& s2) const
return 0;
}
+/* A converter between boost::string_view and null-terminated C-strings.
+ * It copies memory while trying to utilize the local memory instead of
+ * issuing dynamic allocations. */
+template<std::size_t N = 128>
+static inline boost::container::small_vector<char, N>
+sview2cstr(const boost::string_view& sv)
+{
+ boost::container::small_vector<char, N> cstr;
+ cstr.reserve(sv.size() + sizeof('\0'));
+
+ cstr.assign(std::begin(sv), std::end(sv));
+ cstr.push_back('\0');
+
+ return cstr;
+}
+
#endif