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