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