]> git.proxmox.com Git - ceph.git/blob - ceph/src/rgw/rgw_common.h
import 14.2.4 nautilus point release
[ceph.git] / ceph / src / rgw / rgw_common.h
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3
4 /*
5 * Ceph - scalable distributed file system
6 *
7 * Copyright (C) 2004-2009 Sage Weil <sage@newdream.net>
8 * Copyright (C) 2015 Yehuda Sadeh <yehuda@redhat.com>
9 *
10 * This is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License version 2.1, as published by the Free Software
13 * Foundation. See file COPYING.
14 *
15 */
16
17 #ifndef CEPH_RGW_COMMON_H
18 #define CEPH_RGW_COMMON_H
19
20 #include <array>
21
22 #include <boost/algorithm/string.hpp>
23 #include <boost/utility/string_view.hpp>
24
25 #include "common/ceph_crypto.h"
26 #include "rgw_acl.h"
27 #include "rgw_cors.h"
28 #include "rgw_iam_policy.h"
29 #include "rgw_quota.h"
30 #include "rgw_string.h"
31 #include "common/async/yield_context.h"
32 #include "rgw_website.h"
33 #include "cls/version/cls_version_types.h"
34 #include "cls/user/cls_user_types.h"
35 #include "cls/rgw/cls_rgw_types.h"
36 #include "include/rados/librados.hpp"
37
38 namespace ceph {
39 class Formatter;
40 }
41
42 using ceph::crypto::MD5;
43
44
45 #define RGW_ATTR_PREFIX "user.rgw."
46
47 #define RGW_HTTP_RGWX_ATTR_PREFIX "RGWX_ATTR_"
48 #define RGW_HTTP_RGWX_ATTR_PREFIX_OUT "Rgwx-Attr-"
49
50 #define RGW_AMZ_PREFIX "x-amz-"
51 #define RGW_AMZ_META_PREFIX RGW_AMZ_PREFIX "meta-"
52 #define RGW_AMZ_WEBSITE_REDIRECT_LOCATION RGW_AMZ_PREFIX "website-redirect-location"
53 #define RGW_AMZ_TAG_COUNT RGW_AMZ_PREFIX "tagging-count"
54
55 #define RGW_SYS_PARAM_PREFIX "rgwx-"
56
57 #define RGW_ATTR_ACL RGW_ATTR_PREFIX "acl"
58 #define RGW_ATTR_LC RGW_ATTR_PREFIX "lc"
59 #define RGW_ATTR_CORS RGW_ATTR_PREFIX "cors"
60 #define RGW_ATTR_ETAG RGW_ATTR_PREFIX "etag"
61 #define RGW_ATTR_BUCKETS RGW_ATTR_PREFIX "buckets"
62 #define RGW_ATTR_META_PREFIX RGW_ATTR_PREFIX RGW_AMZ_META_PREFIX
63 #define RGW_ATTR_CONTENT_TYPE RGW_ATTR_PREFIX "content_type"
64 #define RGW_ATTR_CACHE_CONTROL RGW_ATTR_PREFIX "cache_control"
65 #define RGW_ATTR_CONTENT_DISP RGW_ATTR_PREFIX "content_disposition"
66 #define RGW_ATTR_CONTENT_ENC RGW_ATTR_PREFIX "content_encoding"
67 #define RGW_ATTR_CONTENT_LANG RGW_ATTR_PREFIX "content_language"
68 #define RGW_ATTR_EXPIRES RGW_ATTR_PREFIX "expires"
69 #define RGW_ATTR_DELETE_AT RGW_ATTR_PREFIX "delete_at"
70 #define RGW_ATTR_ID_TAG RGW_ATTR_PREFIX "idtag"
71 #define RGW_ATTR_TAIL_TAG RGW_ATTR_PREFIX "tail_tag"
72 #define RGW_ATTR_SHADOW_OBJ RGW_ATTR_PREFIX "shadow_name"
73 #define RGW_ATTR_MANIFEST RGW_ATTR_PREFIX "manifest"
74 #define RGW_ATTR_USER_MANIFEST RGW_ATTR_PREFIX "user_manifest"
75 #define RGW_ATTR_AMZ_WEBSITE_REDIRECT_LOCATION RGW_ATTR_PREFIX RGW_AMZ_WEBSITE_REDIRECT_LOCATION
76 #define RGW_ATTR_SLO_MANIFEST RGW_ATTR_PREFIX "slo_manifest"
77 /* Information whether an object is SLO or not must be exposed to
78 * user through custom HTTP header named X-Static-Large-Object. */
79 #define RGW_ATTR_SLO_UINDICATOR RGW_ATTR_META_PREFIX "static-large-object"
80 #define RGW_ATTR_X_ROBOTS_TAG RGW_ATTR_PREFIX "x-robots-tag"
81 #define RGW_ATTR_STORAGE_CLASS RGW_ATTR_PREFIX "storage_class"
82
83 #define RGW_ATTR_PG_VER RGW_ATTR_PREFIX "pg_ver"
84 #define RGW_ATTR_SOURCE_ZONE RGW_ATTR_PREFIX "source_zone"
85 #define RGW_ATTR_TAGS RGW_ATTR_PREFIX RGW_AMZ_PREFIX "tagging"
86
87 #define RGW_ATTR_TEMPURL_KEY1 RGW_ATTR_META_PREFIX "temp-url-key"
88 #define RGW_ATTR_TEMPURL_KEY2 RGW_ATTR_META_PREFIX "temp-url-key-2"
89
90 /* Account/container quota of the Swift API. */
91 #define RGW_ATTR_QUOTA_NOBJS RGW_ATTR_META_PREFIX "quota-count"
92 #define RGW_ATTR_QUOTA_MSIZE RGW_ATTR_META_PREFIX "quota-bytes"
93
94 /* Static Web Site of Swift API. */
95 #define RGW_ATTR_WEB_INDEX RGW_ATTR_META_PREFIX "web-index"
96 #define RGW_ATTR_WEB_ERROR RGW_ATTR_META_PREFIX "web-error"
97 #define RGW_ATTR_WEB_LISTINGS RGW_ATTR_META_PREFIX "web-listings"
98 #define RGW_ATTR_WEB_LIST_CSS RGW_ATTR_META_PREFIX "web-listings-css"
99 #define RGW_ATTR_SUBDIR_MARKER RGW_ATTR_META_PREFIX "web-directory-type"
100
101 #define RGW_ATTR_OLH_PREFIX RGW_ATTR_PREFIX "olh."
102
103 #define RGW_ATTR_OLH_INFO RGW_ATTR_OLH_PREFIX "info"
104 #define RGW_ATTR_OLH_VER RGW_ATTR_OLH_PREFIX "ver"
105 #define RGW_ATTR_OLH_ID_TAG RGW_ATTR_OLH_PREFIX "idtag"
106 #define RGW_ATTR_OLH_PENDING_PREFIX RGW_ATTR_OLH_PREFIX "pending."
107
108 #define RGW_ATTR_COMPRESSION RGW_ATTR_PREFIX "compression"
109
110 #define RGW_ATTR_APPEND_PART_NUM RGW_ATTR_PREFIX "append_part_num"
111
112 /* IAM Policy */
113 #define RGW_ATTR_IAM_POLICY RGW_ATTR_PREFIX "iam-policy"
114 #define RGW_ATTR_USER_POLICY RGW_ATTR_PREFIX "user-policy"
115
116 /* RGW File Attributes */
117 #define RGW_ATTR_UNIX_KEY1 RGW_ATTR_PREFIX "unix-key1"
118 #define RGW_ATTR_UNIX1 RGW_ATTR_PREFIX "unix1"
119
120 #define RGW_ATTR_CRYPT_PREFIX RGW_ATTR_PREFIX "crypt."
121 #define RGW_ATTR_CRYPT_MODE RGW_ATTR_CRYPT_PREFIX "mode"
122 #define RGW_ATTR_CRYPT_KEYMD5 RGW_ATTR_CRYPT_PREFIX "keymd5"
123 #define RGW_ATTR_CRYPT_KEYID RGW_ATTR_CRYPT_PREFIX "keyid"
124 #define RGW_ATTR_CRYPT_KEYSEL RGW_ATTR_CRYPT_PREFIX "keysel"
125
126 #define RGW_BUCKETS_OBJ_SUFFIX ".buckets"
127
128 #define RGW_FORMAT_PLAIN 0
129 #define RGW_FORMAT_XML 1
130 #define RGW_FORMAT_JSON 2
131 #define RGW_FORMAT_HTML 3
132
133 #define RGW_CAP_READ 0x1
134 #define RGW_CAP_WRITE 0x2
135 #define RGW_CAP_ALL (RGW_CAP_READ | RGW_CAP_WRITE)
136
137 #define RGW_REST_SWIFT 0x1
138 #define RGW_REST_SWIFT_AUTH 0x2
139 #define RGW_REST_S3 0x4
140 #define RGW_REST_WEBSITE 0x8
141 #define RGW_REST_STS 0x10
142
143 #define RGW_SUSPENDED_USER_AUID (uint64_t)-2
144
145 #define RGW_OP_TYPE_READ 0x01
146 #define RGW_OP_TYPE_WRITE 0x02
147 #define RGW_OP_TYPE_DELETE 0x04
148
149 #define RGW_OP_TYPE_MODIFY (RGW_OP_TYPE_WRITE | RGW_OP_TYPE_DELETE)
150 #define RGW_OP_TYPE_ALL (RGW_OP_TYPE_READ | RGW_OP_TYPE_WRITE | RGW_OP_TYPE_DELETE)
151
152 #define RGW_DEFAULT_MAX_BUCKETS 1000
153
154 #define RGW_DEFER_TO_BUCKET_ACLS_RECURSE 1
155 #define RGW_DEFER_TO_BUCKET_ACLS_FULL_CONTROL 2
156
157 #define STATUS_CREATED 1900
158 #define STATUS_ACCEPTED 1901
159 #define STATUS_NO_CONTENT 1902
160 #define STATUS_PARTIAL_CONTENT 1903
161 #define STATUS_REDIRECT 1904
162 #define STATUS_NO_APPLY 1905
163 #define STATUS_APPLIED 1906
164
165 #define ERR_INVALID_BUCKET_NAME 2000
166 #define ERR_INVALID_OBJECT_NAME 2001
167 #define ERR_NO_SUCH_BUCKET 2002
168 #define ERR_METHOD_NOT_ALLOWED 2003
169 #define ERR_INVALID_DIGEST 2004
170 #define ERR_BAD_DIGEST 2005
171 #define ERR_UNRESOLVABLE_EMAIL 2006
172 #define ERR_INVALID_PART 2007
173 #define ERR_INVALID_PART_ORDER 2008
174 #define ERR_NO_SUCH_UPLOAD 2009
175 #define ERR_REQUEST_TIMEOUT 2010
176 #define ERR_LENGTH_REQUIRED 2011
177 #define ERR_REQUEST_TIME_SKEWED 2012
178 #define ERR_BUCKET_EXISTS 2013
179 #define ERR_BAD_URL 2014
180 #define ERR_PRECONDITION_FAILED 2015
181 #define ERR_NOT_MODIFIED 2016
182 #define ERR_INVALID_UTF8 2017
183 #define ERR_UNPROCESSABLE_ENTITY 2018
184 #define ERR_TOO_LARGE 2019
185 #define ERR_TOO_MANY_BUCKETS 2020
186 #define ERR_INVALID_REQUEST 2021
187 #define ERR_TOO_SMALL 2022
188 #define ERR_NOT_FOUND 2023
189 #define ERR_PERMANENT_REDIRECT 2024
190 #define ERR_LOCKED 2025
191 #define ERR_QUOTA_EXCEEDED 2026
192 #define ERR_SIGNATURE_NO_MATCH 2027
193 #define ERR_INVALID_ACCESS_KEY 2028
194 #define ERR_MALFORMED_XML 2029
195 #define ERR_USER_EXIST 2030
196 #define ERR_NOT_SLO_MANIFEST 2031
197 #define ERR_EMAIL_EXIST 2032
198 #define ERR_KEY_EXIST 2033
199 #define ERR_INVALID_SECRET_KEY 2034
200 #define ERR_INVALID_KEY_TYPE 2035
201 #define ERR_INVALID_CAP 2036
202 #define ERR_INVALID_TENANT_NAME 2037
203 #define ERR_WEBSITE_REDIRECT 2038
204 #define ERR_NO_SUCH_WEBSITE_CONFIGURATION 2039
205 #define ERR_AMZ_CONTENT_SHA256_MISMATCH 2040
206 #define ERR_NO_SUCH_LC 2041
207 #define ERR_NO_SUCH_USER 2042
208 #define ERR_NO_SUCH_SUBUSER 2043
209 #define ERR_MFA_REQUIRED 2044
210 #define ERR_NO_SUCH_CORS_CONFIGURATION 2045
211 #define ERR_USER_SUSPENDED 2100
212 #define ERR_INTERNAL_ERROR 2200
213 #define ERR_NOT_IMPLEMENTED 2201
214 #define ERR_SERVICE_UNAVAILABLE 2202
215 #define ERR_ROLE_EXISTS 2203
216 #define ERR_MALFORMED_DOC 2204
217 #define ERR_NO_ROLE_FOUND 2205
218 #define ERR_DELETE_CONFLICT 2206
219 #define ERR_NO_SUCH_BUCKET_POLICY 2207
220 #define ERR_INVALID_LOCATION_CONSTRAINT 2208
221 #define ERR_TAG_CONFLICT 2209
222 #define ERR_INVALID_TAG 2210
223 #define ERR_ZERO_IN_URL 2211
224 #define ERR_MALFORMED_ACL_ERROR 2212
225 #define ERR_ZONEGROUP_DEFAULT_PLACEMENT_MISCONFIGURATION 2213
226 #define ERR_INVALID_ENCRYPTION_ALGORITHM 2214
227 #define ERR_INVALID_CORS_RULES_ERROR 2215
228 #define ERR_NO_CORS_FOUND 2216
229 #define ERR_INVALID_WEBSITE_ROUTING_RULES_ERROR 2217
230 #define ERR_RATE_LIMITED 2218
231 #define ERR_POSITION_NOT_EQUAL_TO_LENGTH 2219
232 #define ERR_OBJECT_NOT_APPENDABLE 2220
233 #define ERR_INVALID_BUCKET_STATE 2221
234
235 #define ERR_BUSY_RESHARDING 2300
236 #define ERR_NO_SUCH_ENTITY 2301
237
238 // STS Errors
239 #define ERR_PACKED_POLICY_TOO_LARGE 2400
240 #define ERR_INVALID_IDENTITY_TOKEN 2401
241
242 #ifndef UINT32_MAX
243 #define UINT32_MAX (0xffffffffu)
244 #endif
245
246 struct req_state;
247
248 typedef void *RGWAccessHandle;
249
250 /* size should be the required string size + 1 */
251 int gen_rand_base64(CephContext *cct, char *dest, int size);
252 void gen_rand_alphanumeric(CephContext *cct, char *dest, int size);
253 void gen_rand_alphanumeric_lower(CephContext *cct, char *dest, int size);
254 void gen_rand_alphanumeric_upper(CephContext *cct, char *dest, int size);
255 void gen_rand_alphanumeric_no_underscore(CephContext *cct, char *dest, int size);
256 void gen_rand_alphanumeric_plain(CephContext *cct, char *dest, int size);
257 void gen_rand_alphanumeric_lower(CephContext *cct, string *str, int length);
258
259 enum RGWIntentEvent {
260 DEL_OBJ = 0,
261 DEL_DIR = 1,
262 };
263
264 enum HostStyle {
265 PathStyle = 0,
266 VirtualStyle = 1,
267 };
268
269 /** Store error returns for output at a different point in the program */
270 struct rgw_err {
271 rgw_err();
272 void clear();
273 bool is_clear() const;
274 bool is_err() const;
275 friend std::ostream& operator<<(std::ostream& oss, const rgw_err &err);
276
277 int http_ret;
278 int ret;
279 std::string err_code;
280 std::string message;
281 };
282
283
284
285 /* Helper class used for RGWHTTPArgs parsing */
286 class NameVal
287 {
288 string str;
289 string name;
290 string val;
291 public:
292 explicit NameVal(string nv) : str(nv) {}
293
294 int parse();
295
296 string& get_name() { return name; }
297 string& get_val() { return val; }
298 };
299
300 /** Stores the XML arguments associated with the HTTP request in req_state*/
301 class RGWHTTPArgs {
302 string str, empty_str;
303 map<string, string> val_map;
304 map<string, string> sys_val_map;
305 map<string, string> sub_resources;
306 bool has_resp_modifier;
307 bool admin_subresource_added;
308 public:
309 RGWHTTPArgs() : has_resp_modifier(false), admin_subresource_added(false) {}
310
311 /** Set the arguments; as received */
312 void set(string s) {
313 has_resp_modifier = false;
314 val_map.clear();
315 sub_resources.clear();
316 str = s;
317 }
318 /** parse the received arguments */
319 int parse();
320 void append(const string& name, const string& val);
321 /** Get the value for a specific argument parameter */
322 const string& get(const string& name, bool *exists = NULL) const;
323 boost::optional<const std::string&>
324 get_optional(const std::string& name) const;
325 int get_bool(const string& name, bool *val, bool *exists);
326 int get_bool(const char *name, bool *val, bool *exists);
327 void get_bool(const char *name, bool *val, bool def_val);
328 int get_int(const char *name, int *val, int def_val);
329
330 /** Get the value for specific system argument parameter */
331 std::string sys_get(const string& name, bool *exists = nullptr) const;
332
333 /** see if a parameter is contained in this RGWHTTPArgs */
334 bool exists(const char *name) const {
335 return (val_map.find(name) != std::end(val_map));
336 }
337 bool sub_resource_exists(const char *name) const {
338 return (sub_resources.find(name) != std::end(sub_resources));
339 }
340 map<string, string>& get_params() {
341 return val_map;
342 }
343 const std::map<std::string, std::string>& get_sub_resources() const {
344 return sub_resources;
345 }
346 unsigned get_num_params() const {
347 return val_map.size();
348 }
349 bool has_response_modifier() const {
350 return has_resp_modifier;
351 }
352 void set_system() { /* make all system params visible */
353 map<string, string>::iterator iter;
354 for (iter = sys_val_map.begin(); iter != sys_val_map.end(); ++iter) {
355 val_map[iter->first] = iter->second;
356 }
357 }
358 const string& get_str() {
359 return str;
360 }
361 }; // RGWHTTPArgs
362
363 const char *rgw_conf_get(const map<string, string, ltstr_nocase>& conf_map, const char *name, const char *def_val);
364 int rgw_conf_get_int(const map<string, string, ltstr_nocase>& conf_map, const char *name, int def_val);
365 bool rgw_conf_get_bool(const map<string, string, ltstr_nocase>& conf_map, const char *name, bool def_val);
366
367 class RGWEnv;
368
369 class RGWConf {
370 friend class RGWEnv;
371 int enable_ops_log;
372 int enable_usage_log;
373 uint8_t defer_to_bucket_acls;
374 void init(CephContext *cct);
375 public:
376 RGWConf()
377 : enable_ops_log(1),
378 enable_usage_log(1),
379 defer_to_bucket_acls(0) {
380 }
381 };
382
383 class RGWEnv {
384 std::map<string, string, ltstr_nocase> env_map;
385 RGWConf conf;
386 public:
387 void init(CephContext *cct);
388 void init(CephContext *cct, char **envp);
389 void set(std::string name, std::string val);
390 const char *get(const char *name, const char *def_val = nullptr) const;
391 int get_int(const char *name, int def_val = 0) const;
392 bool get_bool(const char *name, bool def_val = 0);
393 size_t get_size(const char *name, size_t def_val = 0) const;
394 bool exists(const char *name) const;
395 bool exists_prefix(const char *prefix) const;
396 void remove(const char *name);
397 const std::map<string, string, ltstr_nocase>& get_map() const { return env_map; }
398 int get_enable_ops_log() const {
399 return conf.enable_ops_log;
400 }
401
402 int get_enable_usage_log() const {
403 return conf.enable_usage_log;
404 }
405
406 int get_defer_to_bucket_acls() const {
407 return conf.defer_to_bucket_acls;
408 }
409 };
410
411 // return true if the connection is secure. this either means that the
412 // connection arrived via ssl, or was forwarded as https by a trusted proxy
413 bool rgw_transport_is_secure(CephContext *cct, const RGWEnv& env);
414
415 enum http_op {
416 OP_GET,
417 OP_PUT,
418 OP_DELETE,
419 OP_HEAD,
420 OP_POST,
421 OP_COPY,
422 OP_OPTIONS,
423 OP_UNKNOWN,
424 };
425
426 enum RGWOpType {
427 RGW_OP_UNKNOWN = 0,
428 RGW_OP_GET_OBJ,
429 RGW_OP_LIST_BUCKETS,
430 RGW_OP_STAT_ACCOUNT,
431 RGW_OP_LIST_BUCKET,
432 RGW_OP_GET_BUCKET_LOGGING,
433 RGW_OP_GET_BUCKET_LOCATION,
434 RGW_OP_GET_BUCKET_VERSIONING,
435 RGW_OP_SET_BUCKET_VERSIONING,
436 RGW_OP_GET_BUCKET_WEBSITE,
437 RGW_OP_SET_BUCKET_WEBSITE,
438 RGW_OP_STAT_BUCKET,
439 RGW_OP_CREATE_BUCKET,
440 RGW_OP_DELETE_BUCKET,
441 RGW_OP_PUT_OBJ,
442 RGW_OP_STAT_OBJ,
443 RGW_OP_POST_OBJ,
444 RGW_OP_PUT_METADATA_ACCOUNT,
445 RGW_OP_PUT_METADATA_BUCKET,
446 RGW_OP_PUT_METADATA_OBJECT,
447 RGW_OP_SET_TEMPURL,
448 RGW_OP_DELETE_OBJ,
449 RGW_OP_COPY_OBJ,
450 RGW_OP_GET_ACLS,
451 RGW_OP_PUT_ACLS,
452 RGW_OP_GET_CORS,
453 RGW_OP_PUT_CORS,
454 RGW_OP_DELETE_CORS,
455 RGW_OP_OPTIONS_CORS,
456 RGW_OP_GET_REQUEST_PAYMENT,
457 RGW_OP_SET_REQUEST_PAYMENT,
458 RGW_OP_INIT_MULTIPART,
459 RGW_OP_COMPLETE_MULTIPART,
460 RGW_OP_ABORT_MULTIPART,
461 RGW_OP_LIST_MULTIPART,
462 RGW_OP_LIST_BUCKET_MULTIPARTS,
463 RGW_OP_DELETE_MULTI_OBJ,
464 RGW_OP_BULK_DELETE,
465 RGW_OP_SET_ATTRS,
466 RGW_OP_GET_CROSS_DOMAIN_POLICY,
467 RGW_OP_GET_HEALTH_CHECK,
468 RGW_OP_GET_INFO,
469 RGW_OP_CREATE_ROLE,
470 RGW_OP_DELETE_ROLE,
471 RGW_OP_GET_ROLE,
472 RGW_OP_MODIFY_ROLE,
473 RGW_OP_LIST_ROLES,
474 RGW_OP_PUT_ROLE_POLICY,
475 RGW_OP_GET_ROLE_POLICY,
476 RGW_OP_LIST_ROLE_POLICIES,
477 RGW_OP_DELETE_ROLE_POLICY,
478 RGW_OP_PUT_BUCKET_POLICY,
479 RGW_OP_GET_BUCKET_POLICY,
480 RGW_OP_DELETE_BUCKET_POLICY,
481 RGW_OP_PUT_OBJ_TAGGING,
482 RGW_OP_GET_OBJ_TAGGING,
483 RGW_OP_DELETE_OBJ_TAGGING,
484 RGW_OP_PUT_LC,
485 RGW_OP_GET_LC,
486 RGW_OP_DELETE_LC,
487 RGW_OP_PUT_USER_POLICY,
488 RGW_OP_GET_USER_POLICY,
489 RGW_OP_LIST_USER_POLICIES,
490 RGW_OP_DELETE_USER_POLICY,
491 /* rgw specific */
492 RGW_OP_ADMIN_SET_METADATA,
493 RGW_OP_GET_OBJ_LAYOUT,
494 RGW_OP_BULK_UPLOAD,
495 RGW_OP_METADATA_SEARCH,
496 RGW_OP_CONFIG_BUCKET_META_SEARCH,
497 RGW_OP_GET_BUCKET_META_SEARCH,
498 RGW_OP_DEL_BUCKET_META_SEARCH,
499 /* sts specific*/
500 RGW_STS_ASSUME_ROLE,
501 RGW_STS_GET_SESSION_TOKEN,
502 RGW_STS_ASSUME_ROLE_WEB_IDENTITY,
503 /* pubsub */
504 RGW_OP_PUBSUB_TOPIC_CREATE,
505 RGW_OP_PUBSUB_TOPICS_LIST,
506 RGW_OP_PUBSUB_TOPIC_GET,
507 RGW_OP_PUBSUB_TOPIC_DELETE,
508 RGW_OP_PUBSUB_SUB_CREATE,
509 RGW_OP_PUBSUB_SUB_GET,
510 RGW_OP_PUBSUB_SUB_DELETE,
511 RGW_OP_PUBSUB_SUB_PULL,
512 RGW_OP_PUBSUB_SUB_ACK,
513 RGW_OP_PUBSUB_NOTIF_CREATE,
514 RGW_OP_PUBSUB_NOTIF_DELETE,
515 RGW_OP_PUBSUB_NOTIF_LIST,
516 };
517
518 class RGWAccessControlPolicy;
519 class JSONObj;
520
521 struct RGWAccessKey {
522 string id; // AccessKey
523 string key; // SecretKey
524 string subuser;
525
526 RGWAccessKey() {}
527 RGWAccessKey(std::string _id, std::string _key)
528 : id(std::move(_id)), key(std::move(_key)) {}
529
530 void encode(bufferlist& bl) const {
531 ENCODE_START(2, 2, bl);
532 encode(id, bl);
533 encode(key, bl);
534 encode(subuser, bl);
535 ENCODE_FINISH(bl);
536 }
537
538 void decode(bufferlist::const_iterator& bl) {
539 DECODE_START_LEGACY_COMPAT_LEN_32(2, 2, 2, bl);
540 decode(id, bl);
541 decode(key, bl);
542 decode(subuser, bl);
543 DECODE_FINISH(bl);
544 }
545 void dump(Formatter *f) const;
546 void dump_plain(Formatter *f) const;
547 void dump(Formatter *f, const string& user, bool swift) const;
548 static void generate_test_instances(list<RGWAccessKey*>& o);
549
550 void decode_json(JSONObj *obj);
551 void decode_json(JSONObj *obj, bool swift);
552 };
553 WRITE_CLASS_ENCODER(RGWAccessKey)
554
555 struct RGWSubUser {
556 string name;
557 uint32_t perm_mask;
558
559 RGWSubUser() : perm_mask(0) {}
560 void encode(bufferlist& bl) const {
561 ENCODE_START(2, 2, bl);
562 encode(name, bl);
563 encode(perm_mask, bl);
564 ENCODE_FINISH(bl);
565 }
566
567 void decode(bufferlist::const_iterator& bl) {
568 DECODE_START_LEGACY_COMPAT_LEN_32(2, 2, 2, bl);
569 decode(name, bl);
570 decode(perm_mask, bl);
571 DECODE_FINISH(bl);
572 }
573 void dump(Formatter *f) const;
574 void dump(Formatter *f, const string& user) const;
575 static void generate_test_instances(list<RGWSubUser*>& o);
576
577 void decode_json(JSONObj *obj);
578 };
579 WRITE_CLASS_ENCODER(RGWSubUser)
580
581 class RGWUserCaps
582 {
583 map<string, uint32_t> caps;
584
585 int get_cap(const string& cap, string& type, uint32_t *perm);
586 int add_cap(const string& cap);
587 int remove_cap(const string& cap);
588 public:
589 static int parse_cap_perm(const string& str, uint32_t *perm);
590 int add_from_string(const string& str);
591 int remove_from_string(const string& str);
592
593 void encode(bufferlist& bl) const {
594 ENCODE_START(1, 1, bl);
595 encode(caps, bl);
596 ENCODE_FINISH(bl);
597 }
598 void decode(bufferlist::const_iterator& bl) {
599 DECODE_START(1, bl);
600 decode(caps, bl);
601 DECODE_FINISH(bl);
602 }
603 int check_cap(const string& cap, uint32_t perm);
604 bool is_valid_cap_type(const string& tp);
605 void dump(Formatter *f) const;
606 void dump(Formatter *f, const char *name) const;
607
608 void decode_json(JSONObj *obj);
609 };
610 WRITE_CLASS_ENCODER(RGWUserCaps)
611
612 void encode_json(const char *name, const obj_version& v, Formatter *f);
613 void encode_json(const char *name, const RGWUserCaps& val, Formatter *f);
614
615 void decode_json_obj(obj_version& v, JSONObj *obj);
616
617
618
619 enum RGWIdentityType
620 {
621 TYPE_NONE=0,
622 TYPE_RGW=1,
623 TYPE_KEYSTONE=2,
624 TYPE_LDAP=3,
625 TYPE_ROLE=4,
626 TYPE_WEB=5,
627 };
628
629 static string RGW_STORAGE_CLASS_STANDARD = "STANDARD";
630
631 struct rgw_placement_rule {
632 std::string name;
633 std::string storage_class;
634
635 rgw_placement_rule() {}
636 rgw_placement_rule(const string& _n, const string& _sc) : name(_n), storage_class(_sc) {}
637 rgw_placement_rule(const rgw_placement_rule& _r, const string& _sc) : name(_r.name) {
638 if (!_sc.empty()) {
639 storage_class = _sc;
640 } else {
641 storage_class = _r.storage_class;
642 }
643 }
644
645 bool empty() const {
646 return name.empty() && storage_class.empty();
647 }
648
649 void inherit_from(const rgw_placement_rule& r) {
650 if (name.empty()) {
651 name = r.name;
652 }
653 if (storage_class.empty()) {
654 storage_class = r.storage_class;
655 }
656 }
657
658 void clear() {
659 name.clear();
660 storage_class.clear();
661 }
662
663 void init(const string& n, const string& c) {
664 name = n;
665 storage_class = c;
666 }
667
668 static const string& get_canonical_storage_class(const string& storage_class) {
669 if (storage_class.empty()) {
670 return RGW_STORAGE_CLASS_STANDARD;
671 }
672 return storage_class;
673 }
674
675 const string& get_storage_class() const {
676 return get_canonical_storage_class(storage_class);
677 }
678
679 int compare(const rgw_placement_rule& r) const {
680 int c = name.compare(r.name);
681 if (c != 0) {
682 return c;
683 }
684 return get_storage_class().compare(r.get_storage_class());
685 }
686
687 bool operator==(const rgw_placement_rule& r) const {
688 return (name == r.name &&
689 get_storage_class() == r.get_storage_class());
690 }
691
692 bool operator!=(const rgw_placement_rule& r) const {
693 return !(*this == r);
694 }
695
696 void encode(bufferlist& bl) const {
697 /* no ENCODE_START/END due to backward compatibility */
698 std::string s = to_str();
699 ceph::encode(s, bl);
700 }
701
702 void decode(bufferlist::const_iterator& bl) {
703 std::string s;
704 ceph::decode(s, bl);
705 from_str(s);
706 }
707
708 std::string to_str() const {
709 if (standard_storage_class()) {
710 return name;
711 }
712 return to_str_explicit();
713 }
714
715 std::string to_str_explicit() const {
716 return name + "/" + storage_class;
717 }
718
719 void from_str(const std::string& s) {
720 size_t pos = s.find("/");
721 if (pos == std::string::npos) {
722 name = s;
723 storage_class.clear();
724 return;
725 }
726 name = s.substr(0, pos);
727 storage_class = s.substr(pos + 1);
728 }
729
730 bool standard_storage_class() const {
731 return storage_class.empty() || storage_class == RGW_STORAGE_CLASS_STANDARD;
732 }
733 };
734 WRITE_CLASS_ENCODER(rgw_placement_rule)
735
736 void encode_json(const char *name, const rgw_placement_rule& val, ceph::Formatter *f);
737 void decode_json_obj(rgw_placement_rule& v, JSONObj *obj);
738
739 inline ostream& operator<<(ostream& out, const rgw_placement_rule& rule) {
740 return out << rule.to_str();
741 }
742 struct RGWUserInfo
743 {
744 rgw_user user_id;
745 string display_name;
746 string user_email;
747 map<string, RGWAccessKey> access_keys;
748 map<string, RGWAccessKey> swift_keys;
749 map<string, RGWSubUser> subusers;
750 __u8 suspended;
751 int32_t max_buckets;
752 uint32_t op_mask;
753 RGWUserCaps caps;
754 __u8 admin;
755 __u8 system;
756 rgw_placement_rule default_placement;
757 list<string> placement_tags;
758 RGWQuotaInfo bucket_quota;
759 map<int, string> temp_url_keys;
760 RGWQuotaInfo user_quota;
761 uint32_t type;
762 set<string> mfa_ids;
763 string assumed_role_arn;
764
765 RGWUserInfo()
766 : suspended(0),
767 max_buckets(RGW_DEFAULT_MAX_BUCKETS),
768 op_mask(RGW_OP_TYPE_ALL),
769 admin(0),
770 system(0),
771 type(TYPE_NONE) {
772 }
773
774 RGWAccessKey* get_key(const string& access_key) {
775 if (access_keys.empty())
776 return nullptr;
777
778 auto k = access_keys.find(access_key);
779 if (k == access_keys.end())
780 return nullptr;
781 else
782 return &(k->second);
783 }
784
785 void encode(bufferlist& bl) const {
786 ENCODE_START(21, 9, bl);
787 encode((uint64_t)0, bl); // old auid
788 string access_key;
789 string secret_key;
790 if (!access_keys.empty()) {
791 map<string, RGWAccessKey>::const_iterator iter = access_keys.begin();
792 const RGWAccessKey& k = iter->second;
793 access_key = k.id;
794 secret_key = k.key;
795 }
796 encode(access_key, bl);
797 encode(secret_key, bl);
798 encode(display_name, bl);
799 encode(user_email, bl);
800 string swift_name;
801 string swift_key;
802 if (!swift_keys.empty()) {
803 map<string, RGWAccessKey>::const_iterator iter = swift_keys.begin();
804 const RGWAccessKey& k = iter->second;
805 swift_name = k.id;
806 swift_key = k.key;
807 }
808 encode(swift_name, bl);
809 encode(swift_key, bl);
810 encode(user_id.id, bl);
811 encode(access_keys, bl);
812 encode(subusers, bl);
813 encode(suspended, bl);
814 encode(swift_keys, bl);
815 encode(max_buckets, bl);
816 encode(caps, bl);
817 encode(op_mask, bl);
818 encode(system, bl);
819 encode(default_placement, bl);
820 encode(placement_tags, bl);
821 encode(bucket_quota, bl);
822 encode(temp_url_keys, bl);
823 encode(user_quota, bl);
824 encode(user_id.tenant, bl);
825 encode(admin, bl);
826 encode(type, bl);
827 encode(mfa_ids, bl);
828 encode(assumed_role_arn, bl);
829 ENCODE_FINISH(bl);
830 }
831 void decode(bufferlist::const_iterator& bl) {
832 DECODE_START_LEGACY_COMPAT_LEN_32(20, 9, 9, bl);
833 if (struct_v >= 2) {
834 uint64_t old_auid;
835 decode(old_auid, bl);
836 }
837 string access_key;
838 string secret_key;
839 decode(access_key, bl);
840 decode(secret_key, bl);
841 if (struct_v < 6) {
842 RGWAccessKey k;
843 k.id = access_key;
844 k.key = secret_key;
845 access_keys[access_key] = k;
846 }
847 decode(display_name, bl);
848 decode(user_email, bl);
849 /* We populate swift_keys map later nowadays, but we have to decode. */
850 string swift_name;
851 string swift_key;
852 if (struct_v >= 3) decode(swift_name, bl);
853 if (struct_v >= 4) decode(swift_key, bl);
854 if (struct_v >= 5)
855 decode(user_id.id, bl);
856 else
857 user_id.id = access_key;
858 if (struct_v >= 6) {
859 decode(access_keys, bl);
860 decode(subusers, bl);
861 }
862 suspended = 0;
863 if (struct_v >= 7) {
864 decode(suspended, bl);
865 }
866 if (struct_v >= 8) {
867 decode(swift_keys, bl);
868 }
869 if (struct_v >= 10) {
870 decode(max_buckets, bl);
871 } else {
872 max_buckets = RGW_DEFAULT_MAX_BUCKETS;
873 }
874 if (struct_v >= 11) {
875 decode(caps, bl);
876 }
877 if (struct_v >= 12) {
878 decode(op_mask, bl);
879 } else {
880 op_mask = RGW_OP_TYPE_ALL;
881 }
882 if (struct_v >= 13) {
883 decode(system, bl);
884 decode(default_placement, bl);
885 decode(placement_tags, bl); /* tags of allowed placement rules */
886 }
887 if (struct_v >= 14) {
888 decode(bucket_quota, bl);
889 }
890 if (struct_v >= 15) {
891 decode(temp_url_keys, bl);
892 }
893 if (struct_v >= 16) {
894 decode(user_quota, bl);
895 }
896 if (struct_v >= 17) {
897 decode(user_id.tenant, bl);
898 } else {
899 user_id.tenant.clear();
900 }
901 if (struct_v >= 18) {
902 decode(admin, bl);
903 }
904 if (struct_v >= 19) {
905 decode(type, bl);
906 }
907 if (struct_v >= 20) {
908 decode(mfa_ids, bl);
909 }
910 if (struct_v >= 21) {
911 decode(assumed_role_arn, bl);
912 }
913 DECODE_FINISH(bl);
914 }
915 void dump(Formatter *f) const;
916 static void generate_test_instances(list<RGWUserInfo*>& o);
917
918 void decode_json(JSONObj *obj);
919 };
920 WRITE_CLASS_ENCODER(RGWUserInfo)
921
922 struct rgw_pool {
923 std::string name;
924 std::string ns;
925
926 rgw_pool() = default;
927 rgw_pool(const rgw_pool& _p) : name(_p.name), ns(_p.ns) {}
928 rgw_pool(rgw_pool&&) = default;
929 rgw_pool(const string& _s) {
930 from_str(_s);
931 }
932 rgw_pool(const string& _name, const string& _ns) : name(_name), ns(_ns) {}
933
934 string to_str() const;
935 void from_str(const string& s);
936
937 void init(const string& _s) {
938 from_str(_s);
939 }
940
941 bool empty() const {
942 return name.empty();
943 }
944
945 int compare(const rgw_pool& p) const {
946 int r = name.compare(p.name);
947 if (r != 0) {
948 return r;
949 }
950 return ns.compare(p.ns);
951 }
952
953 void encode(bufferlist& bl) const {
954 ENCODE_START(10, 10, bl);
955 encode(name, bl);
956 encode(ns, bl);
957 ENCODE_FINISH(bl);
958 }
959
960 void decode_from_bucket(bufferlist::const_iterator& bl);
961
962 void decode(bufferlist::const_iterator& bl) {
963 DECODE_START_LEGACY_COMPAT_LEN(10, 3, 3, bl);
964
965 decode(name, bl);
966
967 if (struct_v < 10) {
968
969 /*
970 * note that rgw_pool can be used where rgw_bucket was used before
971 * therefore we inherit rgw_bucket's old versions. However, we only
972 * need the first field from rgw_bucket. unless we add more fields
973 * in which case we'll need to look at struct_v, and check the actual
974 * version. Anything older than 10 needs to be treated as old rgw_bucket
975 */
976
977 } else {
978 decode(ns, bl);
979 }
980
981 DECODE_FINISH(bl);
982 }
983
984 rgw_pool& operator=(const rgw_pool&) = default;
985
986 bool operator==(const rgw_pool& p) const {
987 return (compare(p) == 0);
988 }
989 bool operator!=(const rgw_pool& p) const {
990 return !(*this == p);
991 }
992 bool operator<(const rgw_pool& p) const {
993 int r = name.compare(p.name);
994 if (r == 0) {
995 return (ns.compare(p.ns) < 0);
996 }
997 return (r < 0);
998 }
999 };
1000 WRITE_CLASS_ENCODER(rgw_pool)
1001
1002 struct rgw_data_placement_target {
1003 rgw_pool data_pool;
1004 rgw_pool data_extra_pool;
1005 rgw_pool index_pool;
1006
1007 rgw_data_placement_target() = default;
1008 rgw_data_placement_target(const rgw_data_placement_target&) = default;
1009 rgw_data_placement_target(rgw_data_placement_target&&) = default;
1010
1011 rgw_data_placement_target(const rgw_pool& data_pool,
1012 const rgw_pool& data_extra_pool,
1013 const rgw_pool& index_pool)
1014 : data_pool(data_pool),
1015 data_extra_pool(data_extra_pool),
1016 index_pool(index_pool) {
1017 }
1018
1019 rgw_data_placement_target&
1020 operator=(const rgw_data_placement_target&) = default;
1021
1022 const rgw_pool& get_data_extra_pool() const {
1023 if (data_extra_pool.empty()) {
1024 return data_pool;
1025 }
1026 return data_extra_pool;
1027 }
1028
1029 int compare(const rgw_data_placement_target& t) {
1030 int c = data_pool.compare(t.data_pool);
1031 if (c != 0) {
1032 return c;
1033 }
1034 c = data_extra_pool.compare(t.data_extra_pool);
1035 if (c != 0) {
1036 return c;
1037 }
1038 return index_pool.compare(t.index_pool);
1039 };
1040
1041 void dump(Formatter *f) const;
1042 void decode_json(JSONObj *obj);
1043 };
1044
1045 inline ostream& operator<<(ostream& out, const rgw_pool& p) {
1046 out << p.to_str();
1047 return out;
1048 }
1049
1050 struct rgw_raw_obj {
1051 rgw_pool pool;
1052 std::string oid;
1053 std::string loc;
1054
1055 rgw_raw_obj() {}
1056 rgw_raw_obj(const rgw_pool& _pool, const std::string& _oid) {
1057 init(_pool, _oid);
1058 }
1059 rgw_raw_obj(const rgw_pool& _pool, const std::string& _oid, const string& _loc) : loc(_loc) {
1060 init(_pool, _oid);
1061 }
1062
1063 void init(const rgw_pool& _pool, const std::string& _oid) {
1064 pool = _pool;
1065 oid = _oid;
1066 }
1067
1068 bool empty() const {
1069 return oid.empty();
1070 }
1071
1072 void encode(bufferlist& bl) const {
1073 ENCODE_START(6, 6, bl);
1074 encode(pool, bl);
1075 encode(oid, bl);
1076 encode(loc, bl);
1077 ENCODE_FINISH(bl);
1078 }
1079
1080 void decode_from_rgw_obj(bufferlist::const_iterator& bl);
1081
1082 void decode(bufferlist::const_iterator& bl) {
1083 unsigned ofs = bl.get_off();
1084 DECODE_START(6, bl);
1085 if (struct_v < 6) {
1086 /*
1087 * this object was encoded as rgw_obj, prior to rgw_raw_obj been split out of it,
1088 * let's decode it as rgw_obj and convert it
1089 */
1090 bl.seek(ofs);
1091 decode_from_rgw_obj(bl);
1092 return;
1093 }
1094 decode(pool, bl);
1095 decode(oid, bl);
1096 decode(loc, bl);
1097 DECODE_FINISH(bl);
1098 }
1099
1100 bool operator<(const rgw_raw_obj& o) const {
1101 int r = pool.compare(o.pool);
1102 if (r == 0) {
1103 r = oid.compare(o.oid);
1104 if (r == 0) {
1105 r = loc.compare(o.loc);
1106 }
1107 }
1108 return (r < 0);
1109 }
1110
1111 bool operator==(const rgw_raw_obj& o) const {
1112 return (pool == o.pool && oid == o.oid && loc == o.loc);
1113 }
1114
1115 void dump(Formatter *f) const;
1116 void decode_json(JSONObj *obj);
1117 };
1118 WRITE_CLASS_ENCODER(rgw_raw_obj)
1119
1120 inline ostream& operator<<(ostream& out, const rgw_raw_obj& o) {
1121 out << o.pool << ":" << o.oid;
1122 return out;
1123 }
1124
1125 struct rgw_bucket {
1126 std::string tenant;
1127 std::string name;
1128 std::string marker;
1129 std::string bucket_id;
1130 rgw_data_placement_target explicit_placement;
1131
1132 std::string oid; /*
1133 * runtime in-memory only info. If not empty, points to the bucket instance object
1134 */
1135
1136 rgw_bucket() { }
1137 // cppcheck-suppress noExplicitConstructor
1138 explicit rgw_bucket(const rgw_user& u, const cls_user_bucket& b) :
1139 tenant(u.tenant),
1140 name(b.name),
1141 marker(b.marker),
1142 bucket_id(b.bucket_id),
1143 explicit_placement(b.explicit_placement.data_pool,
1144 b.explicit_placement.data_extra_pool,
1145 b.explicit_placement.index_pool) {}
1146 rgw_bucket(const rgw_bucket&) = default;
1147 rgw_bucket(rgw_bucket&&) = default;
1148
1149 void convert(cls_user_bucket *b) const {
1150 b->name = name;
1151 b->marker = marker;
1152 b->bucket_id = bucket_id;
1153 b->explicit_placement.data_pool = explicit_placement.data_pool.to_str();
1154 b->explicit_placement.data_extra_pool = explicit_placement.data_extra_pool.to_str();
1155 b->explicit_placement.index_pool = explicit_placement.index_pool.to_str();
1156 }
1157
1158 void encode(bufferlist& bl) const {
1159 ENCODE_START(10, 10, bl);
1160 encode(name, bl);
1161 encode(marker, bl);
1162 encode(bucket_id, bl);
1163 encode(tenant, bl);
1164 bool encode_explicit = !explicit_placement.data_pool.empty();
1165 encode(encode_explicit, bl);
1166 if (encode_explicit) {
1167 encode(explicit_placement.data_pool, bl);
1168 encode(explicit_placement.data_extra_pool, bl);
1169 encode(explicit_placement.index_pool, bl);
1170 }
1171 ENCODE_FINISH(bl);
1172 }
1173 void decode(bufferlist::const_iterator& bl) {
1174 DECODE_START_LEGACY_COMPAT_LEN(10, 3, 3, bl);
1175 decode(name, bl);
1176 if (struct_v < 10) {
1177 decode(explicit_placement.data_pool.name, bl);
1178 }
1179 if (struct_v >= 2) {
1180 decode(marker, bl);
1181 if (struct_v <= 3) {
1182 uint64_t id;
1183 decode(id, bl);
1184 char buf[16];
1185 snprintf(buf, sizeof(buf), "%" PRIu64, id);
1186 bucket_id = buf;
1187 } else {
1188 decode(bucket_id, bl);
1189 }
1190 }
1191 if (struct_v < 10) {
1192 if (struct_v >= 5) {
1193 decode(explicit_placement.index_pool.name, bl);
1194 } else {
1195 explicit_placement.index_pool = explicit_placement.data_pool;
1196 }
1197 if (struct_v >= 7) {
1198 decode(explicit_placement.data_extra_pool.name, bl);
1199 }
1200 }
1201 if (struct_v >= 8) {
1202 decode(tenant, bl);
1203 }
1204 if (struct_v >= 10) {
1205 bool decode_explicit = !explicit_placement.data_pool.empty();
1206 decode(decode_explicit, bl);
1207 if (decode_explicit) {
1208 decode(explicit_placement.data_pool, bl);
1209 decode(explicit_placement.data_extra_pool, bl);
1210 decode(explicit_placement.index_pool, bl);
1211 }
1212 }
1213 DECODE_FINISH(bl);
1214 }
1215
1216 void update_bucket_id(const string& new_bucket_id) {
1217 bucket_id = new_bucket_id;
1218 oid.clear();
1219 }
1220
1221 // format a key for the bucket/instance. pass delim=0 to skip a field
1222 std::string get_key(char tenant_delim = '/',
1223 char id_delim = ':',
1224 size_t reserve = 0) const;
1225
1226 const rgw_pool& get_data_extra_pool() const {
1227 return explicit_placement.get_data_extra_pool();
1228 }
1229
1230 void dump(Formatter *f) const;
1231 void decode_json(JSONObj *obj);
1232 static void generate_test_instances(list<rgw_bucket*>& o);
1233
1234 rgw_bucket& operator=(const rgw_bucket&) = default;
1235
1236 bool operator<(const rgw_bucket& b) const {
1237 if (tenant == b.tenant) {
1238 return name < b.name;
1239 } else {
1240 return tenant < b.tenant;
1241 }
1242 }
1243
1244 bool operator==(const rgw_bucket& b) const {
1245 return (tenant == b.tenant) && (name == b.name) && \
1246 (bucket_id == b.bucket_id);
1247 }
1248 };
1249 WRITE_CLASS_ENCODER(rgw_bucket)
1250
1251 inline ostream& operator<<(ostream& out, const rgw_bucket &b) {
1252 out << b.name << "[" << b.marker << "]";
1253 return out;
1254 }
1255
1256 struct rgw_bucket_shard {
1257 rgw_bucket bucket;
1258 int shard_id;
1259
1260 rgw_bucket_shard() : shard_id(-1) {}
1261 rgw_bucket_shard(const rgw_bucket& _b, int _sid) : bucket(_b), shard_id(_sid) {}
1262
1263 std::string get_key(char tenant_delim = '/', char id_delim = ':',
1264 char shard_delim = ':') const;
1265
1266 bool operator<(const rgw_bucket_shard& b) const {
1267 if (bucket < b.bucket) {
1268 return true;
1269 }
1270 if (b.bucket < bucket) {
1271 return false;
1272 }
1273 return shard_id < b.shard_id;
1274 }
1275 };
1276
1277
1278 struct RGWObjVersionTracker {
1279 obj_version read_version;
1280 obj_version write_version;
1281
1282 obj_version *version_for_read() {
1283 return &read_version;
1284 }
1285
1286 obj_version *version_for_write() {
1287 if (write_version.ver == 0)
1288 return NULL;
1289
1290 return &write_version;
1291 }
1292
1293 obj_version *version_for_check() {
1294 if (read_version.ver == 0)
1295 return NULL;
1296
1297 return &read_version;
1298 }
1299
1300 void prepare_op_for_read(librados::ObjectReadOperation *op);
1301 void prepare_op_for_write(librados::ObjectWriteOperation *op);
1302
1303 void apply_write() {
1304 read_version = write_version;
1305 write_version = obj_version();
1306 }
1307
1308 void clear() {
1309 read_version = obj_version();
1310 write_version = obj_version();
1311 }
1312
1313 void generate_new_write_ver(CephContext *cct);
1314 };
1315
1316 inline ostream& operator<<(ostream& out, const obj_version &v)
1317 {
1318 out << v.tag << ":" << v.ver;
1319 return out;
1320 }
1321
1322 inline ostream& operator<<(ostream& out, const RGWObjVersionTracker &ot)
1323 {
1324 out << "{r=" << ot.read_version << ",w=" << ot.write_version << "}";
1325 return out;
1326 }
1327
1328 enum RGWBucketFlags {
1329 BUCKET_SUSPENDED = 0x1,
1330 BUCKET_VERSIONED = 0x2,
1331 BUCKET_VERSIONS_SUSPENDED = 0x4,
1332 BUCKET_DATASYNC_DISABLED = 0X8,
1333 BUCKET_MFA_ENABLED = 0X10,
1334 };
1335
1336 enum RGWBucketIndexType {
1337 RGWBIType_Normal = 0,
1338 RGWBIType_Indexless = 1,
1339 };
1340
1341 inline ostream& operator<<(ostream& out, const RGWBucketIndexType &index_type)
1342 {
1343 switch (index_type) {
1344 case RGWBIType_Normal:
1345 return out << "Normal";
1346 case RGWBIType_Indexless:
1347 return out << "Indexless";
1348 default:
1349 return out << "Unknown";
1350 }
1351 }
1352
1353 struct RGWBucketInfo {
1354 enum BIShardsHashType {
1355 MOD = 0
1356 };
1357
1358 rgw_bucket bucket;
1359 rgw_user owner;
1360 uint32_t flags;
1361 string zonegroup;
1362 ceph::real_time creation_time;
1363 rgw_placement_rule placement_rule;
1364 bool has_instance_obj;
1365 RGWObjVersionTracker objv_tracker; /* we don't need to serialize this, for runtime tracking */
1366 obj_version ep_objv; /* entry point object version, for runtime tracking only */
1367 RGWQuotaInfo quota;
1368
1369 // Represents the number of bucket index object shards:
1370 // - value of 0 indicates there is no sharding (this is by default before this
1371 // feature is implemented).
1372 // - value of UINT32_T::MAX indicates this is a blind bucket.
1373 uint32_t num_shards;
1374
1375 // Represents the bucket index shard hash type.
1376 uint8_t bucket_index_shard_hash_type;
1377
1378 // Represents the shard number for blind bucket.
1379 const static uint32_t NUM_SHARDS_BLIND_BUCKET;
1380
1381 bool requester_pays;
1382
1383 bool has_website;
1384 RGWBucketWebsiteConf website_conf;
1385
1386 RGWBucketIndexType index_type = RGWBIType_Normal;
1387
1388 bool swift_versioning;
1389 string swift_ver_location;
1390
1391 map<string, uint32_t> mdsearch_config;
1392
1393 /* resharding */
1394 uint8_t reshard_status;
1395 string new_bucket_instance_id;
1396
1397 void encode(bufferlist& bl) const {
1398 ENCODE_START(19, 4, bl);
1399 encode(bucket, bl);
1400 encode(owner.id, bl);
1401 encode(flags, bl);
1402 encode(zonegroup, bl);
1403 uint64_t ct = real_clock::to_time_t(creation_time);
1404 encode(ct, bl);
1405 encode(placement_rule, bl);
1406 encode(has_instance_obj, bl);
1407 encode(quota, bl);
1408 encode(num_shards, bl);
1409 encode(bucket_index_shard_hash_type, bl);
1410 encode(requester_pays, bl);
1411 encode(owner.tenant, bl);
1412 encode(has_website, bl);
1413 if (has_website) {
1414 encode(website_conf, bl);
1415 }
1416 encode((uint32_t)index_type, bl);
1417 encode(swift_versioning, bl);
1418 if (swift_versioning) {
1419 encode(swift_ver_location, bl);
1420 }
1421 encode(creation_time, bl);
1422 encode(mdsearch_config, bl);
1423 encode(reshard_status, bl);
1424 encode(new_bucket_instance_id, bl);
1425 ENCODE_FINISH(bl);
1426 }
1427 void decode(bufferlist::const_iterator& bl) {
1428 DECODE_START_LEGACY_COMPAT_LEN_32(19, 4, 4, bl);
1429 decode(bucket, bl);
1430 if (struct_v >= 2) {
1431 string s;
1432 decode(s, bl);
1433 owner.from_str(s);
1434 }
1435 if (struct_v >= 3)
1436 decode(flags, bl);
1437 if (struct_v >= 5)
1438 decode(zonegroup, bl);
1439 if (struct_v >= 6) {
1440 uint64_t ct;
1441 decode(ct, bl);
1442 if (struct_v < 17)
1443 creation_time = ceph::real_clock::from_time_t((time_t)ct);
1444 }
1445 if (struct_v >= 7)
1446 decode(placement_rule, bl);
1447 if (struct_v >= 8)
1448 decode(has_instance_obj, bl);
1449 if (struct_v >= 9)
1450 decode(quota, bl);
1451 if (struct_v >= 10)
1452 decode(num_shards, bl);
1453 if (struct_v >= 11)
1454 decode(bucket_index_shard_hash_type, bl);
1455 if (struct_v >= 12)
1456 decode(requester_pays, bl);
1457 if (struct_v >= 13)
1458 decode(owner.tenant, bl);
1459 if (struct_v >= 14) {
1460 decode(has_website, bl);
1461 if (has_website) {
1462 decode(website_conf, bl);
1463 } else {
1464 website_conf = RGWBucketWebsiteConf();
1465 }
1466 }
1467 if (struct_v >= 15) {
1468 uint32_t it;
1469 decode(it, bl);
1470 index_type = (RGWBucketIndexType)it;
1471 } else {
1472 index_type = RGWBIType_Normal;
1473 }
1474 swift_versioning = false;
1475 swift_ver_location.clear();
1476 if (struct_v >= 16) {
1477 decode(swift_versioning, bl);
1478 if (swift_versioning) {
1479 decode(swift_ver_location, bl);
1480 }
1481 }
1482 if (struct_v >= 17) {
1483 decode(creation_time, bl);
1484 }
1485 if (struct_v >= 18) {
1486 decode(mdsearch_config, bl);
1487 }
1488 if (struct_v >= 19) {
1489 decode(reshard_status, bl);
1490 decode(new_bucket_instance_id, bl);
1491 }
1492 DECODE_FINISH(bl);
1493 }
1494 void dump(Formatter *f) const;
1495 static void generate_test_instances(list<RGWBucketInfo*>& o);
1496
1497 void decode_json(JSONObj *obj);
1498
1499 bool versioned() const { return (flags & BUCKET_VERSIONED) != 0; }
1500 int versioning_status() const { return flags & (BUCKET_VERSIONED | BUCKET_VERSIONS_SUSPENDED | BUCKET_MFA_ENABLED); }
1501 bool versioning_enabled() const { return (versioning_status() & (BUCKET_VERSIONED | BUCKET_VERSIONS_SUSPENDED)) == BUCKET_VERSIONED; }
1502 bool mfa_enabled() const { return (versioning_status() & BUCKET_MFA_ENABLED) != 0; }
1503 bool datasync_flag_enabled() const { return (flags & BUCKET_DATASYNC_DISABLED) == 0; }
1504
1505 bool has_swift_versioning() const {
1506 /* A bucket may be versioned through one mechanism only. */
1507 return swift_versioning && !versioned();
1508 }
1509
1510 RGWBucketInfo() : flags(0), has_instance_obj(false), num_shards(0), bucket_index_shard_hash_type(MOD), requester_pays(false),
1511 has_website(false), swift_versioning(false), reshard_status(0) {}
1512 };
1513 WRITE_CLASS_ENCODER(RGWBucketInfo)
1514
1515 struct RGWBucketEntryPoint
1516 {
1517 rgw_bucket bucket;
1518 rgw_user owner;
1519 ceph::real_time creation_time;
1520 bool linked;
1521
1522 bool has_bucket_info;
1523 RGWBucketInfo old_bucket_info;
1524
1525 RGWBucketEntryPoint() : linked(false), has_bucket_info(false) {}
1526
1527 void encode(bufferlist& bl) const {
1528 ENCODE_START(10, 8, bl);
1529 encode(bucket, bl);
1530 encode(owner.id, bl);
1531 encode(linked, bl);
1532 uint64_t ctime = (uint64_t)real_clock::to_time_t(creation_time);
1533 encode(ctime, bl);
1534 encode(owner, bl);
1535 encode(creation_time, bl);
1536 ENCODE_FINISH(bl);
1537 }
1538 void decode(bufferlist::const_iterator& bl) {
1539 auto orig_iter = bl;
1540 DECODE_START_LEGACY_COMPAT_LEN_32(10, 4, 4, bl);
1541 if (struct_v < 8) {
1542 /* ouch, old entry, contains the bucket info itself */
1543 old_bucket_info.decode(orig_iter);
1544 has_bucket_info = true;
1545 return;
1546 }
1547 has_bucket_info = false;
1548 decode(bucket, bl);
1549 decode(owner.id, bl);
1550 decode(linked, bl);
1551 uint64_t ctime;
1552 decode(ctime, bl);
1553 if (struct_v < 10) {
1554 creation_time = real_clock::from_time_t((time_t)ctime);
1555 }
1556 if (struct_v >= 9) {
1557 decode(owner, bl);
1558 }
1559 if (struct_v >= 10) {
1560 decode(creation_time, bl);
1561 }
1562 DECODE_FINISH(bl);
1563 }
1564
1565 void dump(Formatter *f) const;
1566 void decode_json(JSONObj *obj);
1567 };
1568 WRITE_CLASS_ENCODER(RGWBucketEntryPoint)
1569
1570 struct RGWStorageStats
1571 {
1572 RGWObjCategory category;
1573 uint64_t size;
1574 uint64_t size_rounded;
1575 uint64_t size_utilized{0}; //< size after compression, encryption
1576 uint64_t num_objects;
1577
1578 RGWStorageStats()
1579 : category(RGWObjCategory::None),
1580 size(0),
1581 size_rounded(0),
1582 num_objects(0) {}
1583
1584 void dump(Formatter *f) const;
1585 };
1586
1587 class RGWEnv;
1588
1589 /* Namespaced forward declarations. */
1590 namespace rgw {
1591 namespace auth {
1592 namespace s3 {
1593 class AWSBrowserUploadAbstractor;
1594 }
1595 class Completer;
1596 }
1597 namespace io {
1598 class BasicClient;
1599 }
1600 }
1601
1602
1603 struct req_info {
1604 const RGWEnv *env;
1605 RGWHTTPArgs args;
1606 map<string, string> x_meta_map;
1607
1608 string host;
1609 const char *method;
1610 string script_uri;
1611 string request_uri;
1612 string request_uri_aws4;
1613 string effective_uri;
1614 string request_params;
1615 string domain;
1616 string storage_class;
1617
1618 req_info(CephContext *cct, const RGWEnv *env);
1619 void rebuild_from(req_info& src);
1620 void init_meta_info(bool *found_bad_meta);
1621 };
1622
1623 typedef cls_rgw_obj_key rgw_obj_index_key;
1624
1625 struct rgw_obj_key {
1626 string name;
1627 string instance;
1628 string ns;
1629
1630 rgw_obj_key() {}
1631 // cppcheck-suppress noExplicitConstructor
1632 rgw_obj_key(const string& n) : name(n) {}
1633 rgw_obj_key(const string& n, const string& i) : name(n), instance(i) {}
1634 rgw_obj_key(const string& n, const string& i, const string& _ns) : name(n), instance(i), ns(_ns) {}
1635
1636 rgw_obj_key(const rgw_obj_index_key& k) {
1637 parse_index_key(k.name, &name, &ns);
1638 instance = k.instance;
1639 }
1640
1641 static void parse_index_key(const string& key, string *name, string *ns) {
1642 if (key[0] != '_') {
1643 *name = key;
1644 ns->clear();
1645 return;
1646 }
1647 if (key[1] == '_') {
1648 *name = key.substr(1);
1649 ns->clear();
1650 return;
1651 }
1652 ssize_t pos = key.find('_', 1);
1653 if (pos < 0) {
1654 /* shouldn't happen, just use key */
1655 *name = key;
1656 ns->clear();
1657 return;
1658 }
1659
1660 *name = key.substr(pos + 1);
1661 *ns = key.substr(1, pos -1);
1662 }
1663
1664 void set(const string& n) {
1665 name = n;
1666 instance.clear();
1667 ns.clear();
1668 }
1669
1670 void set(const string& n, const string& i) {
1671 name = n;
1672 instance = i;
1673 ns.clear();
1674 }
1675
1676 void set(const string& n, const string& i, const string& _ns) {
1677 name = n;
1678 instance = i;
1679 ns = _ns;
1680 }
1681
1682 bool set(const rgw_obj_index_key& index_key) {
1683 if (!parse_raw_oid(index_key.name, this)) {
1684 return false;
1685 }
1686 instance = index_key.instance;
1687 return true;
1688 }
1689
1690 void set_instance(const string& i) {
1691 instance = i;
1692 }
1693
1694 const string& get_instance() const {
1695 return instance;
1696 }
1697
1698 string get_index_key_name() const {
1699 if (ns.empty()) {
1700 if (name.size() < 1 || name[0] != '_') {
1701 return name;
1702 }
1703 return string("_") + name;
1704 };
1705
1706 char buf[ns.size() + 16];
1707 snprintf(buf, sizeof(buf), "_%s_", ns.c_str());
1708 return string(buf) + name;
1709 };
1710
1711 void get_index_key(rgw_obj_index_key *key) const {
1712 key->name = get_index_key_name();
1713 key->instance = instance;
1714 }
1715
1716 string get_loc() const {
1717 /*
1718 * For backward compatibility. Older versions used to have object locator on all objects,
1719 * however, the name was the effective object locator. This had the same effect as not
1720 * having object locator at all for most objects but the ones that started with underscore as
1721 * these were escaped.
1722 */
1723 if (name[0] == '_' && ns.empty()) {
1724 return name;
1725 }
1726
1727 return string();
1728 }
1729
1730 bool empty() const {
1731 return name.empty();
1732 }
1733
1734 bool have_null_instance() const {
1735 return instance == "null";
1736 }
1737
1738 bool have_instance() const {
1739 return !instance.empty();
1740 }
1741
1742 bool need_to_encode_instance() const {
1743 return have_instance() && !have_null_instance();
1744 }
1745
1746 string get_oid() const {
1747 if (ns.empty() && !need_to_encode_instance()) {
1748 if (name.size() < 1 || name[0] != '_') {
1749 return name;
1750 }
1751 return string("_") + name;
1752 }
1753
1754 string oid = "_";
1755 oid.append(ns);
1756 if (need_to_encode_instance()) {
1757 oid.append(string(":") + instance);
1758 }
1759 oid.append("_");
1760 oid.append(name);
1761 return oid;
1762 }
1763
1764 bool operator==(const rgw_obj_key& k) const {
1765 return (name.compare(k.name) == 0) &&
1766 (instance.compare(k.instance) == 0);
1767 }
1768
1769 bool operator<(const rgw_obj_key& k) const {
1770 int r = name.compare(k.name);
1771 if (r == 0) {
1772 r = instance.compare(k.instance);
1773 }
1774 return (r < 0);
1775 }
1776
1777 bool operator<=(const rgw_obj_key& k) const {
1778 return !(k < *this);
1779 }
1780
1781 static void parse_ns_field(string& ns, string& instance) {
1782 int pos = ns.find(':');
1783 if (pos >= 0) {
1784 instance = ns.substr(pos + 1);
1785 ns = ns.substr(0, pos);
1786 } else {
1787 instance.clear();
1788 }
1789 }
1790
1791 // takes an oid and parses out the namespace (ns), name, and
1792 // instance
1793 static bool parse_raw_oid(const string& oid, rgw_obj_key *key) {
1794 key->instance.clear();
1795 key->ns.clear();
1796 if (oid[0] != '_') {
1797 key->name = oid;
1798 return true;
1799 }
1800
1801 if (oid.size() >= 2 && oid[1] == '_') {
1802 key->name = oid.substr(1);
1803 return true;
1804 }
1805
1806 if (oid.size() < 3) // for namespace, min size would be 3: _x_
1807 return false;
1808
1809 size_t pos = oid.find('_', 2); // oid must match ^_[^_].+$
1810 if (pos == string::npos)
1811 return false;
1812
1813 key->ns = oid.substr(1, pos - 1);
1814 parse_ns_field(key->ns, key->instance);
1815
1816 key->name = oid.substr(pos + 1);
1817 return true;
1818 }
1819
1820 /**
1821 * Translate a namespace-mangled object name to the user-facing name
1822 * existing in the given namespace.
1823 *
1824 * If the object is part of the given namespace, it returns true
1825 * and cuts down the name to the unmangled version. If it is not
1826 * part of the given namespace, it returns false.
1827 */
1828 static bool oid_to_key_in_ns(const string& oid, rgw_obj_key *key, const string& ns) {
1829 bool ret = parse_raw_oid(oid, key);
1830 if (!ret) {
1831 return ret;
1832 }
1833
1834 return (ns == key->ns);
1835 }
1836
1837 /**
1838 * Given a mangled object name and an empty namespace string, this
1839 * function extracts the namespace into the string and sets the object
1840 * name to be the unmangled version.
1841 *
1842 * It returns true after successfully doing so, or
1843 * false if it fails.
1844 */
1845 static bool strip_namespace_from_name(string& name, string& ns, string& instance) {
1846 ns.clear();
1847 instance.clear();
1848 if (name[0] != '_') {
1849 return true;
1850 }
1851
1852 size_t pos = name.find('_', 1);
1853 if (pos == string::npos) {
1854 return false;
1855 }
1856
1857 if (name[1] == '_') {
1858 name = name.substr(1);
1859 return true;
1860 }
1861
1862 size_t period_pos = name.find('.');
1863 if (period_pos < pos) {
1864 return false;
1865 }
1866
1867 ns = name.substr(1, pos-1);
1868 name = name.substr(pos+1, string::npos);
1869
1870 parse_ns_field(ns, instance);
1871 return true;
1872 }
1873
1874 void encode(bufferlist& bl) const {
1875 ENCODE_START(2, 1, bl);
1876 encode(name, bl);
1877 encode(instance, bl);
1878 encode(ns, bl);
1879 ENCODE_FINISH(bl);
1880 }
1881 void decode(bufferlist::const_iterator& bl) {
1882 DECODE_START(2, bl);
1883 decode(name, bl);
1884 decode(instance, bl);
1885 if (struct_v >= 2) {
1886 decode(ns, bl);
1887 }
1888 DECODE_FINISH(bl);
1889 }
1890 void dump(Formatter *f) const;
1891 void decode_json(JSONObj *obj);
1892
1893 string to_str() const {
1894 if (instance.empty()) {
1895 return name;
1896 }
1897 char buf[name.size() + instance.size() + 16];
1898 snprintf(buf, sizeof(buf), "%s[%s]", name.c_str(), instance.c_str());
1899 return buf;
1900 }
1901 };
1902 WRITE_CLASS_ENCODER(rgw_obj_key)
1903
1904 inline ostream& operator<<(ostream& out, const rgw_obj_key &o) {
1905 return out << o.to_str();
1906 }
1907
1908 inline ostream& operator<<(ostream& out, const rgw_obj_index_key &o) {
1909 if (o.instance.empty()) {
1910 return out << o.name;
1911 } else {
1912 return out << o.name << "[" << o.instance << "]";
1913 }
1914 }
1915
1916 struct req_init_state {
1917 /* Keeps [[tenant]:]bucket until we parse the token. */
1918 string url_bucket;
1919 string src_bucket;
1920 };
1921
1922 #include "rgw_auth.h"
1923
1924 class RGWObjectCtx;
1925 class RGWSysObjectCtx;
1926
1927 /** Store all the state necessary to complete and respond to an HTTP request*/
1928 struct req_state : DoutPrefixProvider {
1929 CephContext *cct;
1930 rgw::io::BasicClient *cio{nullptr};
1931 http_op op{OP_UNKNOWN};
1932 RGWOpType op_type{};
1933 bool content_started{false};
1934 int format{0};
1935 ceph::Formatter *formatter{nullptr};
1936 string decoded_uri;
1937 string relative_uri;
1938 const char *length{nullptr};
1939 int64_t content_length{0};
1940 map<string, string> generic_attrs;
1941 rgw_err err;
1942 bool expect_cont{false};
1943 uint64_t obj_size{0};
1944 bool enable_ops_log;
1945 bool enable_usage_log;
1946 uint8_t defer_to_bucket_acls;
1947 uint32_t perm_mask{0};
1948
1949 /* Set once when url_bucket is parsed and not violated thereafter. */
1950 string account_name;
1951
1952 string bucket_tenant;
1953 string bucket_name;
1954
1955 rgw_bucket bucket;
1956 rgw_obj_key object;
1957 string src_tenant_name;
1958 string src_bucket_name;
1959 rgw_obj_key src_object;
1960 ACLOwner bucket_owner;
1961 ACLOwner owner;
1962
1963 string zonegroup_name;
1964 string zonegroup_endpoint;
1965 string bucket_instance_id;
1966 int bucket_instance_shard_id{-1};
1967 string redirect_zone_endpoint;
1968
1969 string redirect;
1970
1971 RGWBucketInfo bucket_info;
1972 real_time bucket_mtime;
1973 std::map<std::string, ceph::bufferlist> bucket_attrs;
1974 bool bucket_exists{false};
1975 rgw_placement_rule dest_placement;
1976
1977 bool has_bad_meta{false};
1978
1979 RGWUserInfo *user;
1980
1981 struct {
1982 /* TODO(rzarzynski): switch out to the static_ptr for both members. */
1983
1984 /* Object having the knowledge about an authenticated identity and allowing
1985 * to apply it during the authorization phase (verify_permission() methods
1986 * of a given RGWOp). Thus, it bounds authentication and authorization steps
1987 * through a well-defined interface. For more details, see rgw_auth.h. */
1988 std::unique_ptr<rgw::auth::Identity> identity;
1989
1990 std::shared_ptr<rgw::auth::Completer> completer;
1991
1992 /* A container for credentials of the S3's browser upload. It's necessary
1993 * because: 1) the ::authenticate() method of auth engines and strategies
1994 * take req_state only; 2) auth strategies live much longer than RGWOps -
1995 * there is no way to pass additional data dependencies through ctors. */
1996 class {
1997 /* Writer. */
1998 friend class RGWPostObj_ObjStore_S3;
1999 /* Reader. */
2000 friend class rgw::auth::s3::AWSBrowserUploadAbstractor;
2001
2002 std::string access_key;
2003 std::string signature;
2004 std::string x_amz_algorithm;
2005 std::string x_amz_credential;
2006 std::string x_amz_date;
2007 std::string x_amz_security_token;
2008 ceph::bufferlist encoded_policy;
2009 } s3_postobj_creds;
2010 } auth;
2011
2012 std::unique_ptr<RGWAccessControlPolicy> user_acl;
2013 std::unique_ptr<RGWAccessControlPolicy> bucket_acl;
2014 std::unique_ptr<RGWAccessControlPolicy> object_acl;
2015
2016 rgw::IAM::Environment env;
2017 boost::optional<rgw::IAM::Policy> iam_policy;
2018 vector<rgw::IAM::Policy> iam_user_policies;
2019
2020 /* Is the request made by an user marked as a system one?
2021 * Being system user means we also have the admin status. */
2022 bool system_request{false};
2023
2024 string canned_acl;
2025 bool has_acl_header{false};
2026 bool local_source{false}; /* source is local */
2027
2028 int prot_flags{0};
2029
2030 /* Content-Disposition override for TempURL of Swift API. */
2031 struct {
2032 string override;
2033 string fallback;
2034 } content_disp;
2035
2036 string host_id;
2037
2038 req_info info;
2039 req_init_state init_state;
2040
2041 using Clock = ceph::coarse_real_clock;
2042 Clock::time_point time;
2043
2044 Clock::duration time_elapsed() const { return Clock::now() - time; }
2045
2046 RGWObjectCtx *obj_ctx{nullptr};
2047 RGWSysObjectCtx *sysobj_ctx{nullptr};
2048 string dialect;
2049 string req_id;
2050 string trans_id;
2051 uint64_t id;
2052
2053 bool mfa_verified{false};
2054
2055 /// optional coroutine context
2056 optional_yield yield{null_yield};
2057
2058 req_state(CephContext* _cct, RGWEnv* e, RGWUserInfo* u, uint64_t id);
2059 ~req_state();
2060
2061 bool is_err() const { return err.is_err(); }
2062
2063 // implements DoutPrefixProvider
2064 std::ostream& gen_prefix(std::ostream& out) const override;
2065 CephContext* get_cct() const override { return cct; }
2066 unsigned get_subsys() const override { return ceph_subsys_rgw; }
2067 };
2068
2069 void set_req_state_err(struct req_state*, int);
2070 void set_req_state_err(struct req_state*, int, const string&);
2071 void set_req_state_err(struct rgw_err&, int, const int);
2072 void dump(struct req_state*);
2073
2074 /** Store basic data on bucket */
2075 struct RGWBucketEnt {
2076 rgw_bucket bucket;
2077 size_t size;
2078 size_t size_rounded;
2079 ceph::real_time creation_time;
2080 uint64_t count;
2081
2082 /* The placement_rule is necessary to calculate per-storage-policy statics
2083 * of the Swift API. Although the info available in RGWBucketInfo, we need
2084 * to duplicate it here to not affect the performance of buckets listing. */
2085 rgw_placement_rule placement_rule;
2086
2087 RGWBucketEnt()
2088 : size(0),
2089 size_rounded(0),
2090 count(0) {
2091 }
2092 RGWBucketEnt(const RGWBucketEnt&) = default;
2093 RGWBucketEnt(RGWBucketEnt&&) = default;
2094 explicit RGWBucketEnt(const rgw_user& u, cls_user_bucket_entry&& e)
2095 : bucket(u, std::move(e.bucket)),
2096 size(e.size),
2097 size_rounded(e.size_rounded),
2098 creation_time(e.creation_time),
2099 count(e.count) {
2100 }
2101
2102 RGWBucketEnt& operator=(const RGWBucketEnt&) = default;
2103
2104 void convert(cls_user_bucket_entry *b) const {
2105 bucket.convert(&b->bucket);
2106 b->size = size;
2107 b->size_rounded = size_rounded;
2108 b->creation_time = creation_time;
2109 b->count = count;
2110 }
2111
2112 void encode(bufferlist& bl) const {
2113 ENCODE_START(7, 5, bl);
2114 uint64_t s = size;
2115 __u32 mt = ceph::real_clock::to_time_t(creation_time);
2116 string empty_str; // originally had the bucket name here, but we encode bucket later
2117 encode(empty_str, bl);
2118 encode(s, bl);
2119 encode(mt, bl);
2120 encode(count, bl);
2121 encode(bucket, bl);
2122 s = size_rounded;
2123 encode(s, bl);
2124 encode(creation_time, bl);
2125 encode(placement_rule, bl);
2126 ENCODE_FINISH(bl);
2127 }
2128 void decode(bufferlist::const_iterator& bl) {
2129 DECODE_START_LEGACY_COMPAT_LEN(7, 5, 5, bl);
2130 __u32 mt;
2131 uint64_t s;
2132 string empty_str; // backward compatibility
2133 decode(empty_str, bl);
2134 decode(s, bl);
2135 decode(mt, bl);
2136 size = s;
2137 if (struct_v < 6) {
2138 creation_time = ceph::real_clock::from_time_t(mt);
2139 }
2140 if (struct_v >= 2)
2141 decode(count, bl);
2142 if (struct_v >= 3)
2143 decode(bucket, bl);
2144 if (struct_v >= 4)
2145 decode(s, bl);
2146 size_rounded = s;
2147 if (struct_v >= 6)
2148 decode(creation_time, bl);
2149 if (struct_v >= 7)
2150 decode(placement_rule, bl);
2151 DECODE_FINISH(bl);
2152 }
2153 void dump(Formatter *f) const;
2154 static void generate_test_instances(list<RGWBucketEnt*>& o);
2155 };
2156 WRITE_CLASS_ENCODER(RGWBucketEnt)
2157
2158 struct rgw_obj {
2159 rgw_bucket bucket;
2160 rgw_obj_key key;
2161
2162 bool in_extra_data{false}; /* in-memory only member, does not serialize */
2163
2164 // Represents the hash index source for this object once it is set (non-empty)
2165 std::string index_hash_source;
2166
2167 rgw_obj() {}
2168 rgw_obj(const rgw_bucket& b, const std::string& name) : bucket(b), key(name) {}
2169 rgw_obj(const rgw_bucket& b, const rgw_obj_key& k) : bucket(b), key(k) {}
2170 rgw_obj(const rgw_bucket& b, const rgw_obj_index_key& k) : bucket(b), key(k) {}
2171
2172 void init(const rgw_bucket& b, const std::string& name) {
2173 bucket = b;
2174 key.set(name);
2175 }
2176 void init(const rgw_bucket& b, const std::string& name, const string& i, const string& n) {
2177 bucket = b;
2178 key.set(name, i, n);
2179 }
2180 void init_ns(const rgw_bucket& b, const std::string& name, const string& n) {
2181 bucket = b;
2182 key.name = name;
2183 key.instance.clear();
2184 key.ns = n;
2185 }
2186
2187 bool empty() const {
2188 return key.empty();
2189 }
2190
2191 void set_key(const rgw_obj_key& k) {
2192 key = k;
2193 }
2194
2195 string get_oid() const {
2196 return key.get_oid();
2197 }
2198
2199 const string& get_hash_object() const {
2200 return index_hash_source.empty() ? key.name : index_hash_source;
2201 }
2202
2203 void set_in_extra_data(bool val) {
2204 in_extra_data = val;
2205 }
2206
2207 bool is_in_extra_data() const {
2208 return in_extra_data;
2209 }
2210
2211 void encode(bufferlist& bl) const {
2212 ENCODE_START(6, 6, bl);
2213 encode(bucket, bl);
2214 encode(key.ns, bl);
2215 encode(key.name, bl);
2216 encode(key.instance, bl);
2217 // encode(placement_id, bl);
2218 ENCODE_FINISH(bl);
2219 }
2220 void decode(bufferlist::const_iterator& bl) {
2221 DECODE_START_LEGACY_COMPAT_LEN(6, 3, 3, bl);
2222 if (struct_v < 6) {
2223 string s;
2224 decode(bucket.name, bl); /* bucket.name */
2225 decode(s, bl); /* loc */
2226 decode(key.ns, bl);
2227 decode(key.name, bl);
2228 if (struct_v >= 2)
2229 decode(bucket, bl);
2230 if (struct_v >= 4)
2231 decode(key.instance, bl);
2232 if (key.ns.empty() && key.instance.empty()) {
2233 if (key.name[0] == '_') {
2234 key.name = key.name.substr(1);
2235 }
2236 } else {
2237 if (struct_v >= 5) {
2238 decode(key.name, bl);
2239 } else {
2240 ssize_t pos = key.name.find('_', 1);
2241 if (pos < 0) {
2242 throw buffer::error();
2243 }
2244 key.name = key.name.substr(pos + 1);
2245 }
2246 }
2247 } else {
2248 decode(bucket, bl);
2249 decode(key.ns, bl);
2250 decode(key.name, bl);
2251 decode(key.instance, bl);
2252 // decode(placement_id, bl);
2253 }
2254 DECODE_FINISH(bl);
2255 }
2256 void dump(Formatter *f) const;
2257 static void generate_test_instances(list<rgw_obj*>& o);
2258
2259 bool operator==(const rgw_obj& o) const {
2260 return (key == o.key) &&
2261 (bucket == o.bucket);
2262 }
2263 bool operator<(const rgw_obj& o) const {
2264 int r = key.name.compare(o.key.name);
2265 if (r == 0) {
2266 r = bucket.bucket_id.compare(o.bucket.bucket_id); /* not comparing bucket.name, if bucket_id is equal so will be bucket.name */
2267 if (r == 0) {
2268 r = key.ns.compare(o.key.ns);
2269 if (r == 0) {
2270 r = key.instance.compare(o.key.instance);
2271 }
2272 }
2273 }
2274
2275 return (r < 0);
2276 }
2277
2278 const rgw_pool& get_explicit_data_pool() {
2279 if (!in_extra_data || bucket.explicit_placement.data_extra_pool.empty()) {
2280 return bucket.explicit_placement.data_pool;
2281 }
2282 return bucket.explicit_placement.data_extra_pool;
2283 }
2284 };
2285 WRITE_CLASS_ENCODER(rgw_obj)
2286
2287 struct rgw_cache_entry_info {
2288 string cache_locator;
2289 uint64_t gen;
2290
2291 rgw_cache_entry_info() : gen(0) {}
2292 };
2293
2294 inline ostream& operator<<(ostream& out, const rgw_obj &o) {
2295 return out << o.bucket.name << ":" << o.get_oid();
2296 }
2297
2298 static inline void buf_to_hex(const unsigned char* const buf,
2299 const size_t len,
2300 char* const str)
2301 {
2302 str[0] = '\0';
2303 for (size_t i = 0; i < len; i++) {
2304 ::sprintf(&str[i*2], "%02x", static_cast<int>(buf[i]));
2305 }
2306 }
2307
2308 template<size_t N> static inline std::array<char, N * 2 + 1>
2309 buf_to_hex(const std::array<unsigned char, N>& buf)
2310 {
2311 static_assert(N > 0, "The input array must be at least one element long");
2312
2313 std::array<char, N * 2 + 1> hex_dest;
2314 buf_to_hex(buf.data(), N, hex_dest.data());
2315 return hex_dest;
2316 }
2317
2318 static inline int hexdigit(char c)
2319 {
2320 if (c >= '0' && c <= '9')
2321 return (c - '0');
2322 c = toupper(c);
2323 if (c >= 'A' && c <= 'F')
2324 return c - 'A' + 0xa;
2325 return -EINVAL;
2326 }
2327
2328 static inline int hex_to_buf(const char *hex, char *buf, int len)
2329 {
2330 int i = 0;
2331 const char *p = hex;
2332 while (*p) {
2333 if (i >= len)
2334 return -EINVAL;
2335 buf[i] = 0;
2336 int d = hexdigit(*p);
2337 if (d < 0)
2338 return d;
2339 buf[i] = d << 4;
2340 p++;
2341 if (!*p)
2342 return -EINVAL;
2343 d = hexdigit(*p);
2344 if (d < 0)
2345 return d;
2346 buf[i] += d;
2347 i++;
2348 p++;
2349 }
2350 return i;
2351 }
2352
2353 static inline int rgw_str_to_bool(const char *s, int def_val)
2354 {
2355 if (!s)
2356 return def_val;
2357
2358 return (strcasecmp(s, "true") == 0 ||
2359 strcasecmp(s, "on") == 0 ||
2360 strcasecmp(s, "yes") == 0 ||
2361 strcasecmp(s, "1") == 0);
2362 }
2363
2364 static inline void append_rand_alpha(CephContext *cct, const string& src, string& dest, int len)
2365 {
2366 dest = src;
2367 char buf[len + 1];
2368 gen_rand_alphanumeric(cct, buf, len);
2369 dest.append("_");
2370 dest.append(buf);
2371 }
2372
2373 static inline const char *rgw_obj_category_name(RGWObjCategory category)
2374 {
2375 switch (category) {
2376 case RGWObjCategory::None:
2377 return "rgw.none";
2378 case RGWObjCategory::Main:
2379 return "rgw.main";
2380 case RGWObjCategory::Shadow:
2381 return "rgw.shadow";
2382 case RGWObjCategory::MultiMeta:
2383 return "rgw.multimeta";
2384 }
2385
2386 return "unknown";
2387 }
2388
2389 static inline uint64_t rgw_rounded_kb(uint64_t bytes)
2390 {
2391 return (bytes + 1023) / 1024;
2392 }
2393
2394 static inline uint64_t rgw_rounded_objsize(uint64_t bytes)
2395 {
2396 return ((bytes + 4095) & ~4095);
2397 }
2398
2399 static inline uint64_t rgw_rounded_objsize_kb(uint64_t bytes)
2400 {
2401 return ((bytes + 4095) & ~4095) / 1024;
2402 }
2403
2404 /* implement combining step, S3 header canonicalization; k is a
2405 * valid header and in lc form */
2406 static inline void add_amz_meta_header(
2407 std::map<std::string, std::string>& x_meta_map,
2408 const std::string& k,
2409 const std::string& v)
2410 {
2411 auto it = x_meta_map.find(k);
2412 if (it != x_meta_map.end()) {
2413 std::string old = it->second;
2414 boost::algorithm::trim_right(old);
2415 old.append(",");
2416 old.append(v);
2417 x_meta_map[k] = old;
2418 } else {
2419 x_meta_map[k] = v;
2420 }
2421 } /* add_amz_meta_header */
2422
2423 extern string rgw_string_unquote(const string& s);
2424 extern void parse_csv_string(const string& ival, vector<string>& ovals);
2425 extern int parse_key_value(string& in_str, string& key, string& val);
2426 extern int parse_key_value(string& in_str, const char *delim, string& key, string& val);
2427
2428 extern boost::optional<std::pair<boost::string_view, boost::string_view>>
2429 parse_key_value(const boost::string_view& in_str,
2430 const boost::string_view& delim);
2431 extern boost::optional<std::pair<boost::string_view, boost::string_view>>
2432 parse_key_value(const boost::string_view& in_str);
2433
2434
2435 /** time parsing */
2436 extern int parse_time(const char *time_str, real_time *time);
2437 extern bool parse_rfc2616(const char *s, struct tm *t);
2438 extern bool parse_iso8601(const char *s, struct tm *t, uint32_t *pns = NULL, bool extended_format = true);
2439 extern string rgw_trim_whitespace(const string& src);
2440 extern boost::string_view rgw_trim_whitespace(const boost::string_view& src);
2441 extern string rgw_trim_quotes(const string& val);
2442
2443 extern void rgw_to_iso8601(const real_time& t, char *dest, int buf_size);
2444 extern void rgw_to_iso8601(const real_time& t, string *dest);
2445 extern std::string rgw_to_asctime(const utime_t& t);
2446
2447 /** Check if the req_state's user has the necessary permissions
2448 * to do the requested action */
2449 rgw::IAM::Effect eval_user_policies(const vector<rgw::IAM::Policy>& user_policies,
2450 const rgw::IAM::Environment& env,
2451 boost::optional<const rgw::auth::Identity&> id,
2452 const uint64_t op,
2453 const rgw::IAM::ARN& arn);
2454 bool verify_user_permission(const DoutPrefixProvider* dpp,
2455 struct req_state * const s,
2456 RGWAccessControlPolicy * const user_acl,
2457 const vector<rgw::IAM::Policy>& user_policies,
2458 const rgw::IAM::ARN& res,
2459 const uint64_t op);
2460 bool verify_user_permission_no_policy(const DoutPrefixProvider* dpp,
2461 struct req_state * const s,
2462 RGWAccessControlPolicy * const user_acl,
2463 const int perm);
2464 bool verify_user_permission(const DoutPrefixProvider* dpp,
2465 struct req_state * const s,
2466 const rgw::IAM::ARN& res,
2467 const uint64_t op);
2468 bool verify_user_permission_no_policy(const DoutPrefixProvider* dpp,
2469 struct req_state * const s,
2470 int perm);
2471 bool verify_bucket_permission(
2472 const DoutPrefixProvider* dpp,
2473 struct req_state * const s,
2474 const rgw_bucket& bucket,
2475 RGWAccessControlPolicy * const user_acl,
2476 RGWAccessControlPolicy * const bucket_acl,
2477 const boost::optional<rgw::IAM::Policy>& bucket_policy,
2478 const vector<rgw::IAM::Policy>& user_policies,
2479 const uint64_t op);
2480 bool verify_bucket_permission(const DoutPrefixProvider* dpp, struct req_state * const s, const uint64_t op);
2481 bool verify_bucket_permission_no_policy(
2482 const DoutPrefixProvider* dpp,
2483 struct req_state * const s,
2484 RGWAccessControlPolicy * const user_acl,
2485 RGWAccessControlPolicy * const bucket_acl,
2486 const int perm);
2487 bool verify_bucket_permission_no_policy(const DoutPrefixProvider* dpp,
2488 struct req_state * const s,
2489 const int perm);
2490 int verify_bucket_owner_or_policy(struct req_state* const s,
2491 const uint64_t op);
2492 extern bool verify_object_permission(
2493 const DoutPrefixProvider* dpp,
2494 struct req_state * const s,
2495 const rgw_obj& obj,
2496 RGWAccessControlPolicy * const user_acl,
2497 RGWAccessControlPolicy * const bucket_acl,
2498 RGWAccessControlPolicy * const object_acl,
2499 const boost::optional<rgw::IAM::Policy>& bucket_policy,
2500 const vector<rgw::IAM::Policy>& user_policies,
2501 const uint64_t op);
2502 extern bool verify_object_permission(const DoutPrefixProvider* dpp, struct req_state *s, uint64_t op);
2503 extern bool verify_object_permission_no_policy(
2504 const DoutPrefixProvider* dpp,
2505 struct req_state * const s,
2506 RGWAccessControlPolicy * const user_acl,
2507 RGWAccessControlPolicy * const bucket_acl,
2508 RGWAccessControlPolicy * const object_acl,
2509 int perm);
2510 extern bool verify_object_permission_no_policy(const DoutPrefixProvider* dpp, struct req_state *s,
2511 int perm);
2512 /** Convert an input URL into a sane object name
2513 * by converting %-escaped strings into characters, etc*/
2514 extern void rgw_uri_escape_char(char c, string& dst);
2515 extern std::string url_decode(const boost::string_view& src_str,
2516 bool in_query = false);
2517 extern void url_encode(const std::string& src, string& dst,
2518 bool encode_slash = true);
2519 extern std::string url_encode(const std::string& src, bool encode_slash = true);
2520 /* destination should be CEPH_CRYPTO_HMACSHA1_DIGESTSIZE bytes long */
2521 extern void calc_hmac_sha1(const char *key, int key_len,
2522 const char *msg, int msg_len, char *dest);
2523
2524 static inline sha1_digest_t
2525 calc_hmac_sha1(const boost::string_view& key, const boost::string_view& msg) {
2526 sha1_digest_t dest;
2527 calc_hmac_sha1(key.data(), key.size(), msg.data(), msg.size(),
2528 reinterpret_cast<char*>(dest.v));
2529 return dest;
2530 }
2531
2532 /* destination should be CEPH_CRYPTO_HMACSHA256_DIGESTSIZE bytes long */
2533 extern void calc_hmac_sha256(const char *key, int key_len,
2534 const char *msg, int msg_len,
2535 char *dest);
2536
2537 static inline sha256_digest_t
2538 calc_hmac_sha256(const char *key, const int key_len,
2539 const char *msg, const int msg_len) {
2540 sha256_digest_t dest;
2541 calc_hmac_sha256(key, key_len, msg, msg_len,
2542 reinterpret_cast<char*>(dest.v));
2543 return dest;
2544 }
2545
2546 static inline sha256_digest_t
2547 calc_hmac_sha256(const boost::string_view& key, const boost::string_view& msg) {
2548 sha256_digest_t dest;
2549 calc_hmac_sha256(key.data(), key.size(),
2550 msg.data(), msg.size(),
2551 reinterpret_cast<char*>(dest.v));
2552 return dest;
2553 }
2554
2555 static inline sha256_digest_t
2556 calc_hmac_sha256(const sha256_digest_t &key,
2557 const boost::string_view& msg) {
2558 sha256_digest_t dest;
2559 calc_hmac_sha256(reinterpret_cast<const char*>(key.v), sha256_digest_t::SIZE,
2560 msg.data(), msg.size(),
2561 reinterpret_cast<char*>(dest.v));
2562 return dest;
2563 }
2564
2565 static inline sha256_digest_t
2566 calc_hmac_sha256(const std::vector<unsigned char>& key,
2567 const boost::string_view& msg) {
2568 sha256_digest_t dest;
2569 calc_hmac_sha256(reinterpret_cast<const char*>(key.data()), key.size(),
2570 msg.data(), msg.size(),
2571 reinterpret_cast<char*>(dest.v));
2572 return dest;
2573 }
2574
2575 template<size_t KeyLenN>
2576 static inline sha256_digest_t
2577 calc_hmac_sha256(const std::array<unsigned char, KeyLenN>& key,
2578 const boost::string_view& msg) {
2579 sha256_digest_t dest;
2580 calc_hmac_sha256(reinterpret_cast<const char*>(key.data()), key.size(),
2581 msg.data(), msg.size(),
2582 reinterpret_cast<char*>(dest.v));
2583 return dest;
2584 }
2585
2586 extern sha256_digest_t calc_hash_sha256(const boost::string_view& msg);
2587
2588 extern ceph::crypto::SHA256* calc_hash_sha256_open_stream();
2589 extern void calc_hash_sha256_update_stream(ceph::crypto::SHA256* hash,
2590 const char* msg,
2591 int len);
2592 extern std::string calc_hash_sha256_close_stream(ceph::crypto::SHA256** phash);
2593 extern std::string calc_hash_sha256_restart_stream(ceph::crypto::SHA256** phash);
2594
2595 extern int rgw_parse_op_type_list(const string& str, uint32_t *perm);
2596
2597 static constexpr uint32_t MATCH_POLICY_ACTION = 0x01;
2598 static constexpr uint32_t MATCH_POLICY_RESOURCE = 0x02;
2599 static constexpr uint32_t MATCH_POLICY_ARN = 0x04;
2600 static constexpr uint32_t MATCH_POLICY_STRING = 0x08;
2601
2602 extern bool match_policy(boost::string_view pattern, boost::string_view input,
2603 uint32_t flag);
2604
2605 extern string camelcase_dash_http_attr(const string& orig);
2606 extern string lowercase_dash_http_attr(const string& orig);
2607
2608 void rgw_setup_saved_curl_handles();
2609 void rgw_release_all_curl_handles();
2610
2611 static inline void rgw_escape_str(const string& s, char esc_char,
2612 char special_char, string *dest)
2613 {
2614 const char *src = s.c_str();
2615 char dest_buf[s.size() * 2 + 1];
2616 char *destp = dest_buf;
2617
2618 for (size_t i = 0; i < s.size(); i++) {
2619 char c = src[i];
2620 if (c == esc_char || c == special_char) {
2621 *destp++ = esc_char;
2622 }
2623 *destp++ = c;
2624 }
2625 *destp++ = '\0';
2626 *dest = dest_buf;
2627 }
2628
2629 static inline ssize_t rgw_unescape_str(const string& s, ssize_t ofs,
2630 char esc_char, char special_char,
2631 string *dest)
2632 {
2633 const char *src = s.c_str();
2634 char dest_buf[s.size() + 1];
2635 char *destp = dest_buf;
2636 bool esc = false;
2637
2638 dest_buf[0] = '\0';
2639
2640 for (size_t i = ofs; i < s.size(); i++) {
2641 char c = src[i];
2642 if (!esc && c == esc_char) {
2643 esc = true;
2644 continue;
2645 }
2646 if (!esc && c == special_char) {
2647 *destp = '\0';
2648 *dest = dest_buf;
2649 return (ssize_t)i + 1;
2650 }
2651 *destp++ = c;
2652 esc = false;
2653 }
2654 *destp = '\0';
2655 *dest = dest_buf;
2656 return string::npos;
2657 }
2658
2659 static inline string rgw_bl_str(ceph::buffer::list& raw)
2660 {
2661 size_t len = raw.length();
2662 string s(raw.c_str(), len);
2663 while (len && !s[len - 1]) {
2664 --len;
2665 s.resize(len);
2666 }
2667 return s;
2668 }
2669
2670 template <typename T>
2671 int decode_bl(bufferlist& bl, T& t)
2672 {
2673 auto iter = bl.cbegin();
2674 try {
2675 decode(t, iter);
2676 } catch (buffer::error& err) {
2677 return -EIO;
2678 }
2679 return 0;
2680 }
2681
2682 #endif