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