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