]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | ||
4 | #ifndef CEPH_RGW_REST_S3_H | |
5 | ||
6 | #define CEPH_RGW_REST_S3_H | |
7 | #define TIME_BUF_SIZE 128 | |
8 | ||
9 | #include <mutex> | |
10 | ||
31f18b77 FG |
11 | #include <boost/utility/string_view.hpp> |
12 | #include <boost/container/static_vector.hpp> | |
13 | ||
14 | #include "common/backport14.h" | |
15 | #include "common/sstring.hh" | |
7c673cae FG |
16 | #include "rgw_op.h" |
17 | #include "rgw_rest.h" | |
18 | #include "rgw_http_errors.h" | |
19 | #include "rgw_acl_s3.h" | |
20 | #include "rgw_policy_s3.h" | |
21 | #include "rgw_lc_s3.h" | |
22 | #include "rgw_keystone.h" | |
23 | #include "rgw_rest_conn.h" | |
24 | #include "rgw_ldap.h" | |
25 | #include "rgw_rest.h" | |
26 | ||
27 | #include "rgw_token.h" | |
28 | #include "include/assert.h" | |
29 | ||
30 | #include "rgw_auth.h" | |
31 | #include "rgw_auth_filters.h" | |
32 | ||
33 | #define RGW_AUTH_GRACE_MINS 15 | |
34 | ||
31f18b77 FG |
35 | struct rgw_http_error { |
36 | int http_ret; | |
37 | const char *s3_code; | |
38 | }; | |
39 | ||
40 | void rgw_get_errno_s3(struct rgw_http_error *e, int err_no); | |
7c673cae FG |
41 | |
42 | class RGWGetObj_ObjStore_S3 : public RGWGetObj_ObjStore | |
43 | { | |
44 | protected: | |
45 | // Serving a custom error page from an object is really a 200 response with | |
46 | // just the status line altered. | |
47 | int custom_http_ret = 0; | |
48 | std::map<std::string, std::string> crypt_http_responses; | |
49 | public: | |
50 | RGWGetObj_ObjStore_S3() {} | |
51 | ~RGWGetObj_ObjStore_S3() override {} | |
52 | ||
53 | int get_params() override; | |
54 | int send_response_data_error() override; | |
55 | int send_response_data(bufferlist& bl, off_t ofs, off_t len) override; | |
56 | void set_custom_http_response(int http_ret) { custom_http_ret = http_ret; } | |
57 | int get_decrypt_filter(std::unique_ptr<RGWGetDataCB>* filter, | |
58 | RGWGetDataCB* cb, | |
59 | bufferlist* manifest_bl) override; | |
60 | }; | |
61 | ||
224ce89b WB |
62 | class RGWGetObjTags_ObjStore_S3 : public RGWGetObjTags_ObjStore |
63 | { | |
64 | bufferlist tags_bl; | |
65 | public: | |
66 | RGWGetObjTags_ObjStore_S3() {} | |
67 | ~RGWGetObjTags_ObjStore_S3() {} | |
68 | ||
69 | void send_response_data(bufferlist &bl) override; | |
70 | }; | |
71 | ||
72 | class RGWPutObjTags_ObjStore_S3 : public RGWPutObjTags_ObjStore | |
73 | { | |
74 | public: | |
75 | RGWPutObjTags_ObjStore_S3() {} | |
76 | ~RGWPutObjTags_ObjStore_S3() {} | |
77 | ||
78 | int get_params() override; | |
79 | void send_response() override; | |
80 | }; | |
81 | ||
82 | class RGWDeleteObjTags_ObjStore_S3 : public RGWDeleteObjTags | |
83 | { | |
84 | public: | |
85 | ~RGWDeleteObjTags_ObjStore_S3() override {} | |
86 | void send_response() override; | |
87 | }; | |
88 | ||
7c673cae FG |
89 | class RGWListBuckets_ObjStore_S3 : public RGWListBuckets_ObjStore { |
90 | public: | |
91 | RGWListBuckets_ObjStore_S3() {} | |
92 | ~RGWListBuckets_ObjStore_S3() override {} | |
93 | ||
94 | int get_params() override { | |
95 | limit = -1; /* no limit */ | |
96 | return 0; | |
97 | } | |
98 | void send_response_begin(bool has_buckets) override; | |
99 | void send_response_data(RGWUserBuckets& buckets) override; | |
100 | void send_response_end() override; | |
101 | }; | |
102 | ||
103 | class RGWGetUsage_ObjStore_S3 : public RGWGetUsage_ObjStore { | |
104 | public: | |
105 | RGWGetUsage_ObjStore_S3() {} | |
106 | ~RGWGetUsage_ObjStore_S3() override {} | |
107 | ||
108 | int get_params() override ; | |
109 | void send_response() override; | |
110 | }; | |
111 | ||
112 | class RGWListBucket_ObjStore_S3 : public RGWListBucket_ObjStore { | |
113 | bool objs_container; | |
114 | public: | |
115 | RGWListBucket_ObjStore_S3() : objs_container(false) { | |
116 | default_max = 1000; | |
117 | } | |
118 | ~RGWListBucket_ObjStore_S3() override {} | |
119 | ||
120 | int get_params() override; | |
121 | void send_response() override; | |
122 | void send_versioned_response(); | |
123 | }; | |
124 | ||
125 | class RGWGetBucketLogging_ObjStore_S3 : public RGWGetBucketLogging { | |
126 | public: | |
127 | RGWGetBucketLogging_ObjStore_S3() {} | |
128 | ~RGWGetBucketLogging_ObjStore_S3() override {} | |
129 | ||
130 | void send_response() override; | |
131 | }; | |
132 | ||
133 | class RGWGetBucketLocation_ObjStore_S3 : public RGWGetBucketLocation { | |
134 | public: | |
135 | RGWGetBucketLocation_ObjStore_S3() {} | |
136 | ~RGWGetBucketLocation_ObjStore_S3() override {} | |
137 | ||
138 | void send_response() override; | |
139 | }; | |
140 | ||
141 | class RGWGetBucketVersioning_ObjStore_S3 : public RGWGetBucketVersioning { | |
142 | public: | |
143 | RGWGetBucketVersioning_ObjStore_S3() {} | |
144 | ~RGWGetBucketVersioning_ObjStore_S3() override {} | |
145 | ||
146 | void send_response() override; | |
147 | }; | |
148 | ||
149 | class RGWSetBucketVersioning_ObjStore_S3 : public RGWSetBucketVersioning { | |
150 | public: | |
151 | RGWSetBucketVersioning_ObjStore_S3() {} | |
152 | ~RGWSetBucketVersioning_ObjStore_S3() override {} | |
153 | ||
154 | int get_params() override; | |
155 | void send_response() override; | |
156 | }; | |
157 | ||
158 | class RGWGetBucketWebsite_ObjStore_S3 : public RGWGetBucketWebsite { | |
159 | public: | |
160 | RGWGetBucketWebsite_ObjStore_S3() {} | |
161 | ~RGWGetBucketWebsite_ObjStore_S3() override {} | |
162 | ||
163 | void send_response() override; | |
164 | }; | |
165 | ||
166 | class RGWSetBucketWebsite_ObjStore_S3 : public RGWSetBucketWebsite { | |
167 | public: | |
168 | RGWSetBucketWebsite_ObjStore_S3() {} | |
169 | ~RGWSetBucketWebsite_ObjStore_S3() override {} | |
170 | ||
171 | int get_params() override; | |
172 | void send_response() override; | |
173 | }; | |
174 | ||
175 | class RGWDeleteBucketWebsite_ObjStore_S3 : public RGWDeleteBucketWebsite { | |
176 | public: | |
177 | RGWDeleteBucketWebsite_ObjStore_S3() {} | |
178 | ~RGWDeleteBucketWebsite_ObjStore_S3() override {} | |
179 | ||
180 | void send_response() override; | |
181 | }; | |
182 | ||
183 | class RGWStatBucket_ObjStore_S3 : public RGWStatBucket_ObjStore { | |
184 | public: | |
185 | RGWStatBucket_ObjStore_S3() {} | |
186 | ~RGWStatBucket_ObjStore_S3() override {} | |
187 | ||
188 | void send_response() override; | |
189 | }; | |
190 | ||
191 | class RGWCreateBucket_ObjStore_S3 : public RGWCreateBucket_ObjStore { | |
192 | public: | |
193 | RGWCreateBucket_ObjStore_S3() {} | |
194 | ~RGWCreateBucket_ObjStore_S3() override {} | |
195 | ||
196 | int get_params() override; | |
197 | void send_response() override; | |
198 | }; | |
199 | ||
200 | class RGWDeleteBucket_ObjStore_S3 : public RGWDeleteBucket_ObjStore { | |
201 | public: | |
202 | RGWDeleteBucket_ObjStore_S3() {} | |
203 | ~RGWDeleteBucket_ObjStore_S3() override {} | |
204 | ||
205 | void send_response() override; | |
206 | }; | |
207 | ||
208 | class RGWPutObj_ObjStore_S3 : public RGWPutObj_ObjStore { | |
209 | private: | |
210 | std::map<std::string, std::string> crypt_http_responses; | |
211 | ||
212 | public: | |
213 | RGWPutObj_ObjStore_S3() {} | |
214 | ~RGWPutObj_ObjStore_S3() override {} | |
215 | ||
216 | int get_params() override; | |
217 | int get_data(bufferlist& bl) override; | |
218 | void send_response() override; | |
219 | ||
7c673cae FG |
220 | int get_encrypt_filter(std::unique_ptr<RGWPutObjDataProcessor>* filter, |
221 | RGWPutObjDataProcessor* cb) override; | |
222 | int get_decrypt_filter(std::unique_ptr<RGWGetDataCB>* filter, | |
223 | RGWGetDataCB* cb, | |
224 | map<string, bufferlist>& attrs, | |
225 | bufferlist* manifest_bl) override; | |
226 | }; | |
227 | ||
228 | class RGWPostObj_ObjStore_S3 : public RGWPostObj_ObjStore { | |
229 | parts_collection_t parts; | |
230 | std::string filename; | |
231 | std::string content_type; | |
232 | RGWPolicyEnv env; | |
233 | RGWPolicy post_policy; | |
234 | map<string, string> crypt_http_responses; | |
235 | ||
236 | const rgw::auth::StrategyRegistry* auth_registry_ptr = nullptr; | |
237 | ||
238 | int get_policy(); | |
224ce89b | 239 | int get_tags(); |
7c673cae FG |
240 | void rebuild_key(string& key); |
241 | ||
242 | std::string get_current_filename() const override; | |
243 | std::string get_current_content_type() const override; | |
244 | ||
245 | public: | |
246 | RGWPostObj_ObjStore_S3() {} | |
247 | ~RGWPostObj_ObjStore_S3() override {} | |
248 | ||
249 | int verify_requester(const rgw::auth::StrategyRegistry& auth_registry) { | |
250 | auth_registry_ptr = &auth_registry; | |
251 | return RGWPostObj_ObjStore::verify_requester(auth_registry); | |
252 | } | |
253 | ||
254 | int get_params() override; | |
255 | int complete_get_params(); | |
256 | ||
257 | void send_response() override; | |
258 | int get_data(ceph::bufferlist& bl, bool& again) override; | |
259 | int get_encrypt_filter(std::unique_ptr<RGWPutObjDataProcessor>* filter, | |
260 | RGWPutObjDataProcessor* cb) override; | |
261 | }; | |
262 | ||
263 | class RGWDeleteObj_ObjStore_S3 : public RGWDeleteObj_ObjStore { | |
264 | public: | |
265 | RGWDeleteObj_ObjStore_S3() {} | |
266 | ~RGWDeleteObj_ObjStore_S3() override {} | |
267 | ||
268 | int get_params() override; | |
269 | void send_response() override; | |
270 | }; | |
271 | ||
272 | class RGWCopyObj_ObjStore_S3 : public RGWCopyObj_ObjStore { | |
273 | bool sent_header; | |
274 | public: | |
275 | RGWCopyObj_ObjStore_S3() : sent_header(false) {} | |
276 | ~RGWCopyObj_ObjStore_S3() override {} | |
277 | ||
278 | int init_dest_policy() override; | |
279 | int get_params() override; | |
280 | void send_partial_response(off_t ofs) override; | |
281 | void send_response() override; | |
282 | }; | |
283 | ||
284 | class RGWGetACLs_ObjStore_S3 : public RGWGetACLs_ObjStore { | |
285 | public: | |
286 | RGWGetACLs_ObjStore_S3() {} | |
287 | ~RGWGetACLs_ObjStore_S3() override {} | |
288 | ||
289 | void send_response() override; | |
290 | }; | |
291 | ||
292 | class RGWPutACLs_ObjStore_S3 : public RGWPutACLs_ObjStore { | |
293 | public: | |
294 | RGWPutACLs_ObjStore_S3() {} | |
295 | ~RGWPutACLs_ObjStore_S3() override {} | |
296 | ||
297 | int get_policy_from_state(RGWRados *store, struct req_state *s, stringstream& ss) override; | |
298 | void send_response() override; | |
299 | int get_params() override; | |
300 | }; | |
301 | ||
302 | class RGWGetLC_ObjStore_S3 : public RGWGetLC_ObjStore { | |
303 | protected: | |
304 | RGWLifecycleConfiguration_S3 config; | |
305 | public: | |
306 | RGWGetLC_ObjStore_S3() {} | |
307 | ~RGWGetLC_ObjStore_S3() override {} | |
308 | void execute() override; | |
309 | ||
310 | void send_response() override; | |
311 | }; | |
312 | ||
313 | class RGWPutLC_ObjStore_S3 : public RGWPutLC_ObjStore { | |
314 | public: | |
315 | RGWPutLC_ObjStore_S3() {} | |
316 | ~RGWPutLC_ObjStore_S3() override {} | |
317 | ||
318 | void send_response() override; | |
319 | }; | |
320 | ||
321 | class RGWDeleteLC_ObjStore_S3 : public RGWDeleteLC_ObjStore { | |
322 | public: | |
323 | RGWDeleteLC_ObjStore_S3() {} | |
324 | ~RGWDeleteLC_ObjStore_S3() override {} | |
325 | ||
326 | void send_response() override; | |
327 | }; | |
328 | ||
329 | class RGWGetCORS_ObjStore_S3 : public RGWGetCORS_ObjStore { | |
330 | public: | |
331 | RGWGetCORS_ObjStore_S3() {} | |
332 | ~RGWGetCORS_ObjStore_S3() override {} | |
333 | ||
334 | void send_response() override; | |
335 | }; | |
336 | ||
337 | class RGWPutCORS_ObjStore_S3 : public RGWPutCORS_ObjStore { | |
338 | public: | |
339 | RGWPutCORS_ObjStore_S3() {} | |
340 | ~RGWPutCORS_ObjStore_S3() override {} | |
341 | ||
342 | int get_params() override; | |
343 | void send_response() override; | |
344 | }; | |
345 | ||
346 | class RGWDeleteCORS_ObjStore_S3 : public RGWDeleteCORS_ObjStore { | |
347 | public: | |
348 | RGWDeleteCORS_ObjStore_S3() {} | |
349 | ~RGWDeleteCORS_ObjStore_S3() override {} | |
350 | ||
351 | void send_response() override; | |
352 | }; | |
353 | ||
354 | class RGWOptionsCORS_ObjStore_S3 : public RGWOptionsCORS_ObjStore { | |
355 | public: | |
356 | RGWOptionsCORS_ObjStore_S3() {} | |
357 | ~RGWOptionsCORS_ObjStore_S3() override {} | |
358 | ||
359 | void send_response() override; | |
360 | }; | |
361 | ||
362 | class RGWGetRequestPayment_ObjStore_S3 : public RGWGetRequestPayment { | |
363 | public: | |
364 | RGWGetRequestPayment_ObjStore_S3() {} | |
365 | ~RGWGetRequestPayment_ObjStore_S3() override {} | |
366 | ||
367 | void send_response() override; | |
368 | }; | |
369 | ||
370 | class RGWSetRequestPayment_ObjStore_S3 : public RGWSetRequestPayment { | |
371 | public: | |
372 | RGWSetRequestPayment_ObjStore_S3() {} | |
373 | ~RGWSetRequestPayment_ObjStore_S3() override {} | |
374 | ||
375 | int get_params() override; | |
376 | void send_response() override; | |
377 | }; | |
378 | ||
379 | class RGWInitMultipart_ObjStore_S3 : public RGWInitMultipart_ObjStore { | |
380 | private: | |
381 | std::map<std::string, std::string> crypt_http_responses; | |
382 | public: | |
383 | RGWInitMultipart_ObjStore_S3() {} | |
384 | ~RGWInitMultipart_ObjStore_S3() override {} | |
385 | ||
386 | int get_params() override; | |
387 | void send_response() override; | |
388 | int prepare_encryption(map<string, bufferlist>& attrs) override; | |
389 | }; | |
390 | ||
391 | class RGWCompleteMultipart_ObjStore_S3 : public RGWCompleteMultipart_ObjStore { | |
392 | public: | |
393 | RGWCompleteMultipart_ObjStore_S3() {} | |
394 | ~RGWCompleteMultipart_ObjStore_S3() override {} | |
395 | ||
396 | int get_params() override; | |
397 | void send_response() override; | |
398 | }; | |
399 | ||
400 | class RGWAbortMultipart_ObjStore_S3 : public RGWAbortMultipart_ObjStore { | |
401 | public: | |
402 | RGWAbortMultipart_ObjStore_S3() {} | |
403 | ~RGWAbortMultipart_ObjStore_S3() override {} | |
404 | ||
405 | void send_response() override; | |
406 | }; | |
407 | ||
408 | class RGWListMultipart_ObjStore_S3 : public RGWListMultipart_ObjStore { | |
409 | public: | |
410 | RGWListMultipart_ObjStore_S3() {} | |
411 | ~RGWListMultipart_ObjStore_S3() override {} | |
412 | ||
413 | void send_response() override; | |
414 | }; | |
415 | ||
416 | class RGWListBucketMultiparts_ObjStore_S3 : public RGWListBucketMultiparts_ObjStore { | |
417 | public: | |
418 | RGWListBucketMultiparts_ObjStore_S3() { | |
419 | default_max = 1000; | |
420 | } | |
421 | ~RGWListBucketMultiparts_ObjStore_S3() override {} | |
422 | ||
423 | void send_response() override; | |
424 | }; | |
425 | ||
426 | class RGWDeleteMultiObj_ObjStore_S3 : public RGWDeleteMultiObj_ObjStore { | |
427 | public: | |
428 | RGWDeleteMultiObj_ObjStore_S3() {} | |
429 | ~RGWDeleteMultiObj_ObjStore_S3() override {} | |
430 | ||
431 | int get_params() override; | |
432 | void send_status() override; | |
433 | void begin_response() override; | |
434 | void send_partial_response(rgw_obj_key& key, bool delete_marker, | |
435 | const string& marker_version_id, int ret) override; | |
436 | void end_response() override; | |
437 | }; | |
438 | ||
439 | class RGWGetObjLayout_ObjStore_S3 : public RGWGetObjLayout { | |
440 | public: | |
441 | RGWGetObjLayout_ObjStore_S3() {} | |
442 | ~RGWGetObjLayout_ObjStore_S3() {} | |
443 | ||
444 | void send_response(); | |
445 | }; | |
446 | ||
31f18b77 FG |
447 | class RGWConfigBucketMetaSearch_ObjStore_S3 : public RGWConfigBucketMetaSearch { |
448 | public: | |
449 | RGWConfigBucketMetaSearch_ObjStore_S3() {} | |
450 | ~RGWConfigBucketMetaSearch_ObjStore_S3() {} | |
451 | ||
452 | int get_params() override; | |
453 | void send_response() override; | |
454 | }; | |
455 | ||
456 | class RGWGetBucketMetaSearch_ObjStore_S3 : public RGWGetBucketMetaSearch { | |
457 | public: | |
458 | RGWGetBucketMetaSearch_ObjStore_S3() {} | |
459 | ~RGWGetBucketMetaSearch_ObjStore_S3() {} | |
460 | ||
461 | void send_response() override; | |
462 | }; | |
463 | ||
464 | class RGWDelBucketMetaSearch_ObjStore_S3 : public RGWDelBucketMetaSearch { | |
465 | public: | |
466 | RGWDelBucketMetaSearch_ObjStore_S3() {} | |
467 | ~RGWDelBucketMetaSearch_ObjStore_S3() {} | |
468 | ||
469 | void send_response() override; | |
470 | }; | |
7c673cae FG |
471 | |
472 | class RGW_Auth_S3 { | |
7c673cae FG |
473 | public: |
474 | static int authorize(RGWRados *store, | |
475 | const rgw::auth::StrategyRegistry& auth_registry, | |
476 | struct req_state *s); | |
7c673cae FG |
477 | }; |
478 | ||
479 | class RGWHandler_Auth_S3 : public RGWHandler_REST { | |
480 | friend class RGWRESTMgr_S3; | |
481 | ||
482 | const rgw::auth::StrategyRegistry& auth_registry; | |
483 | ||
484 | public: | |
485 | RGWHandler_Auth_S3(const rgw::auth::StrategyRegistry& auth_registry) | |
486 | : RGWHandler_REST(), | |
487 | auth_registry(auth_registry) { | |
488 | } | |
489 | ~RGWHandler_Auth_S3() override = default; | |
490 | ||
491 | static int validate_bucket_name(const string& bucket); | |
492 | static int validate_object_name(const string& bucket); | |
493 | ||
494 | int init(RGWRados *store, | |
495 | struct req_state *s, | |
496 | rgw::io::BasicClient *cio) override; | |
497 | int authorize() override { | |
498 | return RGW_Auth_S3::authorize(store, auth_registry, s); | |
499 | } | |
500 | int postauth_init() override { return 0; } | |
501 | }; | |
502 | ||
503 | class RGWHandler_REST_S3 : public RGWHandler_REST { | |
504 | friend class RGWRESTMgr_S3; | |
505 | ||
506 | const rgw::auth::StrategyRegistry& auth_registry; | |
507 | public: | |
508 | static int init_from_header(struct req_state *s, int default_formatter, bool configurable_format); | |
509 | ||
510 | RGWHandler_REST_S3(const rgw::auth::StrategyRegistry& auth_registry) | |
511 | : RGWHandler_REST(), | |
512 | auth_registry(auth_registry) { | |
513 | } | |
514 | ~RGWHandler_REST_S3() override = default; | |
515 | ||
516 | int init(RGWRados *store, | |
517 | struct req_state *s, | |
518 | rgw::io::BasicClient *cio) override; | |
519 | int authorize() override { | |
520 | return RGW_Auth_S3::authorize(store, auth_registry, s); | |
521 | } | |
522 | int postauth_init() override; | |
523 | }; | |
524 | ||
525 | class RGWHandler_REST_Service_S3 : public RGWHandler_REST_S3 { | |
526 | protected: | |
527 | bool is_usage_op() { | |
528 | return s->info.args.exists("usage"); | |
529 | } | |
530 | RGWOp *op_get() override; | |
531 | RGWOp *op_head() override; | |
532 | RGWOp *op_post() override; | |
533 | public: | |
534 | using RGWHandler_REST_S3::RGWHandler_REST_S3; | |
535 | ~RGWHandler_REST_Service_S3() override = default; | |
536 | }; | |
537 | ||
538 | class RGWHandler_REST_Bucket_S3 : public RGWHandler_REST_S3 { | |
539 | protected: | |
540 | bool is_acl_op() { | |
541 | return s->info.args.exists("acl"); | |
542 | } | |
543 | bool is_cors_op() { | |
544 | return s->info.args.exists("cors"); | |
545 | } | |
546 | bool is_lc_op() { | |
547 | return s->info.args.exists("lifecycle"); | |
548 | } | |
549 | bool is_obj_update_op() override { | |
550 | return is_acl_op() || is_cors_op(); | |
551 | } | |
552 | bool is_request_payment_op() { | |
553 | return s->info.args.exists("requestPayment"); | |
554 | } | |
31f18b77 FG |
555 | bool is_policy_op() { |
556 | return s->info.args.exists("policy"); | |
557 | } | |
7c673cae FG |
558 | RGWOp *get_obj_op(bool get_data); |
559 | ||
560 | RGWOp *op_get() override; | |
561 | RGWOp *op_head() override; | |
562 | RGWOp *op_put() override; | |
563 | RGWOp *op_delete() override; | |
564 | RGWOp *op_post() override; | |
565 | RGWOp *op_options() override; | |
566 | public: | |
567 | using RGWHandler_REST_S3::RGWHandler_REST_S3; | |
568 | ~RGWHandler_REST_Bucket_S3() override = default; | |
569 | }; | |
570 | ||
571 | class RGWHandler_REST_Obj_S3 : public RGWHandler_REST_S3 { | |
572 | protected: | |
573 | bool is_acl_op() { | |
574 | return s->info.args.exists("acl"); | |
575 | } | |
576 | bool is_cors_op() { | |
577 | return s->info.args.exists("cors"); | |
578 | } | |
224ce89b WB |
579 | bool is_tagging_op() { |
580 | return s->info.args.exists("tagging"); | |
581 | } | |
7c673cae | 582 | bool is_obj_update_op() override { |
224ce89b | 583 | return is_acl_op() || is_tagging_op() ; |
7c673cae FG |
584 | } |
585 | RGWOp *get_obj_op(bool get_data); | |
586 | ||
587 | RGWOp *op_get() override; | |
588 | RGWOp *op_head() override; | |
589 | RGWOp *op_put() override; | |
590 | RGWOp *op_delete() override; | |
591 | RGWOp *op_post() override; | |
592 | RGWOp *op_options() override; | |
593 | public: | |
594 | using RGWHandler_REST_S3::RGWHandler_REST_S3; | |
595 | ~RGWHandler_REST_Obj_S3() override = default; | |
596 | }; | |
597 | ||
598 | class RGWRESTMgr_S3 : public RGWRESTMgr { | |
599 | private: | |
600 | bool enable_s3website; | |
601 | public: | |
602 | explicit RGWRESTMgr_S3(bool enable_s3website = false) | |
603 | : enable_s3website(enable_s3website) { | |
604 | } | |
605 | ||
606 | ~RGWRESTMgr_S3() override = default; | |
607 | ||
608 | RGWHandler_REST *get_handler(struct req_state* s, | |
609 | const rgw::auth::StrategyRegistry& auth_registry, | |
610 | const std::string& frontend_prefix) override; | |
611 | }; | |
612 | ||
613 | class RGWHandler_REST_Obj_S3Website; | |
614 | ||
615 | static inline bool looks_like_ip_address(const char *bucket) | |
616 | { | |
617 | int num_periods = 0; | |
618 | bool expect_period = false; | |
619 | for (const char *b = bucket; *b; ++b) { | |
620 | if (*b == '.') { | |
621 | if (!expect_period) | |
622 | return false; | |
623 | ++num_periods; | |
624 | if (num_periods > 3) | |
625 | return false; | |
626 | expect_period = false; | |
627 | } | |
628 | else if (isdigit(*b)) { | |
629 | expect_period = true; | |
630 | } | |
631 | else { | |
632 | return false; | |
633 | } | |
634 | } | |
635 | return (num_periods == 3); | |
636 | } | |
637 | ||
638 | static inline int valid_s3_object_name(const string& name) { | |
639 | if (name.size() > 1024) { | |
640 | return -ERR_INVALID_OBJECT_NAME; | |
641 | } | |
642 | if (check_utf8(name.c_str(), name.size())) { | |
643 | return -ERR_INVALID_OBJECT_NAME; | |
644 | } | |
645 | return 0; | |
646 | } | |
647 | ||
648 | static inline int valid_s3_bucket_name(const string& name, bool relaxed=false) | |
649 | { | |
650 | // This function enforces Amazon's spec for bucket names. | |
651 | // (The requirements, not the recommendations.) | |
652 | int len = name.size(); | |
653 | if (len < 3) { | |
654 | // Name too short | |
655 | return -ERR_INVALID_BUCKET_NAME; | |
656 | } else if (len > 255) { | |
657 | // Name too long | |
658 | return -ERR_INVALID_BUCKET_NAME; | |
659 | } | |
660 | ||
661 | // bucket names must start with a number, letter, or underscore | |
662 | if (!(isalpha(name[0]) || isdigit(name[0]))) { | |
663 | if (!relaxed) | |
664 | return -ERR_INVALID_BUCKET_NAME; | |
665 | else if (!(name[0] == '_' || name[0] == '.' || name[0] == '-')) | |
666 | return -ERR_INVALID_BUCKET_NAME; | |
667 | } | |
668 | ||
669 | for (const char *s = name.c_str(); *s; ++s) { | |
670 | char c = *s; | |
671 | if (isdigit(c) || (c == '.')) | |
672 | continue; | |
673 | if (isalpha(c)) | |
674 | continue; | |
675 | if ((c == '-') || (c == '_')) | |
676 | continue; | |
677 | // Invalid character | |
678 | return -ERR_INVALID_BUCKET_NAME; | |
679 | } | |
680 | ||
681 | if (looks_like_ip_address(name.c_str())) | |
682 | return -ERR_INVALID_BUCKET_NAME; | |
683 | ||
684 | return 0; | |
685 | } | |
686 | ||
687 | ||
688 | namespace rgw { | |
689 | namespace auth { | |
690 | namespace s3 { | |
691 | ||
31f18b77 | 692 | class AWSEngine : public rgw::auth::Engine { |
7c673cae | 693 | public: |
31f18b77 FG |
694 | class VersionAbstractor { |
695 | static constexpr size_t DIGEST_SIZE_V2 = CEPH_CRYPTO_HMACSHA1_DIGESTSIZE; | |
696 | static constexpr size_t DIGEST_SIZE_V4 = CEPH_CRYPTO_HMACSHA256_DIGESTSIZE; | |
697 | ||
698 | /* Knowing the signature max size allows us to employ the sstring, and thus | |
699 | * avoid dynamic allocations. The multiplier comes from representing digest | |
700 | * in the base64-encoded form. */ | |
701 | static constexpr size_t SIGNATURE_MAX_SIZE = \ | |
702 | ceph::max(DIGEST_SIZE_V2, DIGEST_SIZE_V4) * 2 + sizeof('\0'); | |
703 | ||
7c673cae | 704 | public: |
31f18b77 | 705 | virtual ~VersionAbstractor() {}; |
7c673cae | 706 | |
31f18b77 FG |
707 | using access_key_id_t = boost::string_view; |
708 | using client_signature_t = boost::string_view; | |
709 | using server_signature_t = basic_sstring<char, uint16_t, SIGNATURE_MAX_SIZE>; | |
7c673cae FG |
710 | using string_to_sign_t = std::string; |
711 | ||
31f18b77 FG |
712 | /* Transformation for crafting the AWS signature at server side which is |
713 | * used later to compare with the user-provided one. The methodology for | |
714 | * doing that depends on AWS auth version. */ | |
715 | using signature_factory_t = \ | |
716 | std::function<server_signature_t(CephContext* cct, | |
717 | const std::string& secret_key, | |
718 | const string_to_sign_t& string_to_sign)>; | |
719 | ||
720 | /* Return an instance of Completer for verifying the payload's fingerprint | |
721 | * if necessary. Otherwise caller gets nullptr. Caller may provide secret | |
722 | * key */ | |
723 | using completer_factory_t = \ | |
724 | std::function<rgw::auth::Completer::cmplptr_t( | |
725 | const boost::optional<std::string>& secret_key)>; | |
726 | ||
224ce89b WB |
727 | struct auth_data_t { |
728 | access_key_id_t access_key_id; | |
729 | client_signature_t client_signature; | |
730 | string_to_sign_t string_to_sign; | |
731 | signature_factory_t signature_factory; | |
732 | completer_factory_t completer_factory; | |
733 | }; | |
734 | ||
735 | virtual auth_data_t get_auth_data(const req_state* s) const = 0; | |
7c673cae FG |
736 | }; |
737 | ||
738 | protected: | |
739 | CephContext* cct; | |
31f18b77 | 740 | const VersionAbstractor& ver_abstractor; |
7c673cae | 741 | |
31f18b77 | 742 | AWSEngine(CephContext* const cct, const VersionAbstractor& ver_abstractor) |
7c673cae | 743 | : cct(cct), |
31f18b77 | 744 | ver_abstractor(ver_abstractor) { |
7c673cae FG |
745 | } |
746 | ||
747 | using result_t = rgw::auth::Engine::result_t; | |
31f18b77 FG |
748 | using string_to_sign_t = VersionAbstractor::string_to_sign_t; |
749 | using signature_factory_t = VersionAbstractor::signature_factory_t; | |
750 | using completer_factory_t = VersionAbstractor::completer_factory_t; | |
751 | ||
752 | /* TODO(rzarzynski): clean up. We've too many input parameter hee. Also | |
753 | * the signature get_auth_data() of VersionAbstractor is too complicated. | |
754 | * Replace these thing with a simple, dedicated structure. */ | |
755 | virtual result_t authenticate(const boost::string_view& access_key_id, | |
756 | const boost::string_view& signature, | |
757 | const string_to_sign_t& string_to_sign, | |
758 | const signature_factory_t& signature_factory, | |
759 | const completer_factory_t& completer_factory, | |
7c673cae FG |
760 | const req_state* s) const = 0; |
761 | ||
762 | public: | |
31f18b77 | 763 | result_t authenticate(const req_state* const s) const final; |
7c673cae FG |
764 | }; |
765 | ||
31f18b77 FG |
766 | |
767 | class AWSGeneralAbstractor : public AWSEngine::VersionAbstractor { | |
7c673cae FG |
768 | CephContext* const cct; |
769 | ||
770 | bool is_time_skew_ok(const utime_t& header_time, | |
771 | const bool qsr) const; | |
772 | ||
31f18b77 FG |
773 | virtual boost::optional<std::string> |
774 | get_v4_canonical_headers(const req_info& info, | |
775 | const boost::string_view& signedheaders, | |
776 | const bool using_qs) const; | |
777 | ||
224ce89b WB |
778 | auth_data_t get_auth_data_v2(const req_state* s) const; |
779 | auth_data_t get_auth_data_v4(const req_state* s, bool using_qs) const; | |
31f18b77 | 780 | |
7c673cae | 781 | public: |
31f18b77 | 782 | AWSGeneralAbstractor(CephContext* const cct) |
7c673cae FG |
783 | : cct(cct) { |
784 | } | |
785 | ||
224ce89b | 786 | auth_data_t get_auth_data(const req_state* s) const override; |
7c673cae FG |
787 | }; |
788 | ||
31f18b77 FG |
789 | class AWSGeneralBoto2Abstractor : public AWSGeneralAbstractor { |
790 | boost::optional<std::string> | |
791 | get_v4_canonical_headers(const req_info& info, | |
792 | const boost::string_view& signedheaders, | |
793 | const bool using_qs) const override; | |
794 | ||
795 | public: | |
796 | using AWSGeneralAbstractor::AWSGeneralAbstractor; | |
797 | }; | |
7c673cae | 798 | |
31f18b77 | 799 | class AWSBrowserUploadAbstractor : public AWSEngine::VersionAbstractor { |
7c673cae FG |
800 | static std::string to_string(ceph::bufferlist bl) { |
801 | return std::string(bl.c_str(), | |
802 | static_cast<std::string::size_type>(bl.length())); | |
803 | } | |
804 | ||
31f18b77 FG |
805 | auth_data_t get_auth_data_v2(const req_state* s) const; |
806 | auth_data_t get_auth_data_v4(const req_state* s) const; | |
807 | ||
7c673cae | 808 | public: |
31f18b77 | 809 | AWSBrowserUploadAbstractor(CephContext*) { |
7c673cae FG |
810 | } |
811 | ||
224ce89b | 812 | auth_data_t get_auth_data(const req_state* s) const override; |
7c673cae FG |
813 | }; |
814 | ||
815 | ||
31f18b77 | 816 | class LDAPEngine : public AWSEngine { |
7c673cae FG |
817 | static rgw::LDAPHelper* ldh; |
818 | static std::mutex mtx; | |
819 | ||
820 | static void init(CephContext* const cct); | |
821 | ||
822 | using acl_strategy_t = rgw::auth::RemoteApplier::acl_strategy_t; | |
823 | using auth_info_t = rgw::auth::RemoteApplier::AuthInfo; | |
824 | using result_t = rgw::auth::Engine::result_t; | |
825 | ||
826 | protected: | |
827 | RGWRados* const store; | |
828 | const rgw::auth::RemoteApplier::Factory* const apl_factory; | |
829 | ||
830 | acl_strategy_t get_acl_strategy() const; | |
831 | auth_info_t get_creds_info(const rgw::RGWToken& token) const noexcept; | |
832 | ||
31f18b77 FG |
833 | result_t authenticate(const boost::string_view& access_key_id, |
834 | const boost::string_view& signature, | |
835 | const string_to_sign_t& string_to_sign, | |
836 | const signature_factory_t&, | |
837 | const completer_factory_t& completer_factory, | |
7c673cae FG |
838 | const req_state* s) const override; |
839 | public: | |
840 | LDAPEngine(CephContext* const cct, | |
841 | RGWRados* const store, | |
31f18b77 | 842 | const VersionAbstractor& ver_abstractor, |
7c673cae | 843 | const rgw::auth::RemoteApplier::Factory* const apl_factory) |
31f18b77 | 844 | : AWSEngine(cct, ver_abstractor), |
7c673cae FG |
845 | store(store), |
846 | apl_factory(apl_factory) { | |
847 | init(cct); | |
848 | } | |
849 | ||
31f18b77 | 850 | using AWSEngine::authenticate; |
7c673cae FG |
851 | |
852 | const char* get_name() const noexcept override { | |
853 | return "rgw::auth::s3::LDAPEngine"; | |
854 | } | |
855 | }; | |
856 | ||
857 | ||
31f18b77 | 858 | class LocalEngine : public AWSEngine { |
7c673cae FG |
859 | RGWRados* const store; |
860 | const rgw::auth::LocalApplier::Factory* const apl_factory; | |
861 | ||
31f18b77 FG |
862 | result_t authenticate(const boost::string_view& access_key_id, |
863 | const boost::string_view& signature, | |
864 | const string_to_sign_t& string_to_sign, | |
865 | const signature_factory_t& signature_factory, | |
866 | const completer_factory_t& completer_factory, | |
7c673cae FG |
867 | const req_state* s) const override; |
868 | public: | |
31f18b77 FG |
869 | LocalEngine(CephContext* const cct, |
870 | RGWRados* const store, | |
871 | const VersionAbstractor& ver_abstractor, | |
872 | const rgw::auth::LocalApplier::Factory* const apl_factory) | |
873 | : AWSEngine(cct, ver_abstractor), | |
7c673cae FG |
874 | store(store), |
875 | apl_factory(apl_factory) { | |
876 | } | |
877 | ||
31f18b77 | 878 | using AWSEngine::authenticate; |
7c673cae FG |
879 | |
880 | const char* get_name() const noexcept override { | |
31f18b77 | 881 | return "rgw::auth::s3::LocalEngine"; |
7c673cae FG |
882 | } |
883 | }; | |
884 | ||
885 | ||
d2e6a577 FG |
886 | class S3AnonymousEngine : public rgw::auth::AnonymousEngine { |
887 | bool is_applicable(const req_state* s) const noexcept override; | |
888 | ||
889 | public: | |
890 | /* Let's reuse the parent class' constructor. */ | |
891 | using rgw::auth::AnonymousEngine::AnonymousEngine; | |
892 | ||
893 | const char* get_name() const noexcept override { | |
894 | return "rgw::auth::s3::S3AnonymousEngine"; | |
895 | } | |
896 | }; | |
897 | ||
898 | ||
7c673cae FG |
899 | class S3AuthFactory : public rgw::auth::RemoteApplier::Factory, |
900 | public rgw::auth::LocalApplier::Factory { | |
901 | typedef rgw::auth::IdentityApplier::aplptr_t aplptr_t; | |
902 | RGWRados* const store; | |
903 | ||
904 | public: | |
905 | S3AuthFactory(RGWRados* const store) | |
906 | : store(store) { | |
907 | } | |
908 | ||
909 | aplptr_t create_apl_remote(CephContext* const cct, | |
910 | const req_state* const s, | |
911 | rgw::auth::RemoteApplier::acl_strategy_t&& acl_alg, | |
912 | const rgw::auth::RemoteApplier::AuthInfo info | |
913 | ) const override { | |
914 | return aplptr_t( | |
915 | new rgw::auth::RemoteApplier(cct, store, std::move(acl_alg), info, | |
224ce89b | 916 | cct->_conf->rgw_keystone_implicit_tenants)); |
7c673cae FG |
917 | } |
918 | ||
919 | aplptr_t create_apl_local(CephContext* const cct, | |
920 | const req_state* const s, | |
921 | const RGWUserInfo& user_info, | |
922 | const std::string& subuser) const override { | |
923 | return aplptr_t( | |
924 | new rgw::auth::LocalApplier(cct, user_info, subuser)); | |
925 | } | |
926 | }; | |
927 | ||
928 | ||
929 | } /* namespace s3 */ | |
930 | } /* namespace auth */ | |
931 | } /* namespace rgw */ | |
932 | ||
933 | ||
934 | #endif /* CEPH_RGW_REST_S3_H */ |