]> git.proxmox.com Git - ceph.git/blame - ceph/src/test/test_cors.cc
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / test / test_cors.cc
CommitLineData
7c673cae
FG
1#include <iostream>
2#include <stdio.h>
3#include <stdlib.h>
4#include <string.h>
5extern "C"{
6#include <curl/curl.h>
7}
8#include "common/ceph_crypto.h"
9#include <map>
10#include <list>
11#define S3_BUCKET_NAME "s3testgw.fcgi"
12#define SWIFT_BUCKET_NAME "swift3testgw.fcgi"
13#define BUCKET_URL \
14 ((g_test->get_key_type() == KEY_TYPE_S3)?(string("/" S3_BUCKET_NAME)):(string("/swift/v1/" SWIFT_BUCKET_NAME)))
15#define GTEST
16#ifdef GTEST
17#include <gtest/gtest.h>
18#else
19#define TEST(x, y) void y()
20#define ASSERT_EQ(v, s) if(v != s)cout << "Error at " << __LINE__ << "(" << #v << "!= " << #s << "\n"; \
21 else cout << "(" << #v << "==" << #s << ") PASSED\n";
22#define EXPECT_EQ(v, s) ASSERT_EQ(v, s)
23#define ASSERT_TRUE(c) if(c)cout << "Error at " << __LINE__ << "(" << #c << ")" << "\n"; \
24 else cout << "(" << #c << ") PASSED\n";
25#define EXPECT_TRUE(c) ASSERT_TRUE(c)
26#endif
27#include "common/code_environment.h"
28#include "common/ceph_argparse.h"
29#include "common/Finisher.h"
30#include "global/global_init.h"
31#include "rgw/rgw_cors.h"
32#include "rgw/rgw_cors_s3.h"
33
34using namespace std;
35
36#define CURL_VERBOSE 0
37#define HTTP_RESPONSE_STR "RespCode"
38#define CEPH_CRYPTO_HMACSHA1_DIGESTSIZE 20
39
40extern "C" int ceph_armor(char *dst, const char *dst_end,
41 const char *src, const char *end);
42enum key_type {
43 KEY_TYPE_UNDEFINED = 0,
44 KEY_TYPE_SWIFT,
45 KEY_TYPE_S3
46};
47
48static void print_usage(char *exec){
49 cout << "Usage: " << exec << " <Options>\n";
50 cout << "Options:\n"
51 "-g <gw-ip> - The ip address of the gateway\n"
52 "-p <gw-port> - The port number of the gateway\n"
53 "-k <SWIFT|S3> - The key type, either SWIFT or S3\n"
54 "-s3 <AWSAccessKeyId:SecretAccessKeyID> - Only, if the key type is S3, gives S3 credentials\n"
55 "-swift <Auth-Token> - Only if the key type is SWIFT, and gives the SWIFT credentials\n";
56}
57class test_cors_helper {
58 private:
59 string host;
60 string port;
61 string creds;
62 CURL *curl_inst;
63 map<string, string> response;
64 list<string> extra_hdrs;
65 string *resp_data;
66 unsigned resp_code;
67 key_type kt;
68 public:
69 test_cors_helper() : curl_inst(NULL), resp_data(NULL), resp_code(0), kt(KEY_TYPE_UNDEFINED){
70 curl_global_init(CURL_GLOBAL_ALL);
71 }
72 ~test_cors_helper(){
73 curl_global_cleanup();
74 }
75 int send_request(string method, string uri,
76 size_t (*function)(void *,size_t,size_t,void *) = 0,
77 void *ud = 0, size_t length = 0);
78 int extract_input(unsigned argc, char *argv[]);
79 string& get_response(string hdr){
80 return response[hdr];
81 }
82 void set_extra_header(string hdr){
83 extra_hdrs.push_back(hdr);
84 }
85 void set_response(char *val);
86 void set_response_data(char *data, size_t len){
87 if(resp_data) delete resp_data;
88 resp_data = new string(data, len);
89 /*cout << resp_data->c_str() << "\n";*/
90 }
91 const string *get_response_data(){return resp_data;}
92 unsigned get_resp_code(){return resp_code;}
93 key_type get_key_type(){return kt;}
94};
95
96int test_cors_helper::extract_input(unsigned argc, char *argv[]){
97#define ERR_CHECK_NEXT_PARAM(o) \
98 if((loop + 1) >= argc)return -1; \
99 else o = argv[loop+1];
100
101 for(unsigned loop = 1;loop < argc; loop += 2){
102 if(strcmp(argv[loop], "-g") == 0){
103 ERR_CHECK_NEXT_PARAM(host);
104 }else if(strcmp(argv[loop], "-k") == 0){
105 string type;
106 ERR_CHECK_NEXT_PARAM(type);
107 if(type.compare("S3") == 0)kt = KEY_TYPE_S3;
108 else if(type.compare("SWIFT") == 0)kt = KEY_TYPE_SWIFT;
109 }else if(strcmp(argv[loop],"-s3") == 0){
110 ERR_CHECK_NEXT_PARAM(creds);
111 }else if(strcmp(argv[loop],"-swift") == 0){
112 ERR_CHECK_NEXT_PARAM(creds);
113 }else if(strcmp(argv[loop],"-p") == 0){
114 ERR_CHECK_NEXT_PARAM(port);
115 }else return -1;
116 }
11fdf7f2 117 if(host.empty() || creds.empty())
7c673cae
FG
118 return -1;
119 return 0;
120}
121
122void test_cors_helper::set_response(char *r){
123 string sr(r), h, v;
124 size_t off = sr.find(": ");
125 if(off != string::npos){
126 h.assign(sr, 0, off);
127 v.assign(sr, off + 2, sr.find("\r\n") - (off+2));
128 }else{
129 /*Could be the status code*/
130 if(sr.find("HTTP/") != string::npos){
131 h.assign(HTTP_RESPONSE_STR);
132 off = sr.find(" ");
133 v.assign(sr, off + 1, sr.find("\r\n") - (off + 1));
134 resp_code = atoi((v.substr(0, 3)).c_str());
135 }
136 }
137 response[h] = v;
138}
139
140size_t write_header(void *ptr, size_t size, size_t nmemb, void *ud){
141 test_cors_helper *h = static_cast<test_cors_helper *>(ud);
142 h->set_response((char *)ptr);
143 return size*nmemb;
144}
145
146size_t write_data(void *ptr, size_t size, size_t nmemb, void *ud){
147 test_cors_helper *h = static_cast<test_cors_helper *>(ud);
148 h->set_response_data((char *)ptr, size*nmemb);
149 return size*nmemb;
150}
151static inline void buf_to_hex(const unsigned char *buf, int len, char *str)
152{
153 int i;
154 str[0] = '\0';
155 for (i = 0; i < len; i++) {
156 sprintf(&str[i*2], "%02x", (int)buf[i]);
157 }
158}
159
160static void calc_hmac_sha1(const char *key, int key_len,
161 const char *msg, int msg_len, char *dest)
162/* destination should be CEPH_CRYPTO_HMACSHA1_DIGESTSIZE bytes long */
163{
164 ceph::crypto::HMACSHA1 hmac((const unsigned char *)key, key_len);
165 hmac.Update((const unsigned char *)msg, msg_len);
166 hmac.Final((unsigned char *)dest);
167
168 char hex_str[(CEPH_CRYPTO_HMACSHA1_DIGESTSIZE * 2) + 1];
169 buf_to_hex((unsigned char *)dest, CEPH_CRYPTO_HMACSHA1_DIGESTSIZE, hex_str);
170}
171
11fdf7f2 172static int get_s3_auth(const string &method, string creds, const string &date, const string &res, string& out){
7c673cae
FG
173 string aid, secret, auth_hdr;
174 size_t off = creds.find(":");
175 out = "";
176 if(off != string::npos){
177 aid.assign(creds, 0, off);
178 secret.assign(creds, off + 1, string::npos);
179
180 /*sprintf(auth_hdr, "%s\n\n\n%s\n%s", req_type, date, res);*/
181 char hmac_sha1[CEPH_CRYPTO_HMACSHA1_DIGESTSIZE];
182 char b64[65]; /* 64 is really enough */
183 auth_hdr.append(method + string("\n\n\n") + date + string("\n") + res);
184 calc_hmac_sha1(secret.c_str(), secret.length(), auth_hdr.c_str(), auth_hdr.length(), hmac_sha1);
185 int ret = ceph_armor(b64, b64 + 64, hmac_sha1,
186 hmac_sha1 + CEPH_CRYPTO_HMACSHA1_DIGESTSIZE);
187 if (ret < 0) {
188 cout << "ceph_armor failed\n";
189 return -1;
190 }
191 b64[ret] = 0;
192 out.append(aid + string(":") + b64);
193 }else return -1;
194 return 0;
195}
196
197void get_date(string& d){
198 struct timeval tv;
199 char date[64];
200 struct tm tm;
201 char *days[] = {(char *)"Sun", (char *)"Mon", (char *)"Tue",
202 (char *)"Wed", (char *)"Thu", (char *)"Fri",
203 (char *)"Sat"};
204 char *months[] = {(char *)"Jan", (char *)"Feb", (char *)"Mar",
205 (char *)"Apr", (char *)"May", (char *)"Jun",
206 (char *)"Jul",(char *) "Aug", (char *)"Sep",
207 (char *)"Oct", (char *)"Nov", (char *)"Dec"};
208 gettimeofday(&tv, NULL);
209 gmtime_r(&tv.tv_sec, &tm);
210 sprintf(date, "%s, %d %s %d %d:%d:%d GMT",
211 days[tm.tm_wday],
212 tm.tm_mday, months[tm.tm_mon],
213 tm.tm_year + 1900,
214 tm.tm_hour, tm.tm_min, 0 /*tm.tm_sec*/);
215 d = date;
216}
217
218int test_cors_helper::send_request(string method, string res,
219 size_t (*read_function)( void *,size_t,size_t,void *),
220 void *ud,
221 size_t length){
222 string url;
223 string auth, date;
224 url.append(string("http://") + host);
225 if(port.length() > 0)url.append(string(":") + port);
226 url.append(res);
227 curl_inst = curl_easy_init();
228 if(curl_inst){
229 curl_easy_setopt(curl_inst, CURLOPT_URL, url.c_str());
230 curl_easy_setopt(curl_inst, CURLOPT_CUSTOMREQUEST, method.c_str());
231 curl_easy_setopt(curl_inst, CURLOPT_VERBOSE, CURL_VERBOSE);
232 curl_easy_setopt(curl_inst, CURLOPT_HEADERFUNCTION, write_header);
233 curl_easy_setopt(curl_inst, CURLOPT_WRITEHEADER, (void *)this);
234 curl_easy_setopt(curl_inst, CURLOPT_WRITEFUNCTION, write_data);
235 curl_easy_setopt(curl_inst, CURLOPT_WRITEDATA, (void *)this);
236 if(read_function){
237 curl_easy_setopt(curl_inst, CURLOPT_READFUNCTION, read_function);
238 curl_easy_setopt(curl_inst, CURLOPT_READDATA, (void *)ud);
239 curl_easy_setopt(curl_inst, CURLOPT_UPLOAD, 1L);
240 curl_easy_setopt(curl_inst, CURLOPT_INFILESIZE_LARGE, (curl_off_t)length);
241 }
242
243 get_date(date);
244 string http_date;
245 http_date.append(string("Date: ") + date);
246 if(kt == KEY_TYPE_S3){
247 string s3auth;
248 if(get_s3_auth(method, creds, date, res, s3auth) < 0)return -1;
249 auth.append(string("Authorization: AWS ") + s3auth);
250 } else if(kt == KEY_TYPE_SWIFT){
251 auth.append(string("X-Auth-Token: ") + creds);
252 } else {
253 cout << "Unknown state (" << kt << ")\n";
254 return -1;
255 }
256
257 struct curl_slist *slist = NULL;
258 slist = curl_slist_append(slist, auth.c_str());
259 slist = curl_slist_append(slist, http_date.c_str());
260 for(list<string>::iterator it = extra_hdrs.begin();
261 it != extra_hdrs.end(); ++it){
262 slist = curl_slist_append(slist, (*it).c_str());
263 }
264 if(read_function)
265 curl_slist_append(slist, "Expect:");
266 curl_easy_setopt(curl_inst, CURLOPT_HTTPHEADER, slist);
267
268 response.erase(response.begin(), response.end());
269 extra_hdrs.erase(extra_hdrs.begin(), extra_hdrs.end());
270 CURLcode res = curl_easy_perform(curl_inst);
271 if(res != CURLE_OK){
272 cout << "Curl perform failed for " << url << ", res: " <<
273 curl_easy_strerror(res) << "\n";
274 return -1;
275 }
276 curl_slist_free_all(slist);
277 }
278 curl_easy_cleanup(curl_inst);
279 return 0;
280}
281
282test_cors_helper *g_test;
283Finisher *finisher;
284
285static int create_bucket(void){
286 if(g_test->get_key_type() == KEY_TYPE_S3){
287 g_test->send_request(string("PUT"), string("/" S3_BUCKET_NAME));
288 if(g_test->get_resp_code() != 200U){
289 cout << "Error creating bucket, http code " << g_test->get_resp_code();
290 return -1;
291 }
292 }else if(g_test->get_key_type() == KEY_TYPE_SWIFT){
293 g_test->send_request(string("PUT"), string("/swift/v1/" SWIFT_BUCKET_NAME));
294 if(g_test->get_resp_code() != 201U){
295 cout << "Error creating bucket, http code " << g_test->get_resp_code();
296 return -1;
297 }
298 }else return -1;
299 return 0;
300}
301
302static int delete_bucket(void){
303 if(g_test->get_key_type() == KEY_TYPE_S3){
304 g_test->send_request(string("DELETE"), string("/" S3_BUCKET_NAME));
305 if(g_test->get_resp_code() != 204U){
306 cout << "Error deleting bucket, http code " << g_test->get_resp_code();
307 return -1;
308 }
309 }else if(g_test->get_key_type() == KEY_TYPE_SWIFT){
310 g_test->send_request(string("DELETE"), string("/swift/v1/" SWIFT_BUCKET_NAME));
311 if(g_test->get_resp_code() != 204U){
312 cout << "Error deleting bucket, http code " << g_test->get_resp_code();
313 return -1;
314 }
315 }else return -1;
316 return 0;
317}
318
319RGWCORSRule *xml_to_cors_rule(string s){
320 RGWCORSConfiguration_S3 *cors_config;
321 RGWCORSXMLParser_S3 parser(g_ceph_context);
322 const string *data = g_test->get_response_data();
323 if (!parser.init()) {
324 return NULL;
325 }
326 if (!parser.parse(data->c_str(), data->length(), 1)) {
327 return NULL;
328 }
329 cors_config = (RGWCORSConfiguration_S3 *)parser.find_first("CORSConfiguration");
330 if (!cors_config) {
331 return NULL;
332 }
333 return cors_config->host_name_rule(s.c_str());
334}
335
336size_t cors_read_xml(void *ptr, size_t s, size_t n, void *ud){
337 stringstream *ss = (stringstream *)ud;
338 size_t len = ss->str().length();
339 if(s*n < len){
340 cout << "Cannot copy xml data, as len is not enough\n";
341 return 0;
342 }
343 memcpy(ptr, (void *)ss->str().c_str(), len);
344 return len;
345}
346
347void send_cors(set<string> o, set<string> h,
348 list<string> e, uint8_t flags,
349 unsigned max_age){
350 if(g_test->get_key_type() == KEY_TYPE_S3){
351 RGWCORSRule rule(o, h, e, flags, max_age);
352 RGWCORSConfiguration config;
353 config.stack_rule(rule);
354 stringstream ss;
355 RGWCORSConfiguration_S3 *s3;
356 s3 = static_cast<RGWCORSConfiguration_S3 *>(&config);
357 s3->to_xml(ss);
358
359 g_test->send_request(string("PUT"), string("/" S3_BUCKET_NAME "?cors"), cors_read_xml,
360 (void *)&ss, ss.str().length());
361 }else if(g_test->get_key_type() == KEY_TYPE_SWIFT){
362 set<string>::iterator it;
363 string a_o;
364 for(it = o.begin(); it != o.end(); ++it){
365 if(a_o.length() > 0)a_o.append(" ");
366 a_o.append(*it);
367 }
368 g_test->set_extra_header(string("X-Container-Meta-Access-Control-Allow-Origin: ") + a_o);
369
370 if(!h.empty()){
371 string a_h;
372 for(it = h.begin(); it != h.end(); ++it){
373 if(a_h.length() > 0)a_h.append(" ");
374 a_h.append(*it);
375 }
376 g_test->set_extra_header(string("X-Container-Meta-Access-Control-Allow-Headers: ") + a_h);
377 }
378 if(!e.empty()){
379 string e_h;
380 for(list<string>::iterator lit = e.begin(); lit != e.end(); ++lit){
381 if(e_h.length() > 0)e_h.append(" ");
382 e_h.append(*lit);
383 }
384 g_test->set_extra_header(string("X-Container-Meta-Access-Control-Expose-Headers: ") + e_h);
385 }
386 if(max_age != CORS_MAX_AGE_INVALID){
387 char age[32];
388 sprintf(age, "%u", max_age);
389 g_test->set_extra_header(string("X-Container-Meta-Access-Control-Max-Age: ") + string(age));
390 }
391 //const char *data = "1";
392 stringstream ss;
393 ss << "1";
394 g_test->send_request(string("POST"), string("/swift/v1/" SWIFT_BUCKET_NAME), cors_read_xml,
395 (void *)&ss, 1);
396 }
397}
398
399TEST(TestCORS, getcors_firsttime){
400 if(g_test->get_key_type() == KEY_TYPE_SWIFT)return;
401 ASSERT_EQ(0, create_bucket());
402 g_test->send_request(string("GET"), string("/" S3_BUCKET_NAME "?cors"));
403 EXPECT_EQ(404U, g_test->get_resp_code());
404 ASSERT_EQ(0, delete_bucket());
405}
406
407TEST(TestCORS, putcors_firsttime){
408 ASSERT_EQ(0, create_bucket());
409 set<string> origins, h;
410 list<string> e;
411
412 origins.insert(origins.end(), "example.com");
413 uint8_t flags = RGW_CORS_GET | RGW_CORS_PUT;
414
415 send_cors(origins, h, e, flags, CORS_MAX_AGE_INVALID);
416 EXPECT_EQ(((g_test->get_key_type() == KEY_TYPE_SWIFT)?202U:200U), g_test->get_resp_code());
417
418 /*Now get the CORS and check if its fine*/
419 if(g_test->get_key_type() == KEY_TYPE_S3){
420 g_test->send_request(string("GET"), string("/" S3_BUCKET_NAME "?cors"));
421 EXPECT_EQ(200U, g_test->get_resp_code());
422
423 RGWCORSRule *r = xml_to_cors_rule(string("example.com"));
424 EXPECT_TRUE(r != NULL);
425 if(!r)return;
426
427 EXPECT_TRUE((r->get_allowed_methods() & (RGW_CORS_GET | RGW_CORS_PUT))
428 == (RGW_CORS_GET | RGW_CORS_PUT));
429 }
430 ASSERT_EQ(0, delete_bucket());
431}
432
433TEST(TestCORS, putcors_invalid_hostname){
434 ASSERT_EQ(0, create_bucket());
435 set<string> origins, h;
436 list<string> e;
437
438 origins.insert(origins.end(), "*.example.*");
439 uint8_t flags = RGW_CORS_GET | RGW_CORS_PUT;
440 send_cors(origins, h, e, flags, CORS_MAX_AGE_INVALID);
441 EXPECT_EQ((400U), g_test->get_resp_code());
442 origins.erase(origins.begin(), origins.end());
443
444 if((g_test->get_key_type() != KEY_TYPE_SWIFT)){
445 origins.insert(origins.end(), "");
446 send_cors(origins, h, e, flags, CORS_MAX_AGE_INVALID);
447 EXPECT_EQ((400U), g_test->get_resp_code());
448 origins.erase(origins.begin(), origins.end());
449 }
450 ASSERT_EQ(0, delete_bucket());
451}
452
453TEST(TestCORS, putcors_invalid_headers){
454 ASSERT_EQ(0, create_bucket());
455 set<string> origins, h;
456 list<string> e;
457
458 origins.insert(origins.end(), "www.example.com");
459 h.insert(h.end(), "*-Header-*");
460 uint8_t flags = RGW_CORS_GET | RGW_CORS_PUT;
461 send_cors(origins, h, e, flags, CORS_MAX_AGE_INVALID);
462 EXPECT_EQ((400U), g_test->get_resp_code());
463 h.erase(h.begin(), h.end());
464
465 if((g_test->get_key_type() != KEY_TYPE_SWIFT)){
466 h.insert(h.end(), "");
467 flags = RGW_CORS_GET | RGW_CORS_PUT;
468 send_cors(origins, h, e, flags, CORS_MAX_AGE_INVALID);
469 EXPECT_EQ((400U), g_test->get_resp_code());
470 h.erase(h.begin(), h.end());
471 }
472 ASSERT_EQ(0, delete_bucket());
473}
474
475TEST(TestCORS, optionscors_test_options_1){
476 ASSERT_EQ(0, create_bucket());
477 set<string> origins, h;
478 list<string> e;
479
480 origins.insert(origins.end(), "*.example.com");
481 uint8_t flags = RGW_CORS_GET | RGW_CORS_PUT;
482
483 send_cors(origins, h, e, flags, CORS_MAX_AGE_INVALID);
484 EXPECT_EQ(((g_test->get_key_type() == KEY_TYPE_SWIFT)?202U:200U), g_test->get_resp_code());
485
486 g_test->set_extra_header(string("Origin: a.example.com"));
487 g_test->set_extra_header(string("Access-Control-Request-Method: GET"));
488 g_test->set_extra_header(string("Access-Control-Allow-Headers: SomeHeader"));
489 g_test->send_request(string("OPTIONS"), BUCKET_URL);
490 EXPECT_EQ(200U, g_test->get_resp_code());
491 if(g_test->get_resp_code() == 200){
492 string s = g_test->get_response(string("Access-Control-Allow-Origin"));
493 EXPECT_EQ(0, s.compare("a.example.com"));
494 s = g_test->get_response(string("Access-Control-Allow-Methods"));
495 EXPECT_EQ(0, s.compare("GET"));
496 s = g_test->get_response(string("Access-Control-Allow-Headers"));
497 EXPECT_EQ(0U, s.length());
498 s = g_test->get_response(string("Access-Control-Max-Age"));
499 EXPECT_EQ(0U, s.length());
500 s = g_test->get_response(string("Access-Control-Expose-Headers"));
501 EXPECT_EQ(0U, s.length());
502 }
503
504 ASSERT_EQ(0, delete_bucket());
505}
506
507TEST(TestCORS, optionscors_test_options_2){
508 ASSERT_EQ(0, create_bucket());
509 set<string> origins, h;
510 list<string> e;
511
512 origins.insert(origins.end(), "*.example.com");
513 uint8_t flags = RGW_CORS_GET | RGW_CORS_PUT | RGW_CORS_DELETE | RGW_CORS_HEAD;
514
515 send_cors(origins, h, e, flags, CORS_MAX_AGE_INVALID);
516 EXPECT_EQ(((g_test->get_key_type() == KEY_TYPE_SWIFT)?202U:200U), g_test->get_resp_code());
517
518 g_test->set_extra_header(string("Origin: a.example.com"));
519 g_test->set_extra_header(string("Access-Control-Request-Method: HEAD"));
520 g_test->send_request(string("OPTIONS"), BUCKET_URL);
521 EXPECT_EQ(200U, g_test->get_resp_code());
522 if(g_test->get_resp_code() == 200){
523 string s = g_test->get_response(string("Access-Control-Allow-Origin"));
524 EXPECT_EQ(0, s.compare("a.example.com"));
525 s = g_test->get_response(string("Access-Control-Allow-Methods"));
526 EXPECT_EQ(0, s.compare("HEAD"));
527 }
528
529 g_test->set_extra_header(string("Origin: foo.bar.example.com"));
530 g_test->set_extra_header(string("Access-Control-Request-Method: HEAD"));
531 g_test->send_request(string("OPTIONS"), BUCKET_URL);
532 EXPECT_EQ(200U, g_test->get_resp_code());
533 if(g_test->get_resp_code() == 200){
534 string s = g_test->get_response(string("Access-Control-Allow-Origin"));
535 EXPECT_EQ(0, s.compare("foo.bar.example.com"));
536 s = g_test->get_response(string("Access-Control-Allow-Methods"));
537 EXPECT_EQ(0, s.compare("HEAD"));
538 }
539 ASSERT_EQ(0, delete_bucket());
540}
541
542TEST(TestCORS, optionscors_test_options_3){
543 ASSERT_EQ(0, create_bucket());
544 set<string> origins, h;
545 list<string> e;
546
547 origins.insert(origins.end(), "*");
548 uint8_t flags = RGW_CORS_GET | RGW_CORS_PUT | RGW_CORS_DELETE | RGW_CORS_HEAD;
549
550 send_cors(origins, h, e, flags, CORS_MAX_AGE_INVALID);
551 EXPECT_EQ(((g_test->get_key_type() == KEY_TYPE_SWIFT)?202U:200U), g_test->get_resp_code());
552
553 /*Check for HEAD in Access-Control-Allow-Methods*/
554 g_test->set_extra_header(string("Origin: a.example.com"));
555 g_test->set_extra_header(string("Access-Control-Request-Method: HEAD"));
556 g_test->send_request(string("OPTIONS"), BUCKET_URL);
557 EXPECT_EQ(200U, g_test->get_resp_code());
558 if(g_test->get_resp_code() == 200){
559 string s = g_test->get_response(string("Access-Control-Allow-Origin"));
560 EXPECT_EQ(0, s.compare("a.example.com"));
561 s = g_test->get_response(string("Access-Control-Allow-Methods"));
562 EXPECT_EQ(0, s.compare("HEAD"));
563 }
564
565 /*Check for DELETE in Access-Control-Allow-Methods*/
566 g_test->set_extra_header(string("Origin: foo.bar"));
567 g_test->set_extra_header(string("Access-Control-Request-Method: DELETE"));
568 g_test->send_request(string("OPTIONS"), BUCKET_URL);
569 EXPECT_EQ(200U, g_test->get_resp_code());
570 if(g_test->get_resp_code() == 200){
571 string s = g_test->get_response(string("Access-Control-Allow-Origin"));
572 EXPECT_EQ(0, s.compare("foo.bar"));
573 s = g_test->get_response(string("Access-Control-Allow-Methods"));
574 EXPECT_EQ(0, s.compare("DELETE"));
575 }
576
577 /*Check for PUT in Access-Control-Allow-Methods*/
578 g_test->set_extra_header(string("Origin: foo.bar"));
579 g_test->set_extra_header(string("Access-Control-Request-Method: PUT"));
580 g_test->send_request(string("OPTIONS"), BUCKET_URL);
581 EXPECT_EQ(200U, g_test->get_resp_code());
582 if(g_test->get_resp_code() == 200){
583 string s = g_test->get_response(string("Access-Control-Allow-Origin"));
584 EXPECT_EQ(0, s.compare("foo.bar"));
585 s = g_test->get_response(string("Access-Control-Allow-Methods"));
586 EXPECT_EQ(0, s.compare("PUT"));
587 }
588
589 /*Check for POST in Access-Control-Allow-Methods*/
590 g_test->set_extra_header(string("Origin: foo.bar"));
591 g_test->set_extra_header(string("Access-Control-Request-Method: POST"));
592 g_test->send_request(string("OPTIONS"), BUCKET_URL);
593 EXPECT_EQ(200U, g_test->get_resp_code());
594 if(g_test->get_resp_code() == 200){
595 string s = g_test->get_response(string("Access-Control-Allow-Origin"));
596 EXPECT_EQ(0, s.compare("foo.bar"));
597 if(g_test->get_key_type() == KEY_TYPE_S3){
598 s = g_test->get_response(string("Access-Control-Allow-Methods"));
599 EXPECT_EQ(0U, s.length());
600 }else{
601 s = g_test->get_response(string("Access-Control-Allow-Methods"));
602 EXPECT_EQ(0, s.compare("POST"));
603 }
604 }
605 ASSERT_EQ(0, delete_bucket());
606}
607
608TEST(TestCORS, optionscors_test_options_4){
609 ASSERT_EQ(0, create_bucket());
610 set<string> origins, h;
611 list<string> e;
612
613 origins.insert(origins.end(), "example.com");
614 h.insert(h.end(), "Header1");
615 h.insert(h.end(), "Header2");
616 h.insert(h.end(), "*");
617 uint8_t flags = RGW_CORS_GET | RGW_CORS_PUT;
618
619 send_cors(origins, h, e, flags, CORS_MAX_AGE_INVALID);
620 EXPECT_EQ(((g_test->get_key_type() == KEY_TYPE_SWIFT)?202U:200U), g_test->get_resp_code());
621
622 g_test->set_extra_header(string("Origin: example.com"));
623 g_test->set_extra_header(string("Access-Control-Request-Method: GET"));
624 g_test->send_request(string("OPTIONS"), BUCKET_URL);
625 EXPECT_EQ(200U, g_test->get_resp_code());
626 if(g_test->get_resp_code() == 200){
627 string s = g_test->get_response(string("Access-Control-Allow-Origin"));
628 EXPECT_EQ(0, s.compare("example.com"));
629 s = g_test->get_response(string("Access-Control-Allow-Methods"));
630 EXPECT_EQ(0, s.compare("GET"));
631 s = g_test->get_response(string("Access-Control-Allow-Headers"));
632 EXPECT_EQ(0U, s.length());
633 }
634 g_test->set_extra_header(string("Origin: example.com"));
635 g_test->set_extra_header(string("Access-Control-Request-Method: GET"));
636 g_test->set_extra_header(string("Access-Control-Allow-Headers: Header1"));
637 g_test->send_request(string("OPTIONS"), BUCKET_URL);
638 EXPECT_EQ(200U, g_test->get_resp_code());
639 if(g_test->get_resp_code() == 200){
640 string s = g_test->get_response(string("Access-Control-Allow-Origin"));
641 EXPECT_EQ(0, s.compare("example.com"));
642 s = g_test->get_response(string("Access-Control-Allow-Methods"));
643 EXPECT_EQ(0, s.compare("GET"));
644 s = g_test->get_response(string("Access-Control-Allow-Headers"));
645 EXPECT_EQ(0, s.compare("Header1"));
646 }
647 g_test->set_extra_header(string("Origin: example.com"));
648 g_test->set_extra_header(string("Access-Control-Request-Method: GET"));
649 g_test->set_extra_header(string("Access-Control-Allow-Headers: Header2"));
650 g_test->send_request(string("OPTIONS"), BUCKET_URL);
651 EXPECT_EQ(200U, g_test->get_resp_code());
652 if(g_test->get_resp_code() == 200){
653 string s = g_test->get_response(string("Access-Control-Allow-Origin"));
654 EXPECT_EQ(0, s.compare("example.com"));
655 s = g_test->get_response(string("Access-Control-Allow-Methods"));
656 EXPECT_EQ(0, s.compare("GET"));
657 s = g_test->get_response(string("Access-Control-Allow-Headers"));
658 EXPECT_EQ(0, s.compare("Header2"));
659 }
660 g_test->set_extra_header(string("Origin: example.com"));
661 g_test->set_extra_header(string("Access-Control-Request-Method: GET"));
662 g_test->set_extra_header(string("Access-Control-Allow-Headers: Header2, Header1"));
663 g_test->send_request(string("OPTIONS"), BUCKET_URL);
664 EXPECT_EQ(200U, g_test->get_resp_code());
665 if(g_test->get_resp_code() == 200){
666 string s = g_test->get_response(string("Access-Control-Allow-Origin"));
667 EXPECT_EQ(0, s.compare("example.com"));
668 s = g_test->get_response(string("Access-Control-Allow-Methods"));
669 EXPECT_EQ(0, s.compare("GET"));
670 s = g_test->get_response(string("Access-Control-Allow-Headers"));
671 EXPECT_EQ(0, s.compare("Header2,Header1"));
672 }
673 g_test->set_extra_header(string("Origin: example.com"));
674 g_test->set_extra_header(string("Access-Control-Request-Method: GET"));
675 g_test->set_extra_header(string("Access-Control-Allow-Headers: Header1, Header2"));
676 g_test->send_request(string("OPTIONS"), BUCKET_URL);
677 EXPECT_EQ(200U, g_test->get_resp_code());
678 if(g_test->get_resp_code() == 200){
679 string s = g_test->get_response(string("Access-Control-Allow-Origin"));
680 EXPECT_EQ(0, s.compare("example.com"));
681 s = g_test->get_response(string("Access-Control-Allow-Methods"));
682 EXPECT_EQ(0, s.compare("GET"));
683 s = g_test->get_response(string("Access-Control-Allow-Headers"));
684 EXPECT_EQ(0, s.compare("Header1,Header2"));
685 }
686 g_test->set_extra_header(string("Origin: example.com"));
687 g_test->set_extra_header(string("Access-Control-Request-Method: GET"));
688 g_test->set_extra_header(string("Access-Control-Allow-Headers: Header1, Header2, Header3"));
689 g_test->send_request(string("OPTIONS"), BUCKET_URL);
690 EXPECT_EQ(200U, g_test->get_resp_code());
691 if(g_test->get_resp_code() == 200){
692 string s = g_test->get_response(string("Access-Control-Allow-Origin"));
693 EXPECT_EQ(0, s.compare("example.com"));
694 s = g_test->get_response(string("Access-Control-Allow-Methods"));
695 EXPECT_EQ(0, s.compare("GET"));
696 s = g_test->get_response(string("Access-Control-Allow-Headers"));
697 EXPECT_EQ(0, s.compare("Header1,Header2,Header3"));
698 }
699 ASSERT_EQ(0, delete_bucket());
700}
701
702TEST(TestCORS, optionscors_test_options_5){
703 ASSERT_EQ(0, create_bucket());
704 set<string> origins, h;
705 list<string> e;
706
707 origins.insert(origins.end(), "example.com");
708 e.insert(e.end(), "Expose1");
709 e.insert(e.end(), "Expose2");
710 uint8_t flags = RGW_CORS_GET | RGW_CORS_PUT;
711
712 send_cors(origins, h, e, flags, CORS_MAX_AGE_INVALID);
713 EXPECT_EQ(((g_test->get_key_type() == KEY_TYPE_SWIFT)?202U:200U), g_test->get_resp_code());
714
715 g_test->set_extra_header(string("Origin: example.com"));
716 g_test->set_extra_header(string("Access-Control-Request-Method: GET"));
717 g_test->send_request(string("OPTIONS"), BUCKET_URL);
718 EXPECT_EQ(200U, g_test->get_resp_code());
719 if(g_test->get_resp_code() == 200){
720 string s = g_test->get_response(string("Access-Control-Allow-Origin"));
721 EXPECT_EQ(0, s.compare("example.com"));
722 s = g_test->get_response(string("Access-Control-Allow-Methods"));
723 EXPECT_EQ(0, s.compare("GET"));
724 s = g_test->get_response(string("Access-Control-Expose-Headers"));
725 EXPECT_EQ(0, s.compare("Expose1,Expose2"));
726 }
727 ASSERT_EQ(0, delete_bucket());
728}
729
730TEST(TestCORS, optionscors_test_options_6){
731 ASSERT_EQ(0, create_bucket());
732 set<string> origins, h;
733 list<string> e;
734 unsigned err = (g_test->get_key_type() == KEY_TYPE_SWIFT)?401U:403U;
735
736 origins.insert(origins.end(), "http://www.example.com");
737 uint8_t flags = RGW_CORS_GET | RGW_CORS_PUT;
738
739 send_cors(origins, h, e, flags, CORS_MAX_AGE_INVALID);
740 EXPECT_EQ(((g_test->get_key_type() == KEY_TYPE_SWIFT)?202U:200U), g_test->get_resp_code());
741
742 g_test->set_extra_header(string("Origin: example.com"));
743 g_test->set_extra_header(string("Access-Control-Request-Method: GET"));
744 g_test->send_request(string("OPTIONS"), BUCKET_URL);
745 EXPECT_EQ(err, g_test->get_resp_code());
746
747 g_test->set_extra_header(string("Origin: http://example.com"));
748 g_test->set_extra_header(string("Access-Control-Request-Method: GET"));
749 g_test->send_request(string("OPTIONS"), BUCKET_URL);
750 EXPECT_EQ(err, g_test->get_resp_code());
751
752 g_test->set_extra_header(string("Origin: www.example.com"));
753 g_test->set_extra_header(string("Access-Control-Request-Method: GET"));
754 g_test->send_request(string("OPTIONS"), BUCKET_URL);
755 EXPECT_EQ(err, g_test->get_resp_code());
756
757 g_test->set_extra_header(string("Origin: http://www.example.com"));
758 g_test->set_extra_header(string("Access-Control-Request-Method: GET"));
759 g_test->send_request(string("OPTIONS"), BUCKET_URL);
760 EXPECT_EQ(200U, g_test->get_resp_code());
761
762 origins.erase(origins.begin(), origins.end());
763 origins.insert(origins.end(), "*.example.com");
764 send_cors(origins, h, e, flags, CORS_MAX_AGE_INVALID);
765 EXPECT_EQ(((g_test->get_key_type() == KEY_TYPE_SWIFT)?202U:200U), g_test->get_resp_code());
766
767 g_test->set_extra_header(string("Origin: .example.com"));
768 g_test->set_extra_header(string("Access-Control-Request-Method: GET"));
769 g_test->send_request(string("OPTIONS"), BUCKET_URL);
770 EXPECT_EQ(200U, g_test->get_resp_code());
771
772 g_test->set_extra_header(string("Origin: http://example.com"));
773 g_test->set_extra_header(string("Access-Control-Request-Method: GET"));
774 g_test->send_request(string("OPTIONS"), BUCKET_URL);
775 EXPECT_EQ(err, g_test->get_resp_code());
776
777 g_test->set_extra_header(string("Origin: www.example.com"));
778 g_test->set_extra_header(string("Access-Control-Request-Method: GET"));
779 g_test->send_request(string("OPTIONS"), BUCKET_URL);
780 EXPECT_EQ(200U, g_test->get_resp_code());
781
782 g_test->set_extra_header(string("Origin: http://www.example.com"));
783 g_test->set_extra_header(string("Access-Control-Request-Method: GET"));
784 g_test->send_request(string("OPTIONS"), BUCKET_URL);
785 EXPECT_EQ(200U, g_test->get_resp_code());
786
787 g_test->set_extra_header(string("Origin: https://www.example.com"));
788 g_test->set_extra_header(string("Access-Control-Request-Method: GET"));
789 g_test->send_request(string("OPTIONS"), BUCKET_URL);
790 EXPECT_EQ(200U, g_test->get_resp_code());
791
792 origins.erase(origins.begin(), origins.end());
793 origins.insert(origins.end(), "https://example*.com");
794 send_cors(origins, h, e, flags, CORS_MAX_AGE_INVALID);
795 EXPECT_EQ(((g_test->get_key_type() == KEY_TYPE_SWIFT)?202U:200U), g_test->get_resp_code());
796
797 g_test->set_extra_header(string("Origin: https://example.com"));
798 g_test->set_extra_header(string("Access-Control-Request-Method: GET"));
799 g_test->send_request(string("OPTIONS"), BUCKET_URL);
800 EXPECT_EQ(200U, g_test->get_resp_code());
801
802 g_test->set_extra_header(string("Origin: http://example.com"));
803 g_test->set_extra_header(string("Access-Control-Request-Method: GET"));
804 g_test->send_request(string("OPTIONS"), BUCKET_URL);
805 EXPECT_EQ(err, g_test->get_resp_code());
806
807 g_test->set_extra_header(string("Origin: www.example.com"));
808 g_test->set_extra_header(string("Access-Control-Request-Method: GET"));
809 g_test->send_request(string("OPTIONS"), BUCKET_URL);
810 EXPECT_EQ(err, g_test->get_resp_code());
811
812 g_test->set_extra_header(string("Origin: https://example.a.b.com"));
813 g_test->set_extra_header(string("Access-Control-Request-Method: GET"));
814 g_test->send_request(string("OPTIONS"), BUCKET_URL);
815 EXPECT_EQ(200U, g_test->get_resp_code());
816
817 ASSERT_EQ(0, delete_bucket());
818}
819
820TEST(TestCORS, optionscors_test_options_7){
821 ASSERT_EQ(0, create_bucket());
822 set<string> origins, h;
823 list<string> e;
824
825 origins.insert(origins.end(), "example.com");
826 h.insert(h.end(), "Header*");
827 h.insert(h.end(), "Hdr-*-Length");
828 h.insert(h.end(), "*-Length");
829 h.insert(h.end(), "foo*foo");
830 uint8_t flags = RGW_CORS_GET | RGW_CORS_PUT;
831
832 send_cors(origins, h, e, flags, CORS_MAX_AGE_INVALID);
833 EXPECT_EQ(((g_test->get_key_type() == KEY_TYPE_SWIFT)?202U:200U), g_test->get_resp_code());
834
835 g_test->set_extra_header(string("Origin: example.com"));
836 g_test->set_extra_header(string("Access-Control-Request-Method: GET"));
837 g_test->set_extra_header(string("Access-Control-Allow-Headers: Header1, Header2, Header3, "
838 "Hdr--Length, Hdr-1-Length, Header-Length, Content-Length, foofoofoo"));
839 g_test->send_request(string("OPTIONS"), BUCKET_URL);
840 EXPECT_EQ(200U, g_test->get_resp_code());
841 if(g_test->get_resp_code() == 200){
842 string s = g_test->get_response(string("Access-Control-Allow-Origin"));
843 EXPECT_EQ(0, s.compare("example.com"));
844 s = g_test->get_response(string("Access-Control-Allow-Methods"));
845 EXPECT_EQ(0, s.compare("GET"));
846 s = g_test->get_response(string("Access-Control-Allow-Headers"));
847 EXPECT_EQ(0, s.compare("Header1,Header2,Header3,"
848 "Hdr--Length,Hdr-1-Length,Header-Length,Content-Length,foofoofoo"));
849 }
850 ASSERT_EQ(0, delete_bucket());
851}
852
853TEST(TestCORS, deletecors_firsttime){
854 if(g_test->get_key_type() == KEY_TYPE_SWIFT)return;
855 ASSERT_EQ(0, create_bucket());
856 g_test->send_request("DELETE", "/" S3_BUCKET_NAME "?cors");
857 EXPECT_EQ(204U, g_test->get_resp_code());
858 ASSERT_EQ(0, delete_bucket());
859}
860
861TEST(TestCORS, deletecors_test){
862 set<string> origins, h;
863 list<string> e;
864 if(g_test->get_key_type() == KEY_TYPE_SWIFT)return;
865 ASSERT_EQ(0, create_bucket());
866 origins.insert(origins.end(), "example.com");
867 uint8_t flags = RGW_CORS_GET | RGW_CORS_PUT;
868
869 send_cors(origins, h, e, flags, CORS_MAX_AGE_INVALID);
870 EXPECT_EQ(((g_test->get_key_type() == KEY_TYPE_SWIFT)?202U:200U), g_test->get_resp_code());
871
872 g_test->send_request("GET", "/" S3_BUCKET_NAME "?cors");
873 EXPECT_EQ(200U, g_test->get_resp_code());
874 g_test->send_request("DELETE", "/" S3_BUCKET_NAME "?cors");
875 EXPECT_EQ(204U, g_test->get_resp_code());
876 g_test->send_request("GET", "/" S3_BUCKET_NAME "?cors");
877 EXPECT_EQ(404U, g_test->get_resp_code());
878 ASSERT_EQ(0, delete_bucket());
879}
880
881int main(int argc, char *argv[]){
882 vector<const char*> args;
883 argv_to_vec(argc, (const char **)argv, args);
884
885 auto cct = global_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT,
11fdf7f2
TL
886 CODE_ENVIRONMENT_UTILITY,
887 CINIT_FLAG_NO_DEFAULT_CONFIG_FILE);
7c673cae
FG
888 common_init_finish(g_ceph_context);
889 g_test = new test_cors_helper();
890 finisher = new Finisher(g_ceph_context);
891#ifdef GTEST
892 ::testing::InitGoogleTest(&argc, argv);
893#endif
894 finisher->start();
895
896 if(g_test->extract_input((unsigned)argc, argv) < 0){
897 print_usage(argv[0]);
898 return -1;
899 }
900#ifdef GTEST
901 int r = RUN_ALL_TESTS();
902 if (r >= 0) {
903 cout << "There are failures in the test case\n";
904 return -1;
905 }
906#endif
907 finisher->stop();
908 delete g_test;
909 delete finisher;
910 return 0;
911}
912