1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * All operations via the rados gateway are carried out by
5 * small classes known as RGWOps. This class contains a req_state
6 * and each possible command is a subclass of this with a defined
7 * execute() method that does whatever the subclass name implies.
8 * These subclasses must be further subclassed (by interface type)
9 * to provide additional virtual methods such as send_response or get_params.
23 #include <boost/optional.hpp>
24 #include <boost/utility/in_place_factory.hpp>
25 #include <boost/function.hpp>
27 #include "common/armor.h"
28 #include "common/mime.h"
29 #include "common/utf8.h"
30 #include "common/ceph_json.h"
31 #include "common/utf8.h"
32 #include "common/ceph_time.h"
34 #include "rgw_common.h"
35 #include "rgw_rados.h"
37 #include "rgw_bucket.h"
40 #include "rgw_quota.h"
43 #include "rgw_torrent.h"
45 #include "cls/lock/cls_lock_client.h"
46 #include "cls/rgw/cls_rgw_client.h"
48 #include "include/assert.h"
50 using ceph::crypto::SHA1;
60 class StrategyRegistry;
72 int do_init_permissions();
73 int do_read_permissions(RGWOp* op, bool only_bucket);
80 virtual ~RGWHandler();
82 virtual int init(RGWRados* store,
84 rgw::io::BasicClient* cio);
86 virtual int init_permissions(RGWOp*) {
90 virtual int retarget(RGWOp* op, RGWOp** new_op) {
95 virtual int read_permissions(RGWOp* op) = 0;
96 virtual int authorize() = 0;
97 virtual int postauth_init() = 0;
98 virtual int error_handler(int err_no, std::string* error_content);
99 virtual void dump(const string& code, const string& message) const {}
104 void rgw_bucket_object_pre_exec(struct req_state *s);
107 * Provide the base class for all ops.
112 RGWHandler *dialect_handler;
114 RGWCORSConfiguration bucket_cors;
116 RGWQuotaInfo bucket_quota;
117 RGWQuotaInfo user_quota;
120 int do_aws4_auth_completion();
122 virtual int init_quota();
126 dialect_handler(nullptr),
132 virtual ~RGWOp() = default;
134 int get_ret() const { return op_ret; }
136 virtual int init_processing() {
137 op_ret = init_quota();
144 virtual void init(RGWRados *store, struct req_state *s, RGWHandler *dialect_handler) {
147 this->dialect_handler = dialect_handler;
149 int read_bucket_cors();
150 bool generate_cors_headers(string& origin, string& method, string& headers, string& exp_headers, unsigned *max_age);
152 virtual int verify_params() { return 0; }
153 virtual bool prefetch_data() { return false; }
155 /* Authenticate requester -- verify its identity.
157 * NOTE: typically the procedure is common across all operations of the same
158 * dialect (S3, Swift API). However, there are significant exceptions in
159 * both APIs: browser uploads, /info and OPTIONS handlers. All of them use
160 * different, specific authentication schema driving the need for per-op
161 * authentication. The alternative is to duplicate parts of the method-
162 * dispatch logic in RGWHandler::authorize() and pollute it with a lot
163 * of special cases. */
164 virtual int verify_requester(const rgw::auth::StrategyRegistry& auth_registry) {
165 /* TODO(rzarzynski): rename RGWHandler::authorize to generic_authenticate. */
166 return dialect_handler->authorize();
168 virtual int verify_permission() = 0;
169 virtual int verify_op_mask();
170 virtual void pre_exec() {}
171 virtual void execute() = 0;
172 virtual void send_response() {}
173 virtual void complete() {
176 virtual const string name() = 0;
177 virtual RGWOpType get_type() { return RGW_OP_UNKNOWN; }
179 virtual uint32_t op_mask() { return 0; }
181 virtual int error_handler(int err_no, string *error_content);
184 class RGWGetObj : public RGWOp {
186 seed torrent; // get torrent
187 const char *range_str;
189 const char *if_unmod;
190 const char *if_match;
191 const char *if_nomatch;
192 uint32_t mod_zone_id;
198 ceph::real_time mod_time;
199 ceph::real_time lastmod;
200 ceph::real_time unmod_time;
201 ceph::real_time *mod_ptr;
202 ceph::real_time *unmod_ptr;
203 map<string, bufferlist> attrs;
205 bool partial_content;
208 bool skip_decrypt{false};
210 utime_t gc_invalidate_time;
213 bool rgwx_stat; /* extended rgw stat operation */
217 RGWCompressionInfo cs_info;
218 off_t first_block, last_block;
242 partial_content = false;
243 range_parsed = false;
244 skip_manifest = false;
254 bool prefetch_data() override;
256 void set_get_data(bool get_data) {
257 this->get_data = get_data;
259 int verify_permission() override;
260 void pre_exec() override;
261 void execute() override;
262 int read_user_manifest_part(
264 const rgw_bucket_dir_entry& ent,
265 RGWAccessControlPolicy * const bucket_acl,
266 const boost::optional<rgw::IAM::Policy>& bucket_policy,
267 const off_t start_ofs,
268 const off_t end_ofs);
269 int handle_user_manifest(const char *prefix);
270 int handle_slo_manifest(bufferlist& bl);
272 int get_data_cb(bufferlist& bl, off_t ofs, off_t len);
274 virtual int get_params() = 0;
275 virtual int send_response_data_error() = 0;
276 virtual int send_response_data(bufferlist& bl, off_t ofs, off_t len) = 0;
278 const string name() override { return "get_obj"; }
279 RGWOpType get_type() override { return RGW_OP_GET_OBJ; }
280 uint32_t op_mask() override { return RGW_OP_TYPE_READ; }
281 virtual bool need_object_expiration() { return false; }
283 * calculates filter used to decrypt RGW objects data
285 virtual int get_decrypt_filter(std::unique_ptr<RGWGetDataCB>* filter, RGWGetDataCB* cb, bufferlist* manifest_bl) {
291 class RGWGetObj_CB : public RGWGetDataCB
295 explicit RGWGetObj_CB(RGWGetObj *_op) : op(_op) {}
296 ~RGWGetObj_CB() override {}
298 int handle_data(bufferlist& bl, off_t bl_ofs, off_t bl_len) override {
299 return op->get_data_cb(bl, bl_ofs, bl_len);
303 class RGWGetObj_Filter : public RGWGetDataCB
308 RGWGetObj_Filter(RGWGetDataCB* next): next(next) {}
309 ~RGWGetObj_Filter() override {}
311 * Passes data through filter.
312 * Filter can modify content of bl.
313 * When bl_len == 0 , it means 'flush
315 int handle_data(bufferlist& bl, off_t bl_ofs, off_t bl_len) override {
316 return next->handle_data(bl, bl_ofs, bl_len);
319 * Flushes any cached data. Used by RGWGetObjFilter.
320 * Return logic same as handle_data.
322 int flush() override {
323 return next->flush();
326 * Allows filter to extend range required for successful filtering
328 int fixup_range(off_t& ofs, off_t& end) override {
329 return next->fixup_range(ofs, end);
333 class RGWGetObjTags : public RGWOp {
336 bool has_tags{false};
338 int verify_permission();
342 virtual void send_response_data(bufferlist& bl) = 0;
343 virtual const string name() noexcept override { return "get_obj_tags"; }
344 virtual uint32_t op_mask() { return RGW_OP_TYPE_READ; }
345 RGWOpType get_type() { return RGW_OP_GET_OBJ_TAGGING; }
349 class RGWPutObjTags : public RGWOp {
353 int verify_permission();
356 virtual void send_response() = 0;
357 virtual int get_params() = 0;
358 virtual const string name() { return "put_obj_tags"; }
359 virtual uint32_t op_mask() { return RGW_OP_TYPE_WRITE; }
360 RGWOpType get_type() { return RGW_OP_PUT_OBJ_TAGGING; }
364 class RGWDeleteObjTags: public RGWOp {
367 int verify_permission();
370 virtual void send_response() = 0;
371 virtual const string name() { return "delete_obj_tags"; }
372 virtual uint32_t op_mask() { return RGW_OP_TYPE_DELETE; }
373 RGWOpType get_type() { return RGW_OP_DELETE_OBJ_TAGGING;}
376 class RGWBulkDelete : public RGWOp {
379 std::string bucket_name;
390 unsigned int num_deleted;
391 unsigned int num_unfound;
392 std::list<fail_desc_t> failures;
394 RGWRados * const store;
398 Deleter(RGWRados * const str, req_state * const s)
405 unsigned int get_num_deleted() const {
409 unsigned int get_num_unfound() const {
413 const std::list<fail_desc_t> get_failures() const {
417 bool verify_permission(RGWBucketInfo& binfo,
418 map<string, bufferlist>& battrs,
419 ACLOwner& bucket_owner /* out */);
420 bool delete_single(const acct_path_t& path);
421 bool delete_chunk(const std::list<acct_path_t>& paths);
423 /* End of Deleter subclass */
425 static const size_t MAX_CHUNK_ENTRIES = 1024;
428 std::unique_ptr<Deleter> deleter;
435 int verify_permission() override;
436 void pre_exec() override;
437 void execute() override;
439 virtual int get_data(std::list<acct_path_t>& items,
440 bool * is_truncated) = 0;
441 void send_response() override = 0;
443 const string name() override { return "bulk_delete"; }
444 RGWOpType get_type() override { return RGW_OP_BULK_DELETE; }
445 uint32_t op_mask() override { return RGW_OP_TYPE_DELETE; }
448 inline ostream& operator<<(ostream& out, const RGWBulkDelete::acct_path_t &o) {
449 return out << o.bucket_name << "/" << o.obj_key;
453 class RGWBulkUploadOp : public RGWOp {
454 boost::optional<RGWObjectCtx> dir_ctx;
459 fail_desc_t(const int err, std::string path)
461 path(std::move(path)) {
465 const std::string path;
468 static constexpr std::array<int, 2> terminal_errors = {
472 /* FIXME: boost::container::small_vector<fail_desc_t, 4> failures; */
473 std::vector<fail_desc_t> failures;
477 class DecoratedStreamGetter;
478 class AlignedStreamGetter;
480 virtual std::unique_ptr<StreamGetter> create_stream() = 0;
481 virtual void send_response() = 0;
483 boost::optional<std::pair<std::string, rgw_obj_key>>
484 parse_path(const boost::string_ref& path);
486 std::pair<std::string, std::string>
487 handle_upload_path(struct req_state *s);
489 bool handle_file_verify_permission(RGWBucketInfo& binfo,
491 std::map<std::string, ceph::bufferlist>& battrs,
492 ACLOwner& bucket_owner /* out */);
493 int handle_file(boost::string_ref path,
495 AlignedStreamGetter& body);
497 int handle_dir_verify_permission();
498 int handle_dir(boost::string_ref path);
505 void init(RGWRados* const store,
506 struct req_state* const s,
507 RGWHandler* const h) override {
508 RGWOp::init(store, s, h);
509 dir_ctx.emplace(store);
512 int verify_permission() override;
513 void pre_exec() override;
514 void execute() override;
516 const std::string name() override {
517 return "bulk_upload";
520 RGWOpType get_type() override {
521 return RGW_OP_BULK_UPLOAD;
524 uint32_t op_mask() override {
525 return RGW_OP_TYPE_WRITE;
527 }; /* RGWBulkUploadOp */
530 class RGWBulkUploadOp::StreamGetter {
532 StreamGetter() = default;
533 virtual ~StreamGetter() = default;
535 virtual ssize_t get_at_most(size_t want, ceph::bufferlist& dst) = 0;
536 virtual ssize_t get_exactly(size_t want, ceph::bufferlist& dst) = 0;
537 }; /* End of nested subclass StreamGetter */
540 class RGWBulkUploadOp::DecoratedStreamGetter : public StreamGetter {
541 StreamGetter& decoratee;
544 StreamGetter& get_decoratee() {
549 DecoratedStreamGetter(StreamGetter& decoratee)
550 : decoratee(decoratee) {
552 virtual ~DecoratedStreamGetter() = default;
554 ssize_t get_at_most(const size_t want, ceph::bufferlist& dst) override {
555 return get_decoratee().get_at_most(want, dst);
558 ssize_t get_exactly(const size_t want, ceph::bufferlist& dst) override {
559 return get_decoratee().get_exactly(want, dst);
561 }; /* RGWBulkUploadOp::DecoratedStreamGetter */
564 class RGWBulkUploadOp::AlignedStreamGetter
565 : public RGWBulkUploadOp::DecoratedStreamGetter {
571 template <typename U>
572 AlignedStreamGetter(const size_t position,
574 const size_t alignment,
576 : DecoratedStreamGetter(std::forward<U>(decoratee)),
579 alignment(alignment) {
581 virtual ~AlignedStreamGetter();
582 ssize_t get_at_most(size_t want, ceph::bufferlist& dst) override;
583 ssize_t get_exactly(size_t want, ceph::bufferlist& dst) override;
584 }; /* RGWBulkUploadOp::AlignedStreamGetter */
587 struct RGWUsageStats {
588 uint64_t bytes_used = 0;
589 uint64_t bytes_used_rounded = 0;
590 uint64_t buckets_count = 0;
591 uint64_t objects_count = 0;
594 #define RGW_LIST_BUCKETS_LIMIT_MAX 10000
596 class RGWListBuckets : public RGWOp {
600 std::string end_marker;
603 std::map<std::string, ceph::bufferlist> attrs;
606 RGWUsageStats global_stats;
607 std::map<std::string, RGWUsageStats> policies_stats;
609 virtual uint64_t get_default_max() const {
616 limit(RGW_LIST_BUCKETS_LIMIT_MAX),
617 limit_max(RGW_LIST_BUCKETS_LIMIT_MAX),
618 is_truncated(false) {
621 int verify_permission() override;
622 void execute() override;
624 virtual int get_params() = 0;
625 virtual void handle_listing_chunk(RGWUserBuckets&& buckets) {
626 /* The default implementation, used by e.g. S3, just generates a new
627 * part of listing and sends it client immediately. Swift can behave
628 * differently: when the reverse option is requested, all incoming
629 * instances of RGWUserBuckets are buffered and finally reversed. */
630 return send_response_data(buckets);
632 virtual void send_response_begin(bool has_buckets) = 0;
633 virtual void send_response_data(RGWUserBuckets& buckets) = 0;
634 virtual void send_response_end() = 0;
635 void send_response() override {}
637 virtual bool should_get_stats() { return false; }
638 virtual bool supports_account_metadata() { return false; }
640 const string name() override { return "list_buckets"; }
641 RGWOpType get_type() override { return RGW_OP_LIST_BUCKETS; }
642 uint32_t op_mask() override { return RGW_OP_TYPE_READ; }
645 class RGWGetUsage : public RGWOp {
650 int show_log_entries;
652 map<string, bool> categories;
653 map<rgw_user_bucket, rgw_usage_log_entry> usage;
654 map<string, rgw_usage_log_entry> summary_map;
655 map<string, cls_user_bucket_entry> buckets_usage;
656 cls_user_header header;
658 RGWGetUsage() : sent_data(false), show_log_entries(true), show_log_sum(true){
661 int verify_permission() override;
662 void execute() override;
664 virtual int get_params() = 0;
665 void send_response() override {}
667 virtual bool should_get_stats() { return false; }
669 const string name() override { return "get_usage"; }
670 uint32_t op_mask() override { return RGW_OP_TYPE_READ; }
673 class RGWStatAccount : public RGWOp {
675 RGWUsageStats global_stats;
676 std::map<std::string, RGWUsageStats> policies_stats;
679 RGWStatAccount() = default;
681 int verify_permission() override;
682 void execute() override;
684 void send_response() override = 0;
685 const std::string name() override { return "stat_account"; }
686 RGWOpType get_type() override { return RGW_OP_STAT_ACCOUNT; }
687 uint32_t op_mask() override { return RGW_OP_TYPE_READ; }
690 class RGWListBucket : public RGWOp {
695 rgw_obj_key next_marker;
696 rgw_obj_key end_marker;
699 string encoding_type;
702 vector<rgw_bucket_dir_entry> objs;
703 map<string, bool> common_prefixes;
710 int parse_max_keys();
713 RGWListBucket() : list_versions(false), max(0),
714 default_max(0), is_truncated(false), shard_id(-1) {}
715 int verify_permission() override;
716 void pre_exec() override;
717 void execute() override;
719 virtual int get_params() = 0;
720 void send_response() override = 0;
721 const string name() override { return "list_bucket"; }
722 RGWOpType get_type() override { return RGW_OP_LIST_BUCKET; }
723 uint32_t op_mask() override { return RGW_OP_TYPE_READ; }
724 virtual bool need_container_stats() { return false; }
727 class RGWGetBucketLogging : public RGWOp {
729 RGWGetBucketLogging() {}
730 int verify_permission() override;
731 void execute() override { }
733 void send_response() override = 0;
734 const string name() override { return "get_bucket_logging"; }
735 RGWOpType get_type() override { return RGW_OP_GET_BUCKET_LOGGING; }
736 uint32_t op_mask() override { return RGW_OP_TYPE_READ; }
739 class RGWGetBucketLocation : public RGWOp {
741 RGWGetBucketLocation() {}
742 ~RGWGetBucketLocation() override {}
743 int verify_permission() override;
744 void execute() override { }
746 void send_response() override = 0;
747 const string name() override { return "get_bucket_location"; }
748 RGWOpType get_type() override { return RGW_OP_GET_BUCKET_LOCATION; }
749 uint32_t op_mask() override { return RGW_OP_TYPE_READ; }
752 class RGWGetBucketVersioning : public RGWOp {
755 bool versioning_enabled;
757 RGWGetBucketVersioning() : versioned(false), versioning_enabled(false) {}
759 int verify_permission() override;
760 void pre_exec() override;
761 void execute() override;
763 void send_response() override = 0;
764 const string name() override { return "get_bucket_versioning"; }
765 RGWOpType get_type() override { return RGW_OP_GET_BUCKET_VERSIONING; }
766 uint32_t op_mask() override { return RGW_OP_TYPE_READ; }
769 class RGWSetBucketVersioning : public RGWOp {
771 bool enable_versioning;
774 RGWSetBucketVersioning() : enable_versioning(false) {}
776 int verify_permission() override;
777 void pre_exec() override;
778 void execute() override;
780 virtual int get_params() { return 0; }
782 void send_response() override = 0;
783 const string name() override { return "set_bucket_versioning"; }
784 RGWOpType get_type() override { return RGW_OP_SET_BUCKET_VERSIONING; }
785 uint32_t op_mask() override { return RGW_OP_TYPE_WRITE; }
788 class RGWGetBucketWebsite : public RGWOp {
790 RGWGetBucketWebsite() {}
792 int verify_permission() override;
793 void pre_exec() override;
794 void execute() override;
796 void send_response() override = 0;
797 const string name() override { return "get_bucket_website"; }
798 RGWOpType get_type() override { return RGW_OP_GET_BUCKET_WEBSITE; }
799 uint32_t op_mask() override { return RGW_OP_TYPE_READ; }
802 class RGWSetBucketWebsite : public RGWOp {
805 RGWBucketWebsiteConf website_conf;
807 RGWSetBucketWebsite() {}
809 int verify_permission() override;
810 void pre_exec() override;
811 void execute() override;
813 virtual int get_params() { return 0; }
815 void send_response() override = 0;
816 const string name() override { return "set_bucket_website"; }
817 RGWOpType get_type() override { return RGW_OP_SET_BUCKET_WEBSITE; }
818 uint32_t op_mask() override { return RGW_OP_TYPE_WRITE; }
821 class RGWDeleteBucketWebsite : public RGWOp {
823 RGWDeleteBucketWebsite() {}
825 int verify_permission() override;
826 void pre_exec() override;
827 void execute() override;
829 void send_response() override = 0;
830 const string name() override { return "delete_bucket_website"; }
831 RGWOpType get_type() override { return RGW_OP_SET_BUCKET_WEBSITE; }
832 uint32_t op_mask() override { return RGW_OP_TYPE_WRITE; }
835 class RGWStatBucket : public RGWOp {
841 ~RGWStatBucket() override {}
843 int verify_permission() override;
844 void pre_exec() override;
845 void execute() override;
847 void send_response() override = 0;
848 const string name() override { return "stat_bucket"; }
849 RGWOpType get_type() override { return RGW_OP_STAT_BUCKET; }
850 uint32_t op_mask() override { return RGW_OP_TYPE_READ; }
853 class RGWCreateBucket : public RGWOp {
855 RGWAccessControlPolicy policy;
856 string location_constraint;
857 string placement_rule;
861 RGWCORSConfiguration cors_config;
862 boost::optional<std::string> swift_ver_location;
863 map<string, buffer::list> attrs;
864 set<string> rmattr_names;
868 virtual bool need_metadata_upload() const { return false; }
871 RGWCreateBucket() : has_cors(false) {}
873 void emplace_attr(std::string&& key, buffer::list&& bl) {
874 attrs.emplace(std::move(key), std::move(bl)); /* key and bl are r-value refs */
877 int verify_permission() override;
878 void pre_exec() override;
879 void execute() override;
880 void init(RGWRados *store, struct req_state *s, RGWHandler *h) override {
881 RGWOp::init(store, s, h);
882 policy.set_ctx(s->cct);
884 virtual int get_params() { return 0; }
885 void send_response() override = 0;
886 const string name() override { return "create_bucket"; }
887 RGWOpType get_type() override { return RGW_OP_CREATE_BUCKET; }
888 uint32_t op_mask() override { return RGW_OP_TYPE_WRITE; }
891 class RGWDeleteBucket : public RGWOp {
893 RGWObjVersionTracker objv_tracker;
898 int verify_permission() override;
899 void pre_exec() override;
900 void execute() override;
902 void send_response() override = 0;
903 const string name() override { return "delete_bucket"; }
904 RGWOpType get_type() override { return RGW_OP_DELETE_BUCKET; }
905 uint32_t op_mask() override { return RGW_OP_TYPE_DELETE; }
908 struct rgw_slo_entry {
913 rgw_slo_entry() : size_bytes(0) {}
915 void encode(bufferlist& bl) const {
916 ENCODE_START(1, 1, bl);
919 ::encode(size_bytes, bl);
923 void decode(bufferlist::iterator& bl) {
927 ::decode(size_bytes, bl);
931 void decode_json(JSONObj *obj);
933 WRITE_CLASS_ENCODER(rgw_slo_entry)
936 vector<rgw_slo_entry> entries;
943 RGWSLOInfo() : total_size(0), raw_data(NULL), raw_data_len(0) {}
948 void encode(bufferlist& bl) const {
949 ENCODE_START(1, 1, bl);
950 ::encode(entries, bl);
951 ::encode(total_size, bl);
955 void decode(bufferlist::iterator& bl) {
957 ::decode(entries, bl);
958 ::decode(total_size, bl);
962 WRITE_CLASS_ENCODER(RGWSLOInfo)
964 class RGWPutObj : public RGWOp {
966 friend class RGWPutObjProcessor;
971 const char *supplied_md5_b64;
972 const char *supplied_etag;
973 const char *if_match;
974 const char *if_nomatch;
975 const char *copy_source;
976 const char *copy_source_range;
977 RGWBucketInfo copy_source_bucket_info;
978 string copy_source_tenant_name;
979 string copy_source_bucket_name;
980 string copy_source_object_name;
981 string copy_source_version_id;
982 off_t copy_source_range_fst;
983 off_t copy_source_range_lst;
986 RGWAccessControlPolicy policy;
987 std::unique_ptr <RGWObjTags> obj_tags;
988 const char *dlo_manifest;
989 RGWSLOInfo *slo_info;
990 map<string, bufferlist> attrs;
991 ceph::real_time mtime;
995 map<string, string> crypt_http_responses;
998 boost::optional<ceph::real_time> delete_at;
1001 RGWPutObj() : ofs(0),
1002 supplied_md5_b64(NULL),
1003 supplied_etag(NULL),
1007 copy_source_range(NULL),
1008 copy_source_range_fst(0),
1009 copy_source_range_lst(0),
1015 ~RGWPutObj() override {
1019 void init(RGWRados *store, struct req_state *s, RGWHandler *h) override {
1020 RGWOp::init(store, s, h);
1021 policy.set_ctx(s->cct);
1024 void emplace_attr(std::string&& key, buffer::list&& bl) {
1025 attrs.emplace(std::move(key), std::move(bl)); /* key and bl are r-value refs */
1028 virtual RGWPutObjProcessor *select_processor(RGWObjectCtx& obj_ctx, bool *is_multipart);
1029 void dispose_processor(RGWPutObjDataProcessor *processor);
1031 int verify_permission() override;
1032 void pre_exec() override;
1033 void execute() override;
1035 /* this is for cases when copying data from other object */
1036 virtual int get_decrypt_filter(std::unique_ptr<RGWGetDataCB>* filter,
1038 map<string, bufferlist>& attrs,
1039 bufferlist* manifest_bl) {
1043 virtual int get_encrypt_filter(std::unique_ptr<RGWPutObjDataProcessor> *filter, RGWPutObjDataProcessor* cb) {
1048 int get_data_cb(bufferlist& bl, off_t bl_ofs, off_t bl_len);
1049 int get_data(const off_t fst, const off_t lst, bufferlist& bl);
1051 virtual int get_params() = 0;
1052 virtual int get_data(bufferlist& bl) = 0;
1053 void send_response() override = 0;
1054 const string name() override { return "put_obj"; }
1055 RGWOpType get_type() override { return RGW_OP_PUT_OBJ; }
1056 uint32_t op_mask() override { return RGW_OP_TYPE_WRITE; }
1059 class RGWPutObj_Filter : public RGWPutObjDataProcessor
1062 RGWPutObjDataProcessor* next;
1064 RGWPutObj_Filter(RGWPutObjDataProcessor* next) :
1066 ~RGWPutObj_Filter() override {}
1067 int handle_data(bufferlist& bl, off_t ofs, void **phandle, rgw_raw_obj *pobj, bool *again) override {
1068 return next->handle_data(bl, ofs, phandle, pobj, again);
1070 int throttle_data(void *handle, const rgw_raw_obj& obj, uint64_t size, bool need_to_wait) override {
1071 return next->throttle_data(handle, obj, size, need_to_wait);
1073 }; /* RGWPutObj_Filter */
1075 class RGWPostObj : public RGWOp {
1081 const char *supplied_md5_b64;
1082 const char *supplied_etag;
1084 RGWAccessControlPolicy policy;
1085 map<string, bufferlist> attrs;
1086 boost::optional<ceph::real_time> delete_at;
1088 /* Must be called after get_data() or the result is undefined. */
1089 virtual std::string get_current_filename() const = 0;
1090 virtual std::string get_current_content_type() const = 0;
1091 virtual bool is_next_file_to_upload() {
1095 RGWPostObj() : min_len(0),
1099 supplied_md5_b64(nullptr),
1100 supplied_etag(nullptr) {
1103 void emplace_attr(std::string&& key, buffer::list&& bl) {
1104 attrs.emplace(std::move(key), std::move(bl)); /* key and bl are r-value refs */
1107 void init(RGWRados *store, struct req_state *s, RGWHandler *h) override {
1108 RGWOp::init(store, s, h);
1109 policy.set_ctx(s->cct);
1112 int verify_permission() override;
1113 void pre_exec() override;
1114 void execute() override;
1116 virtual int get_encrypt_filter(std::unique_ptr<RGWPutObjDataProcessor> *filter, RGWPutObjDataProcessor* cb) {
1120 virtual int get_params() = 0;
1121 virtual int get_data(ceph::bufferlist& bl, bool& again) = 0;
1122 void send_response() override = 0;
1123 const std::string name() override { return "post_obj"; }
1124 RGWOpType get_type() override { return RGW_OP_POST_OBJ; }
1125 uint32_t op_mask() override { return RGW_OP_TYPE_WRITE; }
1128 class RGWPutMetadataAccount : public RGWOp {
1130 std::set<std::string> rmattr_names;
1131 std::map<std::string, bufferlist> attrs, orig_attrs;
1132 std::map<int, std::string> temp_url_keys;
1133 RGWQuotaInfo new_quota;
1134 bool new_quota_extracted;
1136 RGWObjVersionTracker acct_op_tracker;
1138 RGWAccessControlPolicy policy;
1142 RGWPutMetadataAccount()
1143 : new_quota_extracted(false),
1147 void init(RGWRados *store, struct req_state *s, RGWHandler *h) override {
1148 RGWOp::init(store, s, h);
1149 policy.set_ctx(s->cct);
1151 int init_processing() override;
1152 int verify_permission() override;
1153 void pre_exec() override { }
1154 void execute() override;
1156 virtual int get_params() = 0;
1157 void send_response() override = 0;
1158 virtual void filter_out_temp_url(map<string, bufferlist>& add_attrs,
1159 const set<string>& rmattr_names,
1160 map<int, string>& temp_url_keys);
1161 const string name() override { return "put_account_metadata"; }
1162 RGWOpType get_type() override { return RGW_OP_PUT_METADATA_ACCOUNT; }
1163 uint32_t op_mask() override { return RGW_OP_TYPE_WRITE; }
1166 class RGWPutMetadataBucket : public RGWOp {
1168 map<string, buffer::list> attrs;
1169 set<string> rmattr_names;
1170 bool has_policy, has_cors;
1171 uint32_t policy_rw_mask;
1172 RGWAccessControlPolicy policy;
1173 RGWCORSConfiguration cors_config;
1174 string placement_rule;
1175 boost::optional<std::string> swift_ver_location;
1178 RGWPutMetadataBucket()
1179 : has_policy(false), has_cors(false), policy_rw_mask(0)
1182 void emplace_attr(std::string&& key, buffer::list&& bl) {
1183 attrs.emplace(std::move(key), std::move(bl)); /* key and bl are r-value refs */
1186 void init(RGWRados *store, struct req_state *s, RGWHandler *h) override {
1187 RGWOp::init(store, s, h);
1188 policy.set_ctx(s->cct);
1191 int verify_permission() override;
1192 void pre_exec() override;
1193 void execute() override;
1195 virtual int get_params() = 0;
1196 void send_response() override = 0;
1197 const string name() override { return "put_bucket_metadata"; }
1198 RGWOpType get_type() override { return RGW_OP_PUT_METADATA_BUCKET; }
1199 uint32_t op_mask() override { return RGW_OP_TYPE_WRITE; }
1202 class RGWPutMetadataObject : public RGWOp {
1204 RGWAccessControlPolicy policy;
1205 string placement_rule;
1206 boost::optional<ceph::real_time> delete_at;
1207 const char *dlo_manifest;
1210 RGWPutMetadataObject()
1211 : dlo_manifest(NULL)
1214 void init(RGWRados *store, struct req_state *s, RGWHandler *h) override {
1215 RGWOp::init(store, s, h);
1216 policy.set_ctx(s->cct);
1218 int verify_permission() override;
1219 void pre_exec() override;
1220 void execute() override;
1222 virtual int get_params() = 0;
1223 void send_response() override = 0;
1224 const string name() override { return "put_obj_metadata"; }
1225 RGWOpType get_type() override { return RGW_OP_PUT_METADATA_OBJECT; }
1226 uint32_t op_mask() override { return RGW_OP_TYPE_WRITE; }
1227 virtual bool need_object_expiration() { return false; }
1230 class RGWDeleteObj : public RGWOp {
1233 bool multipart_delete;
1235 ceph::real_time unmod_since; /* if unmodified since */
1236 bool no_precondition_error;
1237 std::unique_ptr<RGWBulkDelete::Deleter> deleter;
1241 : delete_marker(false),
1242 multipart_delete(false),
1243 no_precondition_error(false),
1247 int verify_permission() override;
1248 void pre_exec() override;
1249 void execute() override;
1250 int handle_slo_manifest(bufferlist& bl);
1252 virtual int get_params() { return 0; }
1253 void send_response() override = 0;
1254 const string name() override { return "delete_obj"; }
1255 RGWOpType get_type() override { return RGW_OP_DELETE_OBJ; }
1256 uint32_t op_mask() override { return RGW_OP_TYPE_DELETE; }
1257 virtual bool need_object_expiration() { return false; }
1260 class RGWCopyObj : public RGWOp {
1262 RGWAccessControlPolicy dest_policy;
1264 const char *if_unmod;
1265 const char *if_match;
1266 const char *if_nomatch;
1270 ceph::real_time mod_time;
1271 ceph::real_time unmod_time;
1272 ceph::real_time *mod_ptr;
1273 ceph::real_time *unmod_ptr;
1274 map<string, buffer::list> attrs;
1275 string src_tenant_name, src_bucket_name;
1276 rgw_bucket src_bucket;
1277 rgw_obj_key src_object;
1278 string dest_tenant_name, dest_bucket_name;
1279 rgw_bucket dest_bucket;
1281 ceph::real_time src_mtime;
1282 ceph::real_time mtime;
1283 RGWRados::AttrsMod attrs_mod;
1284 RGWBucketInfo src_bucket_info;
1285 RGWBucketInfo dest_bucket_info;
1289 ceph::buffer::list etag;
1296 boost::optional<ceph::real_time> delete_at;
1312 attrs_mod = RGWRados::ATTRSMOD_NONE;
1315 copy_if_newer = false;
1318 static bool parse_copy_location(const string& src,
1319 string& bucket_name,
1320 rgw_obj_key& object);
1322 void emplace_attr(std::string&& key, buffer::list&& bl) {
1323 attrs.emplace(std::move(key), std::move(bl));
1326 void init(RGWRados *store, struct req_state *s, RGWHandler *h) override {
1327 RGWOp::init(store, s, h);
1328 dest_policy.set_ctx(s->cct);
1330 int verify_permission() override;
1331 void pre_exec() override;
1332 void execute() override;
1333 void progress_cb(off_t ofs);
1335 virtual int init_dest_policy() { return 0; }
1336 virtual int get_params() = 0;
1337 virtual void send_partial_response(off_t ofs) {}
1338 void send_response() override = 0;
1339 const string name() override { return "copy_obj"; }
1340 RGWOpType get_type() override { return RGW_OP_COPY_OBJ; }
1341 uint32_t op_mask() override { return RGW_OP_TYPE_WRITE; }
1344 class RGWGetACLs : public RGWOp {
1351 int verify_permission() override;
1352 void pre_exec() override;
1353 void execute() override;
1355 void send_response() override = 0;
1356 const string name() override { return "get_acls"; }
1357 RGWOpType get_type() override { return RGW_OP_GET_ACLS; }
1358 uint32_t op_mask() override { return RGW_OP_TYPE_READ; }
1361 class RGWPutACLs : public RGWOp {
1372 ~RGWPutACLs() override {
1376 int verify_permission() override;
1377 void pre_exec() override;
1378 void execute() override;
1380 virtual int get_policy_from_state(RGWRados *store, struct req_state *s, stringstream& ss) { return 0; }
1381 virtual int get_params() = 0;
1382 void send_response() override = 0;
1383 const string name() override { return "put_acls"; }
1384 RGWOpType get_type() override { return RGW_OP_PUT_ACLS; }
1385 uint32_t op_mask() override { return RGW_OP_TYPE_WRITE; }
1388 class RGWGetLC : public RGWOp {
1393 ~RGWGetLC() override { }
1395 int verify_permission() override;
1396 void pre_exec() override;
1397 void execute() override = 0;
1399 void send_response() override = 0;
1400 const string name() override { return "get_lifecycle"; }
1401 RGWOpType get_type() override { return RGW_OP_GET_LC; }
1402 uint32_t op_mask() override { return RGW_OP_TYPE_READ; }
1405 class RGWPutLC : public RGWOp {
1416 ~RGWPutLC() override {
1420 void init(RGWRados *store, struct req_state *s, RGWHandler *dialect_handler) override {
1421 #define COOKIE_LEN 16
1422 char buf[COOKIE_LEN + 1];
1424 RGWOp::init(store, s, dialect_handler);
1425 gen_rand_alphanumeric(s->cct, buf, sizeof(buf) - 1);
1429 int verify_permission() override;
1430 void pre_exec() override;
1431 void execute() override;
1433 // virtual int get_policy_from_state(RGWRados *store, struct req_state *s, stringstream& ss) { return 0; }
1434 virtual int get_params() = 0;
1435 void send_response() override = 0;
1436 const string name() override { return "put_lifecycle"; }
1437 RGWOpType get_type() override { return RGW_OP_PUT_LC; }
1438 uint32_t op_mask() override { return RGW_OP_TYPE_WRITE; }
1441 class RGWDeleteLC : public RGWOp {
1451 ~RGWDeleteLC() override {
1455 int verify_permission() override;
1456 void pre_exec() override;
1457 void execute() override;
1459 void send_response() override = 0;
1460 const string name() override { return "delete_lifecycle"; }
1461 RGWOpType get_type() override { return RGW_OP_DELETE_LC; }
1462 uint32_t op_mask() override { return RGW_OP_TYPE_WRITE; }
1465 class RGWGetCORS : public RGWOp {
1471 int verify_permission() override;
1472 void execute() override;
1474 void send_response() override = 0;
1475 const string name() override { return "get_cors"; }
1476 RGWOpType get_type() override { return RGW_OP_GET_CORS; }
1477 uint32_t op_mask() override { return RGW_OP_TYPE_READ; }
1480 class RGWPutCORS : public RGWOp {
1487 ~RGWPutCORS() override {}
1489 int verify_permission() override;
1490 void execute() override;
1492 virtual int get_params() = 0;
1493 void send_response() override = 0;
1494 const string name() override { return "put_cors"; }
1495 RGWOpType get_type() override { return RGW_OP_PUT_CORS; }
1496 uint32_t op_mask() override { return RGW_OP_TYPE_WRITE; }
1499 class RGWDeleteCORS : public RGWOp {
1505 int verify_permission() override;
1506 void execute() override;
1508 void send_response() override = 0;
1509 const string name() override { return "delete_cors"; }
1510 RGWOpType get_type() override { return RGW_OP_DELETE_CORS; }
1511 uint32_t op_mask() override { return RGW_OP_TYPE_WRITE; }
1514 class RGWOptionsCORS : public RGWOp {
1517 const char *origin, *req_hdrs, *req_meth;
1520 RGWOptionsCORS() : rule(NULL), origin(NULL),
1521 req_hdrs(NULL), req_meth(NULL) {
1524 int verify_permission() override {return 0;}
1525 int validate_cors_request(RGWCORSConfiguration *cc);
1526 void execute() override;
1527 void get_response_params(string& allowed_hdrs, string& exp_hdrs, unsigned *max_age);
1528 void send_response() override = 0;
1529 const string name() override { return "options_cors"; }
1530 RGWOpType get_type() override { return RGW_OP_OPTIONS_CORS; }
1531 uint32_t op_mask() override { return RGW_OP_TYPE_READ; }
1534 class RGWGetRequestPayment : public RGWOp {
1536 bool requester_pays;
1539 RGWGetRequestPayment() : requester_pays(0) {}
1541 int verify_permission() override;
1542 void pre_exec() override;
1543 void execute() override;
1545 void send_response() override = 0;
1546 const string name() override { return "get_request_payment"; }
1547 RGWOpType get_type() override { return RGW_OP_GET_REQUEST_PAYMENT; }
1548 uint32_t op_mask() override { return RGW_OP_TYPE_READ; }
1551 class RGWSetRequestPayment : public RGWOp {
1553 bool requester_pays;
1555 RGWSetRequestPayment() : requester_pays(false) {}
1557 int verify_permission() override;
1558 void pre_exec() override;
1559 void execute() override;
1561 virtual int get_params() { return 0; }
1563 void send_response() override = 0;
1564 const string name() override { return "set_request_payment"; }
1565 RGWOpType get_type() override { return RGW_OP_SET_REQUEST_PAYMENT; }
1566 uint32_t op_mask() override { return RGW_OP_TYPE_WRITE; }
1569 class RGWInitMultipart : public RGWOp {
1572 RGWAccessControlPolicy policy;
1575 RGWInitMultipart() {}
1577 void init(RGWRados *store, struct req_state *s, RGWHandler *h) override {
1578 RGWOp::init(store, s, h);
1579 policy.set_ctx(s->cct);
1581 int verify_permission() override;
1582 void pre_exec() override;
1583 void execute() override;
1585 virtual int get_params() = 0;
1586 void send_response() override = 0;
1587 const string name() override { return "init_multipart"; }
1588 RGWOpType get_type() override { return RGW_OP_INIT_MULTIPART; }
1589 uint32_t op_mask() override { return RGW_OP_TYPE_WRITE; }
1590 virtual int prepare_encryption(map<string, bufferlist>& attrs) { return 0; }
1593 class RGWCompleteMultipart : public RGWOp {
1600 struct MPSerializer {
1601 librados::IoCtx ioctx;
1602 rados::cls::lock::Lock lock;
1603 librados::ObjectWriteOperation op;
1607 MPSerializer() : lock("RGWCompleteMultipart"), locked(false)
1610 int try_lock(const std::string& oid, utime_t dur);
1613 return lock.unlock(&ioctx, oid);
1616 void clear_locked() {
1622 RGWCompleteMultipart() {
1626 ~RGWCompleteMultipart() override {
1630 int verify_permission() override;
1631 void pre_exec() override;
1632 void execute() override;
1633 void complete() override;
1635 virtual int get_params() = 0;
1636 void send_response() override = 0;
1637 const string name() override { return "complete_multipart"; }
1638 RGWOpType get_type() override { return RGW_OP_COMPLETE_MULTIPART; }
1639 uint32_t op_mask() override { return RGW_OP_TYPE_WRITE; }
1642 class RGWAbortMultipart : public RGWOp {
1644 RGWAbortMultipart() {}
1646 int verify_permission() override;
1647 void pre_exec() override;
1648 void execute() override;
1650 void send_response() override = 0;
1651 const string name() override { return "abort_multipart"; }
1652 RGWOpType get_type() override { return RGW_OP_ABORT_MULTIPART; }
1653 uint32_t op_mask() override { return RGW_OP_TYPE_DELETE; }
1656 class RGWListMultipart : public RGWOp {
1659 map<uint32_t, RGWUploadPartInfo> parts;
1662 RGWAccessControlPolicy policy;
1666 RGWListMultipart() {
1672 void init(RGWRados *store, struct req_state *s, RGWHandler *h) override {
1673 RGWOp::init(store, s, h);
1674 policy = RGWAccessControlPolicy(s->cct);
1676 int verify_permission() override;
1677 void pre_exec() override;
1678 void execute() override;
1680 virtual int get_params() = 0;
1681 void send_response() override = 0;
1682 const string name() override { return "list_multipart"; }
1683 RGWOpType get_type() override { return RGW_OP_LIST_MULTIPART; }
1684 uint32_t op_mask() override { return RGW_OP_TYPE_READ; }
1687 struct RGWMultipartUploadEntry {
1688 rgw_bucket_dir_entry obj;
1692 class RGWListBucketMultiparts : public RGWOp {
1696 RGWMultipartUploadEntry next_marker;
1699 vector<RGWMultipartUploadEntry> uploads;
1700 map<string, bool> common_prefixes;
1705 RGWListBucketMultiparts() {
1707 is_truncated = false;
1711 void init(RGWRados *store, struct req_state *s, RGWHandler *h) override {
1712 RGWOp::init(store, s, h);
1713 max_uploads = default_max;
1716 int verify_permission() override;
1717 void pre_exec() override;
1718 void execute() override;
1720 virtual int get_params() = 0;
1721 void send_response() override = 0;
1722 const string name() override { return "list_bucket_multiparts"; }
1723 RGWOpType get_type() override { return RGW_OP_LIST_BUCKET_MULTIPARTS; }
1724 uint32_t op_mask() override { return RGW_OP_TYPE_READ; }
1728 class RGWGetCrossDomainPolicy : public RGWOp {
1730 RGWGetCrossDomainPolicy() = default;
1731 ~RGWGetCrossDomainPolicy() override = default;
1733 int verify_permission() override {
1737 void execute() override {
1741 const string name() override {
1742 return "get_crossdomain_policy";
1745 RGWOpType get_type() override {
1746 return RGW_OP_GET_CROSS_DOMAIN_POLICY;
1749 uint32_t op_mask() override {
1750 return RGW_OP_TYPE_READ;
1755 class RGWGetHealthCheck : public RGWOp {
1757 RGWGetHealthCheck() = default;
1758 ~RGWGetHealthCheck() override = default;
1760 int verify_permission() override {
1764 void execute() override;
1766 const string name() override {
1767 return "get_health_check";
1770 RGWOpType get_type() override {
1771 return RGW_OP_GET_HEALTH_CHECK;
1774 uint32_t op_mask() override {
1775 return RGW_OP_TYPE_READ;
1780 class RGWDeleteMultiObj : public RGWOp {
1788 bool acl_allowed = false;
1791 RGWDeleteMultiObj() {
1792 max_to_delete = 1000;
1796 status_dumped = false;
1798 int verify_permission() override;
1799 void pre_exec() override;
1800 void execute() override;
1802 virtual int get_params() = 0;
1803 virtual void send_status() = 0;
1804 virtual void begin_response() = 0;
1805 virtual void send_partial_response(rgw_obj_key& key, bool delete_marker,
1806 const string& marker_version_id, int ret) = 0;
1807 virtual void end_response() = 0;
1808 const string name() override { return "multi_object_delete"; }
1809 RGWOpType get_type() override { return RGW_OP_DELETE_MULTI_OBJ; }
1810 uint32_t op_mask() override { return RGW_OP_TYPE_DELETE; }
1813 class RGWInfo: public RGWOp {
1815 RGWInfo() = default;
1816 ~RGWInfo() override = default;
1818 int verify_permission() override { return 0; }
1819 const string name() override { return "get info"; }
1820 RGWOpType get_type() override { return RGW_OP_GET_INFO; }
1821 uint32_t op_mask() override { return RGW_OP_TYPE_READ; }
1824 extern int rgw_build_bucket_policies(RGWRados* store, struct req_state* s);
1825 extern int rgw_build_object_policies(RGWRados *store, struct req_state *s,
1826 bool prefetch_data);
1827 extern rgw::IAM::Environment rgw_build_iam_environment(RGWRados* store,
1828 struct req_state* s);
1830 static inline int put_data_and_throttle(RGWPutObjDataProcessor *processor,
1831 bufferlist& data, off_t ofs,
1836 void *handle = nullptr;
1839 uint64_t size = data.length();
1841 int ret = processor->handle_data(data, ofs, &handle, &obj, &again);
1844 if (handle != nullptr)
1846 ret = processor->throttle_data(handle, obj, size, need_to_wait);
1852 need_to_wait = false; /* the need to wait only applies to the first
1857 } /* put_data_and_throttle */
1863 static inline int get_system_versioning_params(req_state *s,
1864 uint64_t *olh_epoch,
1867 if (!s->system_request) {
1872 string epoch_str = s->info.args.get(RGW_SYS_PARAM_PREFIX "versioned-epoch");
1873 if (!epoch_str.empty()) {
1875 *olh_epoch = strict_strtol(epoch_str.c_str(), 10, &err);
1877 lsubdout(s->cct, rgw, 0) << "failed to parse versioned-epoch param"
1885 *version_id = s->info.args.get(RGW_SYS_PARAM_PREFIX "version-id");
1889 } /* get_system_versioning_params */
1891 static inline void format_xattr(std::string &xattr)
1893 /* If the extended attribute is not valid UTF-8, we encode it using
1894 * quoted-printable encoding.
1896 if ((check_utf8(xattr.c_str(), xattr.length()) != 0) ||
1897 (check_for_control_characters(xattr.c_str(), xattr.length()) != 0)) {
1898 static const char MIME_PREFIX_STR[] = "=?UTF-8?Q?";
1899 static const int MIME_PREFIX_LEN = sizeof(MIME_PREFIX_STR) - 1;
1900 static const char MIME_SUFFIX_STR[] = "?=";
1901 static const int MIME_SUFFIX_LEN = sizeof(MIME_SUFFIX_STR) - 1;
1902 int mlen = mime_encode_as_qp(xattr.c_str(), NULL, 0);
1903 char *mime = new char[MIME_PREFIX_LEN + mlen + MIME_SUFFIX_LEN + 1];
1904 strcpy(mime, MIME_PREFIX_STR);
1905 mime_encode_as_qp(xattr.c_str(), mime + MIME_PREFIX_LEN, mlen);
1906 strcpy(mime + MIME_PREFIX_LEN + (mlen - 1), MIME_SUFFIX_STR);
1910 } /* format_xattr */
1913 * Get the HTTP request metadata out of the req_state as a
1914 * map(<attr_name, attr_contents>, where attr_name is RGW_ATTR_PREFIX.HTTP_NAME)
1915 * s: The request state
1916 * attrs: will be filled up with attrs mapped as <attr_name, attr_contents>
1917 * On success returns 0.
1918 * On failure returns a negative error code.
1921 static inline int rgw_get_request_metadata(CephContext* const cct,
1922 struct req_info& info,
1923 std::map<std::string, ceph::bufferlist>& attrs,
1924 const bool allow_empty_attrs = true)
1926 static const std::set<std::string> blacklisted_headers = {
1927 "x-amz-server-side-encryption-customer-algorithm",
1928 "x-amz-server-side-encryption-customer-key",
1929 "x-amz-server-side-encryption-customer-key-md5"
1932 size_t valid_meta_count = 0;
1933 for (auto& kv : info.x_meta_map) {
1934 const std::string& name = kv.first;
1935 std::string& xattr = kv.second;
1937 if (blacklisted_headers.count(name) == 1) {
1938 lsubdout(cct, rgw, 10) << "skipping x>> " << name << dendl;
1940 } else if (allow_empty_attrs || !xattr.empty()) {
1941 lsubdout(cct, rgw, 10) << "x>> " << name << ":" << xattr << dendl;
1942 format_xattr(xattr);
1944 std::string attr_name(RGW_ATTR_PREFIX);
1945 attr_name.append(name);
1947 /* Check roughly whether we aren't going behind the limit on attribute
1948 * name. Passing here doesn't guarantee that an OSD will accept that
1949 * as ObjectStore::get_max_attr_name_length() can set the limit even
1950 * lower than the "osd_max_attr_name_len" configurable. */
1951 const size_t max_attr_name_len = \
1952 cct->_conf->get_val<size_t>("rgw_max_attr_name_len");
1953 if (max_attr_name_len && attr_name.length() > max_attr_name_len) {
1954 return -ENAMETOOLONG;
1957 /* Similar remarks apply to the check for value size. We're veryfing
1958 * it early at the RGW's side as it's being claimed in /info. */
1959 const size_t max_attr_size = \
1960 cct->_conf->get_val<size_t>("rgw_max_attr_size");
1961 if (max_attr_size && xattr.length() > max_attr_size) {
1965 /* Swift allows administrators to limit the number of metadats items
1966 * send _in a single request_. */
1967 const auto rgw_max_attrs_num_in_req = \
1968 cct->_conf->get_val<size_t>("rgw_max_attrs_num_in_req");
1969 if (rgw_max_attrs_num_in_req &&
1970 ++valid_meta_count > rgw_max_attrs_num_in_req) {
1974 auto rval = attrs.emplace(std::move(attr_name), ceph::bufferlist());
1975 /* At the moment the value of the freshly created attribute key-value
1976 * pair is an empty bufferlist. */
1978 ceph::bufferlist& bl = rval.first->second;
1979 bl.append(xattr.c_str(), xattr.size() + 1);
1984 } /* rgw_get_request_metadata */
1986 static inline void encode_delete_at_attr(boost::optional<ceph::real_time> delete_at,
1987 map<string, bufferlist>& attrs)
1989 if (delete_at == boost::none) {
1994 ::encode(*delete_at, delatbl);
1995 attrs[RGW_ATTR_DELETE_AT] = delatbl;
1996 } /* encode_delete_at_attr */
1998 static inline void encode_obj_tags_attr(RGWObjTags* obj_tags, map<string, bufferlist>& attrs)
2000 if (obj_tags == nullptr){
2001 // we assume the user submitted a tag format which we couldn't parse since
2002 // this wouldn't be parsed later by get/put obj tags, lets delete if the
2003 // attr was populated
2008 obj_tags->encode(tagsbl);
2009 attrs[RGW_ATTR_TAGS] = tagsbl;
2012 static inline int encode_dlo_manifest_attr(const char * const dlo_manifest,
2013 map<string, bufferlist>& attrs)
2015 string dm = dlo_manifest;
2017 if (dm.find('/') == string::npos) {
2021 bufferlist manifest_bl;
2022 manifest_bl.append(dlo_manifest, strlen(dlo_manifest) + 1);
2023 attrs[RGW_ATTR_USER_MANIFEST] = manifest_bl;
2026 } /* encode_dlo_manifest_attr */
2028 static inline void complete_etag(MD5& hash, string *etag)
2030 char etag_buf[CEPH_CRYPTO_MD5_DIGESTSIZE];
2031 char etag_buf_str[CEPH_CRYPTO_MD5_DIGESTSIZE * 2 + 16];
2033 hash.Final((byte *)etag_buf);
2034 buf_to_hex((const unsigned char *)etag_buf, CEPH_CRYPTO_MD5_DIGESTSIZE,
2037 *etag = etag_buf_str;
2038 } /* complete_etag */
2040 class RGWSetAttrs : public RGWOp {
2042 map<string, buffer::list> attrs;
2046 ~RGWSetAttrs() override {}
2048 void emplace_attr(std::string&& key, buffer::list&& bl) {
2049 attrs.emplace(std::move(key), std::move(bl));
2052 int verify_permission() override;
2053 void pre_exec() override;
2054 void execute() override;
2056 virtual int get_params() = 0;
2057 void send_response() override = 0;
2058 const string name() override { return "set_attrs"; }
2059 RGWOpType get_type() override { return RGW_OP_SET_ATTRS; }
2060 uint32_t op_mask() override { return RGW_OP_TYPE_WRITE; }
2063 class RGWGetObjLayout : public RGWOp {
2065 RGWObjManifest *manifest{nullptr};
2066 rgw_raw_obj head_obj;
2072 int check_caps(RGWUserCaps& caps) {
2073 return caps.check_cap("admin", RGW_CAP_READ);
2075 int verify_permission() {
2076 return check_caps(s->user->caps);
2081 virtual void send_response() = 0;
2082 virtual const string name() { return "get_obj_layout"; }
2083 virtual RGWOpType get_type() { return RGW_OP_GET_OBJ_LAYOUT; }
2084 virtual uint32_t op_mask() { return RGW_OP_TYPE_READ; }
2087 class RGWPutBucketPolicy : public RGWOp {
2089 char *data = nullptr;
2091 RGWPutBucketPolicy() = default;
2092 ~RGWPutBucketPolicy() {
2094 free(static_cast<void*>(data));
2097 void send_response() override;
2098 int verify_permission() override;
2099 uint32_t op_mask() override {
2100 return RGW_OP_TYPE_WRITE;
2102 void execute() override;
2104 const std::string name() override {
2105 return "put_bucket_policy";
2107 RGWOpType get_type() override {
2108 return RGW_OP_PUT_BUCKET_POLICY;
2112 class RGWGetBucketPolicy : public RGWOp {
2113 buffer::list policy;
2115 RGWGetBucketPolicy() = default;
2116 void send_response() override;
2117 int verify_permission() override;
2118 uint32_t op_mask() override {
2119 return RGW_OP_TYPE_READ;
2121 void execute() override;
2122 const std::string name() override {
2123 return "get_bucket_policy";
2125 RGWOpType get_type() override {
2126 return RGW_OP_GET_BUCKET_POLICY;
2130 class RGWDeleteBucketPolicy : public RGWOp {
2132 RGWDeleteBucketPolicy() = default;
2133 void send_response() override;
2134 int verify_permission() override;
2135 uint32_t op_mask() override {
2136 return RGW_OP_TYPE_WRITE;
2138 void execute() override;
2140 const std::string name() override {
2141 return "delete_bucket_policy";
2143 RGWOpType get_type() override {
2144 return RGW_OP_DELETE_BUCKET_POLICY;
2149 class RGWConfigBucketMetaSearch : public RGWOp {
2151 std::map<std::string, uint32_t> mdsearch_config;
2153 RGWConfigBucketMetaSearch() {}
2155 int verify_permission();
2159 virtual int get_params() = 0;
2160 virtual void send_response() = 0;
2161 virtual const string name() { return "config_bucket_meta_search"; }
2162 virtual RGWOpType get_type() { return RGW_OP_CONFIG_BUCKET_META_SEARCH; }
2163 virtual uint32_t op_mask() { return RGW_OP_TYPE_WRITE; }
2166 class RGWGetBucketMetaSearch : public RGWOp {
2168 RGWGetBucketMetaSearch() {}
2170 int verify_permission();
2174 virtual void send_response() = 0;
2175 virtual const string name() { return "get_bucket_meta_search"; }
2176 virtual RGWOpType get_type() { return RGW_OP_GET_BUCKET_META_SEARCH; }
2177 virtual uint32_t op_mask() { return RGW_OP_TYPE_READ; }
2180 class RGWDelBucketMetaSearch : public RGWOp {
2182 RGWDelBucketMetaSearch() {}
2184 int verify_permission();
2188 virtual void send_response() = 0;
2189 virtual const string name() { return "delete_bucket_meta_search"; }
2190 virtual RGWOpType delete_type() { return RGW_OP_DEL_BUCKET_META_SEARCH; }
2191 virtual uint32_t op_mask() { return RGW_OP_TYPE_WRITE; }
2194 #endif /* CEPH_RGW_OP_H */