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