#ifndef CEPH_RGW_COMMON_H
#define CEPH_RGW_COMMON_H
+#include <array>
+
+#include <boost/utility/string_view.hpp>
+
#include "common/ceph_crypto.h"
#include "common/perf_counters.h"
#include "acconfig.h"
#include "rgw_acl.h"
#include "rgw_cors.h"
+#include "rgw_iam_policy.h"
#include "rgw_quota.h"
#include "rgw_string.h"
#include "rgw_website.h"
#include "cls/rgw/cls_rgw_types.h"
#include "include/rados/librados.hpp"
-using namespace std;
-
namespace ceph {
class Formatter;
}
#define RGW_ATTR_COMPRESSION RGW_ATTR_PREFIX "compression"
+/* IAM Policy */
+#define RGW_ATTR_IAM_POLICY RGW_ATTR_PREFIX "iam-policy"
+
+
/* RGW File Attributes */
#define RGW_ATTR_UNIX_KEY1 RGW_ATTR_PREFIX "unix-key1"
#define RGW_ATTR_UNIX1 RGW_ATTR_PREFIX "unix1"
#define ERR_MALFORMED_DOC 2204
#define ERR_NO_ROLE_FOUND 2205
#define ERR_DELETE_CONFLICT 2206
+#define ERR_NO_SUCH_BUCKET_POLICY 2207
+#define ERR_INVALID_LOCATION_CONSTRAINT 2208
+
+#define ERR_BUSY_RESHARDING 2300
#ifndef UINT32_MAX
#define UINT32_MAX (0xffffffffu)
#endif
+struct req_state;
+
typedef void *RGWAccessHandle;
/** Store error returns for output at a different point in the program */
struct rgw_err {
rgw_err();
- rgw_err(int http, const std::string &s3);
void clear();
bool is_clear() const;
bool is_err() const;
int http_ret;
int ret;
- std::string s3_code;
+ std::string err_code;
std::string message;
};
+
+
/* Helper class used for RGWHTTPArgs parsing */
class NameVal
{
}
};
+const char *rgw_conf_get(const map<string, string, ltstr_nocase>& conf_map, const char *name, const char *def_val);
+int rgw_conf_get_int(const map<string, string, ltstr_nocase>& conf_map, const char *name, int def_val);
+bool rgw_conf_get_bool(const map<string, string, ltstr_nocase>& conf_map, const char *name, bool def_val);
+
class RGWEnv;
class RGWConf {
void init(CephContext *cct);
void init(CephContext *cct, char **envp);
void set(const boost::string_ref& name, const boost::string_ref& val);
- const char *get(const char *name, const char *def_val = NULL);
- int get_int(const char *name, int def_val = 0);
+ const char *get(const char *name, const char *def_val = nullptr) const;
+ int get_int(const char *name, int def_val = 0) const;
bool get_bool(const char *name, bool def_val = 0);
- size_t get_size(const char *name, size_t def_val = 0);
- bool exists(const char *name);
- bool exists_prefix(const char *prefix);
+ size_t get_size(const char *name, size_t def_val = 0) const;
+ bool exists(const char *name) const;
+ bool exists_prefix(const char *prefix) const;
void remove(const char *name);
- std::map<string, string, ltstr_nocase>& get_map() { return env_map; }
+ const std::map<string, string, ltstr_nocase>& get_map() const { return env_map; }
};
enum http_op {
RGW_OP_GET_ROLE_POLICY,
RGW_OP_LIST_ROLE_POLICIES,
RGW_OP_DELETE_ROLE_POLICY,
+ RGW_OP_PUT_BUCKET_POLICY,
+ RGW_OP_GET_BUCKET_POLICY,
+ RGW_OP_DELETE_BUCKET_POLICY,
/* rgw specific */
RGW_OP_ADMIN_SET_METADATA,
RGW_OP_GET_OBJ_LAYOUT,
-
- RGW_OP_BULK_UPLOAD
+ RGW_OP_BULK_UPLOAD,
+ RGW_OP_METADATA_SEARCH,
+ RGW_OP_CONFIG_BUCKET_META_SEARCH,
+ RGW_OP_GET_BUCKET_META_SEARCH,
+ RGW_OP_DEL_BUCKET_META_SEARCH,
};
class RGWAccessControlPolicy;
DECODE_FINISH(bl);
}
+ void update_bucket_id(const string& new_bucket_id) {
+ bucket_id = new_bucket_id;
+ oid.clear();
+ }
+
// format a key for the bucket/instance. pass delim=0 to skip a field
std::string get_key(char tenant_delim = '/',
char id_delim = ':') const;
bool swift_versioning;
string swift_ver_location;
+ map<string, uint32_t> mdsearch_config;
+
+ /* resharding */
+ uint8_t reshard_status;
+ string new_bucket_instance_id;
void encode(bufferlist& bl) const {
- ENCODE_START(17, 4, bl);
+ ENCODE_START(19, 4, bl);
::encode(bucket, bl);
::encode(owner.id, bl);
::encode(flags, bl);
::encode(swift_ver_location, bl);
}
::encode(creation_time, bl);
+ ::encode(mdsearch_config, bl);
+ ::encode(reshard_status, bl);
+ ::encode(new_bucket_instance_id, bl);
ENCODE_FINISH(bl);
}
void decode(bufferlist::iterator& bl) {
- DECODE_START_LEGACY_COMPAT_LEN_32(17, 4, 4, bl);
+ DECODE_START_LEGACY_COMPAT_LEN_32(19, 4, 4, bl);
::decode(bucket, bl);
if (struct_v >= 2) {
string s;
if (struct_v >= 17) {
::decode(creation_time, bl);
}
+ if (struct_v >= 18) {
+ ::decode(mdsearch_config, bl);
+ }
+ if (struct_v >= 19) {
+ ::decode(reshard_status, bl);
+ ::decode(new_bucket_instance_id, bl);
+ }
DECODE_FINISH(bl);
}
void dump(Formatter *f) const;
}
RGWBucketInfo() : flags(0), has_instance_obj(false), num_shards(0), bucket_index_shard_hash_type(MOD), requester_pays(false),
- has_website(false), swift_versioning(false) {}
+ has_website(false), swift_versioning(false), reshard_status(0) {}
};
WRITE_CLASS_ENCODER(RGWBucketInfo)
void dump(Formatter *f) const;
};
-struct req_state;
-
class RGWEnv;
/* Namespaced forward declarations. */
namespace rgw {
namespace auth {
namespace s3 {
- class RGWGetPolicyV2Extractor;
+ class AWSBrowserUploadAbstractor;
}
+ class Completer;
}
namespace io {
class BasicClient;
}
}
+
struct req_info {
- RGWEnv *env;
+ const RGWEnv *env;
RGWHTTPArgs args;
map<string, string> x_meta_map;
string request_params;
string domain;
- req_info(CephContext *cct, RGWEnv *_env);
+ req_info(CephContext *cct, const RGWEnv *env);
void rebuild_from(req_info& src);
void init_meta_info(bool *found_bad_meta);
};
}
}
-struct rgw_aws4_auth {
- string date;
- string expires;
- string credential;
- string signedheaders;
- string signed_hdrs;
- string access_key_id;
- string credential_scope;
- string canonical_uri;
- string canonical_qs;
- string canonical_hdrs;
- string signature;
- string new_signature;
- string payload_hash;
- string seed_signature;
- string signing_key;
- char signing_k[CEPH_CRYPTO_HMACSHA256_DIGESTSIZE];
- bufferlist bl;
-};
-
struct req_init_state {
/* Keeps [[tenant]:]bucket until we parse the token. */
string url_bucket;
const char *length;
int64_t content_length;
map<string, string> generic_attrs;
- struct rgw_err err;
+ rgw_err err;
bool expect_cont;
- bool header_ended;
uint64_t obj_size;
bool enable_ops_log;
bool enable_usage_log;
* through a well-defined interface. For more details, see rgw_auth.h. */
std::unique_ptr<rgw::auth::Identity> identity;
- std::unique_ptr<rgw::auth::Completer> completer;
+ std::shared_ptr<rgw::auth::Completer> completer;
/* A container for credentials of the S3's browser upload. It's necessary
* because: 1) the ::authenticate() method of auth engines and strategies
/* Writer. */
friend class RGWPostObj_ObjStore_S3;
/* Reader. */
- friend class rgw::auth::s3::RGWGetPolicyV2Extractor;
+ friend class rgw::auth::s3::AWSBrowserUploadAbstractor;
std::string access_key;
std::string signature;
+ std::string x_amz_algorithm;
+ std::string x_amz_credential;
+ std::string x_amz_date;
ceph::bufferlist encoded_policy;
} s3_postobj_creds;
} auth;
RGWAccessControlPolicy *bucket_acl;
RGWAccessControlPolicy *object_acl;
+ rgw::IAM::Environment env;
+ boost::optional<rgw::IAM::Policy> iam_policy;
+
/* Is the request made by an user marked as a system one?
* Being system user means we also have the admin status. */
bool system_request;
- /* aws4 auth support */
- bool aws4_auth_needs_complete;
- bool aws4_auth_streaming_mode;
- unique_ptr<rgw_aws4_auth> aws4_auth;
-
string canned_acl;
bool has_acl_header;
- const char *http_auth;
bool local_source; /* source is local */
int prot_flags;
req_state(CephContext* _cct, RGWEnv* e, RGWUserInfo* u);
~req_state();
+
+ bool is_err() const { return err.is_err(); }
};
+void set_req_state_err(struct req_state*, int);
+void set_req_state_err(struct req_state*, int, const string&);
+void set_req_state_err(struct rgw_err&, int, const int);
+void dump(struct req_state*);
+
/** Store basic data on bucket */
struct RGWBucketEnt {
rgw_bucket bucket;
return out << o.bucket.name << ":" << o.get_oid();
}
-static inline void buf_to_hex(const unsigned char *buf, int len, char *str)
+static inline void buf_to_hex(const unsigned char* const buf,
+ const size_t len,
+ char* const str)
{
- int i;
str[0] = '\0';
- for (i = 0; i < len; i++) {
- sprintf(&str[i*2], "%02x", (int)buf[i]);
+ for (size_t i = 0; i < len; i++) {
+ ::sprintf(&str[i*2], "%02x", static_cast<int>(buf[i]));
}
}
+template<size_t N> static inline std::array<char, N * 2 + 1>
+buf_to_hex(const std::array<unsigned char, N>& buf)
+{
+ static_assert(N > 0, "The input array must be at least one element long");
+
+ std::array<char, N * 2 + 1> hex_dest;
+ buf_to_hex(buf.data(), N, hex_dest.data());
+ return hex_dest;
+}
+
static inline int hexdigit(char c)
{
if (c >= '0' && c <= '9')
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);
const int perm);
bool verify_user_permission(struct req_state * const s,
const int perm);
-extern bool verify_bucket_permission(struct req_state * s,
- RGWAccessControlPolicy * user_acl,
- RGWAccessControlPolicy * bucket_acl,
- int perm);
-extern bool verify_bucket_permission(struct req_state *s, int perm);
-extern bool verify_object_permission(struct req_state *s,
- RGWAccessControlPolicy * user_acl,
- RGWAccessControlPolicy * bucket_acl,
- RGWAccessControlPolicy * object_acl,
- int perm);
-extern bool verify_object_permission(struct req_state *s, int perm);
+bool verify_bucket_permission(
+ struct req_state * const s,
+ const rgw_bucket& bucket,
+ RGWAccessControlPolicy * const user_acl,
+ RGWAccessControlPolicy * const bucket_acl,
+ const boost::optional<rgw::IAM::Policy>& bucket_policy,
+ const uint64_t op);
+bool verify_bucket_permission(struct req_state * const s, const uint64_t op);
+bool verify_bucket_permission_no_policy(
+ struct req_state * const s,
+ RGWAccessControlPolicy * const user_acl,
+ RGWAccessControlPolicy * const bucket_acl,
+ const int perm);
+bool verify_bucket_permission_no_policy(struct req_state * const s,
+ const int perm);
+extern bool verify_object_permission(
+ struct req_state * const s,
+ const rgw_obj& obj,
+ RGWAccessControlPolicy * const user_acl,
+ RGWAccessControlPolicy * const bucket_acl,
+ RGWAccessControlPolicy * const object_acl,
+ const boost::optional<rgw::IAM::Policy>& bucket_policy,
+ const uint64_t op);
+extern bool verify_object_permission(struct req_state *s, uint64_t op);
+extern bool verify_object_permission_no_policy(
+ struct req_state * const s,
+ RGWAccessControlPolicy * const user_acl,
+ RGWAccessControlPolicy * const bucket_acl,
+ RGWAccessControlPolicy * const object_acl,
+ int perm);
+extern bool verify_object_permission_no_policy(struct req_state *s,
+ int perm);
/** Convert an input URL into a sane object name
* by converting %-escaped strings into characters, etc*/
extern void rgw_uri_escape_char(char c, string& dst);
-extern bool url_decode(const std::string& src_str,
- std::string& dest_str,
- bool in_query = false);
+extern std::string url_decode(const boost::string_view& src_str,
+ bool in_query = false);
extern void url_encode(const std::string& src,
string& dst);
extern std::string url_encode(const std::string& src);
/* destination should be CEPH_CRYPTO_HMACSHA1_DIGESTSIZE bytes long */
extern void calc_hmac_sha1(const char *key, int key_len,
const char *msg, int msg_len, char *dest);
+
+using sha1_digest_t = \
+ std::array<char, CEPH_CRYPTO_HMACSHA1_DIGESTSIZE>;
+
+static inline sha1_digest_t
+calc_hmac_sha1(const boost::string_view& key, const boost::string_view& msg) {
+ sha1_digest_t dest;
+ calc_hmac_sha1(key.data(), key.size(), msg.data(), msg.size(), dest.data());
+ return dest;
+}
+
/* destination should be CEPH_CRYPTO_HMACSHA256_DIGESTSIZE bytes long */
-extern void calc_hmac_sha256(const char *key, int key_len, const char *msg, int msg_len, char *dest);
-extern void calc_hash_sha256(const char *msg, int len, string& dest);
-extern void calc_hash_sha256(const string& msg, string& dest);
+extern void calc_hmac_sha256(const char *key, int key_len,
+ const char *msg, int msg_len,
+ char *dest);
+
+using sha256_digest_t = \
+ std::array<unsigned char, CEPH_CRYPTO_HMACSHA256_DIGESTSIZE>;
+
+static inline sha256_digest_t
+calc_hmac_sha256(const char *key, const int key_len,
+ const char *msg, const int msg_len) {
+ std::array<unsigned char, CEPH_CRYPTO_HMACSHA256_DIGESTSIZE> dest;
+ calc_hmac_sha256(key, key_len, msg, msg_len,
+ reinterpret_cast<char*>(dest.data()));
+ return dest;
+}
+
+static inline sha256_digest_t
+calc_hmac_sha256(const boost::string_view& key, const boost::string_view& msg) {
+ std::array<unsigned char, CEPH_CRYPTO_HMACSHA256_DIGESTSIZE> dest;
+ calc_hmac_sha256(key.data(), key.size(),
+ msg.data(), msg.size(),
+ reinterpret_cast<char*>(dest.data()));
+ return dest;
+}
-using ceph::crypto::SHA256;
-extern SHA256* calc_hash_sha256_open_stream();
-extern void calc_hash_sha256_update_stream(SHA256 *hash, const char *msg, int len);
-extern string calc_hash_sha256_close_stream(SHA256 **hash);
+static inline sha256_digest_t
+calc_hmac_sha256(const std::vector<unsigned char>& key,
+ const boost::string_view& msg) {
+ std::array<unsigned char, CEPH_CRYPTO_HMACSHA256_DIGESTSIZE> dest;
+ calc_hmac_sha256(reinterpret_cast<const char*>(key.data()), key.size(),
+ msg.data(), msg.size(),
+ reinterpret_cast<char*>(dest.data()));
+ return dest;
+}
+
+template<size_t KeyLenN>
+static inline sha256_digest_t
+calc_hmac_sha256(const std::array<unsigned char, KeyLenN>& key,
+ const boost::string_view& msg) {
+ std::array<unsigned char, CEPH_CRYPTO_HMACSHA256_DIGESTSIZE> dest;
+ calc_hmac_sha256(reinterpret_cast<const char*>(key.data()), key.size(),
+ msg.data(), msg.size(),
+ reinterpret_cast<char*>(dest.data()));
+ return dest;
+}
+
+extern sha256_digest_t calc_hash_sha256(const boost::string_view& msg);
+
+extern ceph::crypto::SHA256* calc_hash_sha256_open_stream();
+extern void calc_hash_sha256_update_stream(ceph::crypto::SHA256* hash,
+ const char* msg,
+ int len);
+extern std::string calc_hash_sha256_close_stream(ceph::crypto::SHA256** phash);
+extern std::string calc_hash_sha256_restart_stream(ceph::crypto::SHA256** phash);
extern int rgw_parse_op_type_list(const string& str, uint32_t *perm);
-int match(const string& pattern, const string& input, int flag);
+namespace {
+ constexpr uint32_t MATCH_POLICY_ACTION = 0x01;
+ constexpr uint32_t MATCH_POLICY_RESOURCE = 0x02;
+ constexpr uint32_t MATCH_POLICY_ARN = 0x04;
+ constexpr uint32_t MATCH_POLICY_STRING = 0x08;
+}
+
+int match(const std::string& pattern, const std::string& input, uint32_t flag);
#endif