]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/test_cors.cc
import ceph pacific 16.2.5
[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 const DoutPrefix dp(g_ceph_context, 1, "test cors: ");
311 RGWCORSXMLParser_S3 parser(&dp, g_ceph_context);
312 const string *data = g_test->get_response_data();
313 if (!parser.init()) {
314 return NULL;
315 }
316 if (!parser.parse(data->c_str(), data->length(), 1)) {
317 return NULL;
318 }
319 cors_config = (RGWCORSConfiguration_S3 *)parser.find_first("CORSConfiguration");
320 if (!cors_config) {
321 return NULL;
322 }
323 return cors_config->host_name_rule(s.c_str());
324 }
325
326 size_t cors_read_xml(void *ptr, size_t s, size_t n, void *ud){
327 stringstream *ss = (stringstream *)ud;
328 size_t len = ss->str().length();
329 if(s*n < len){
330 cout << "Cannot copy xml data, as len is not enough\n";
331 return 0;
332 }
333 memcpy(ptr, (void *)ss->str().c_str(), len);
334 return len;
335 }
336
337 void send_cors(set<string> o, set<string> h,
338 list<string> e, uint8_t flags,
339 unsigned max_age){
340 if(g_test->get_key_type() == KEY_TYPE_S3){
341 RGWCORSRule rule(o, h, e, flags, max_age);
342 RGWCORSConfiguration config;
343 config.stack_rule(rule);
344 stringstream ss;
345 RGWCORSConfiguration_S3 *s3;
346 s3 = static_cast<RGWCORSConfiguration_S3 *>(&config);
347 s3->to_xml(ss);
348
349 g_test->send_request(string("PUT"), string("/" S3_BUCKET_NAME "?cors"), cors_read_xml,
350 (void *)&ss, ss.str().length());
351 }else if(g_test->get_key_type() == KEY_TYPE_SWIFT){
352 set<string>::iterator it;
353 string a_o;
354 for(it = o.begin(); it != o.end(); ++it){
355 if(a_o.length() > 0)a_o.append(" ");
356 a_o.append(*it);
357 }
358 g_test->set_extra_header(string("X-Container-Meta-Access-Control-Allow-Origin: ") + a_o);
359
360 if(!h.empty()){
361 string a_h;
362 for(it = h.begin(); it != h.end(); ++it){
363 if(a_h.length() > 0)a_h.append(" ");
364 a_h.append(*it);
365 }
366 g_test->set_extra_header(string("X-Container-Meta-Access-Control-Allow-Headers: ") + a_h);
367 }
368 if(!e.empty()){
369 string e_h;
370 for(list<string>::iterator lit = e.begin(); lit != e.end(); ++lit){
371 if(e_h.length() > 0)e_h.append(" ");
372 e_h.append(*lit);
373 }
374 g_test->set_extra_header(string("X-Container-Meta-Access-Control-Expose-Headers: ") + e_h);
375 }
376 if(max_age != CORS_MAX_AGE_INVALID){
377 char age[32];
378 sprintf(age, "%u", max_age);
379 g_test->set_extra_header(string("X-Container-Meta-Access-Control-Max-Age: ") + string(age));
380 }
381 //const char *data = "1";
382 stringstream ss;
383 ss << "1";
384 g_test->send_request(string("POST"), string("/swift/v1/" SWIFT_BUCKET_NAME), cors_read_xml,
385 (void *)&ss, 1);
386 }
387 }
388
389 TEST(TestCORS, getcors_firsttime){
390 if(g_test->get_key_type() == KEY_TYPE_SWIFT)return;
391 ASSERT_EQ(0, create_bucket());
392 g_test->send_request(string("GET"), string("/" S3_BUCKET_NAME "?cors"));
393 EXPECT_EQ(404U, g_test->get_resp_code());
394 ASSERT_EQ(0, delete_bucket());
395 }
396
397 TEST(TestCORS, putcors_firsttime){
398 ASSERT_EQ(0, create_bucket());
399 set<string> origins, h;
400 list<string> e;
401
402 origins.insert(origins.end(), "example.com");
403 uint8_t flags = RGW_CORS_GET | RGW_CORS_PUT;
404
405 send_cors(origins, h, e, flags, CORS_MAX_AGE_INVALID);
406 EXPECT_EQ(((g_test->get_key_type() == KEY_TYPE_SWIFT)?202U:200U), g_test->get_resp_code());
407
408 /*Now get the CORS and check if its fine*/
409 if(g_test->get_key_type() == KEY_TYPE_S3){
410 g_test->send_request(string("GET"), string("/" S3_BUCKET_NAME "?cors"));
411 EXPECT_EQ(200U, g_test->get_resp_code());
412
413 RGWCORSRule *r = xml_to_cors_rule(string("example.com"));
414 EXPECT_TRUE(r != NULL);
415 if(!r)return;
416
417 EXPECT_TRUE((r->get_allowed_methods() & (RGW_CORS_GET | RGW_CORS_PUT))
418 == (RGW_CORS_GET | RGW_CORS_PUT));
419 }
420 ASSERT_EQ(0, delete_bucket());
421 }
422
423 TEST(TestCORS, putcors_invalid_hostname){
424 ASSERT_EQ(0, create_bucket());
425 set<string> origins, h;
426 list<string> e;
427
428 origins.insert(origins.end(), "*.example.*");
429 uint8_t flags = RGW_CORS_GET | RGW_CORS_PUT;
430 send_cors(origins, h, e, flags, CORS_MAX_AGE_INVALID);
431 EXPECT_EQ((400U), g_test->get_resp_code());
432 origins.erase(origins.begin(), origins.end());
433
434 if((g_test->get_key_type() != KEY_TYPE_SWIFT)){
435 origins.insert(origins.end(), "");
436 send_cors(origins, h, e, flags, CORS_MAX_AGE_INVALID);
437 EXPECT_EQ((400U), g_test->get_resp_code());
438 origins.erase(origins.begin(), origins.end());
439 }
440 ASSERT_EQ(0, delete_bucket());
441 }
442
443 TEST(TestCORS, putcors_invalid_headers){
444 ASSERT_EQ(0, create_bucket());
445 set<string> origins, h;
446 list<string> e;
447
448 origins.insert(origins.end(), "www.example.com");
449 h.insert(h.end(), "*-Header-*");
450 uint8_t flags = RGW_CORS_GET | RGW_CORS_PUT;
451 send_cors(origins, h, e, flags, CORS_MAX_AGE_INVALID);
452 EXPECT_EQ((400U), g_test->get_resp_code());
453 h.erase(h.begin(), h.end());
454
455 if((g_test->get_key_type() != KEY_TYPE_SWIFT)){
456 h.insert(h.end(), "");
457 flags = RGW_CORS_GET | RGW_CORS_PUT;
458 send_cors(origins, h, e, flags, CORS_MAX_AGE_INVALID);
459 EXPECT_EQ((400U), g_test->get_resp_code());
460 h.erase(h.begin(), h.end());
461 }
462 ASSERT_EQ(0, delete_bucket());
463 }
464
465 TEST(TestCORS, optionscors_test_options_1){
466 ASSERT_EQ(0, create_bucket());
467 set<string> origins, h;
468 list<string> e;
469
470 origins.insert(origins.end(), "*.example.com");
471 uint8_t flags = RGW_CORS_GET | RGW_CORS_PUT;
472
473 send_cors(origins, h, e, flags, CORS_MAX_AGE_INVALID);
474 EXPECT_EQ(((g_test->get_key_type() == KEY_TYPE_SWIFT)?202U:200U), g_test->get_resp_code());
475
476 g_test->set_extra_header(string("Origin: a.example.com"));
477 g_test->set_extra_header(string("Access-Control-Request-Method: GET"));
478 g_test->set_extra_header(string("Access-Control-Allow-Headers: SomeHeader"));
479 g_test->send_request(string("OPTIONS"), BUCKET_URL);
480 EXPECT_EQ(200U, g_test->get_resp_code());
481 if(g_test->get_resp_code() == 200){
482 string s = g_test->get_response(string("Access-Control-Allow-Origin"));
483 EXPECT_EQ(0, s.compare("a.example.com"));
484 s = g_test->get_response(string("Access-Control-Allow-Methods"));
485 EXPECT_EQ(0, s.compare("GET"));
486 s = g_test->get_response(string("Access-Control-Allow-Headers"));
487 EXPECT_EQ(0U, s.length());
488 s = g_test->get_response(string("Access-Control-Max-Age"));
489 EXPECT_EQ(0U, s.length());
490 s = g_test->get_response(string("Access-Control-Expose-Headers"));
491 EXPECT_EQ(0U, s.length());
492 }
493
494 ASSERT_EQ(0, delete_bucket());
495 }
496
497 TEST(TestCORS, optionscors_test_options_2){
498 ASSERT_EQ(0, create_bucket());
499 set<string> origins, h;
500 list<string> e;
501
502 origins.insert(origins.end(), "*.example.com");
503 uint8_t flags = RGW_CORS_GET | RGW_CORS_PUT | RGW_CORS_DELETE | RGW_CORS_HEAD;
504
505 send_cors(origins, h, e, flags, CORS_MAX_AGE_INVALID);
506 EXPECT_EQ(((g_test->get_key_type() == KEY_TYPE_SWIFT)?202U:200U), g_test->get_resp_code());
507
508 g_test->set_extra_header(string("Origin: a.example.com"));
509 g_test->set_extra_header(string("Access-Control-Request-Method: HEAD"));
510 g_test->send_request(string("OPTIONS"), BUCKET_URL);
511 EXPECT_EQ(200U, g_test->get_resp_code());
512 if(g_test->get_resp_code() == 200){
513 string s = g_test->get_response(string("Access-Control-Allow-Origin"));
514 EXPECT_EQ(0, s.compare("a.example.com"));
515 s = g_test->get_response(string("Access-Control-Allow-Methods"));
516 EXPECT_EQ(0, s.compare("HEAD"));
517 }
518
519 g_test->set_extra_header(string("Origin: foo.bar.example.com"));
520 g_test->set_extra_header(string("Access-Control-Request-Method: HEAD"));
521 g_test->send_request(string("OPTIONS"), BUCKET_URL);
522 EXPECT_EQ(200U, g_test->get_resp_code());
523 if(g_test->get_resp_code() == 200){
524 string s = g_test->get_response(string("Access-Control-Allow-Origin"));
525 EXPECT_EQ(0, s.compare("foo.bar.example.com"));
526 s = g_test->get_response(string("Access-Control-Allow-Methods"));
527 EXPECT_EQ(0, s.compare("HEAD"));
528 }
529 ASSERT_EQ(0, delete_bucket());
530 }
531
532 TEST(TestCORS, optionscors_test_options_3){
533 ASSERT_EQ(0, create_bucket());
534 set<string> origins, h;
535 list<string> e;
536
537 origins.insert(origins.end(), "*");
538 uint8_t flags = RGW_CORS_GET | RGW_CORS_PUT | RGW_CORS_DELETE | RGW_CORS_HEAD;
539
540 send_cors(origins, h, e, flags, CORS_MAX_AGE_INVALID);
541 EXPECT_EQ(((g_test->get_key_type() == KEY_TYPE_SWIFT)?202U:200U), g_test->get_resp_code());
542
543 /*Check for HEAD in Access-Control-Allow-Methods*/
544 g_test->set_extra_header(string("Origin: a.example.com"));
545 g_test->set_extra_header(string("Access-Control-Request-Method: HEAD"));
546 g_test->send_request(string("OPTIONS"), BUCKET_URL);
547 EXPECT_EQ(200U, g_test->get_resp_code());
548 if(g_test->get_resp_code() == 200){
549 string s = g_test->get_response(string("Access-Control-Allow-Origin"));
550 EXPECT_EQ(0, s.compare("a.example.com"));
551 s = g_test->get_response(string("Access-Control-Allow-Methods"));
552 EXPECT_EQ(0, s.compare("HEAD"));
553 }
554
555 /*Check for DELETE in Access-Control-Allow-Methods*/
556 g_test->set_extra_header(string("Origin: foo.bar"));
557 g_test->set_extra_header(string("Access-Control-Request-Method: DELETE"));
558 g_test->send_request(string("OPTIONS"), BUCKET_URL);
559 EXPECT_EQ(200U, g_test->get_resp_code());
560 if(g_test->get_resp_code() == 200){
561 string s = g_test->get_response(string("Access-Control-Allow-Origin"));
562 EXPECT_EQ(0, s.compare("foo.bar"));
563 s = g_test->get_response(string("Access-Control-Allow-Methods"));
564 EXPECT_EQ(0, s.compare("DELETE"));
565 }
566
567 /*Check for PUT in Access-Control-Allow-Methods*/
568 g_test->set_extra_header(string("Origin: foo.bar"));
569 g_test->set_extra_header(string("Access-Control-Request-Method: PUT"));
570 g_test->send_request(string("OPTIONS"), BUCKET_URL);
571 EXPECT_EQ(200U, g_test->get_resp_code());
572 if(g_test->get_resp_code() == 200){
573 string s = g_test->get_response(string("Access-Control-Allow-Origin"));
574 EXPECT_EQ(0, s.compare("foo.bar"));
575 s = g_test->get_response(string("Access-Control-Allow-Methods"));
576 EXPECT_EQ(0, s.compare("PUT"));
577 }
578
579 /*Check for POST in Access-Control-Allow-Methods*/
580 g_test->set_extra_header(string("Origin: foo.bar"));
581 g_test->set_extra_header(string("Access-Control-Request-Method: POST"));
582 g_test->send_request(string("OPTIONS"), BUCKET_URL);
583 EXPECT_EQ(200U, g_test->get_resp_code());
584 if(g_test->get_resp_code() == 200){
585 string s = g_test->get_response(string("Access-Control-Allow-Origin"));
586 EXPECT_EQ(0, s.compare("foo.bar"));
587 if(g_test->get_key_type() == KEY_TYPE_S3){
588 s = g_test->get_response(string("Access-Control-Allow-Methods"));
589 EXPECT_EQ(0U, s.length());
590 }else{
591 s = g_test->get_response(string("Access-Control-Allow-Methods"));
592 EXPECT_EQ(0, s.compare("POST"));
593 }
594 }
595 ASSERT_EQ(0, delete_bucket());
596 }
597
598 TEST(TestCORS, optionscors_test_options_4){
599 ASSERT_EQ(0, create_bucket());
600 set<string> origins, h;
601 list<string> e;
602
603 origins.insert(origins.end(), "example.com");
604 h.insert(h.end(), "Header1");
605 h.insert(h.end(), "Header2");
606 h.insert(h.end(), "*");
607 uint8_t flags = RGW_CORS_GET | RGW_CORS_PUT;
608
609 send_cors(origins, h, e, flags, CORS_MAX_AGE_INVALID);
610 EXPECT_EQ(((g_test->get_key_type() == KEY_TYPE_SWIFT)?202U:200U), g_test->get_resp_code());
611
612 g_test->set_extra_header(string("Origin: example.com"));
613 g_test->set_extra_header(string("Access-Control-Request-Method: GET"));
614 g_test->send_request(string("OPTIONS"), BUCKET_URL);
615 EXPECT_EQ(200U, g_test->get_resp_code());
616 if(g_test->get_resp_code() == 200){
617 string s = g_test->get_response(string("Access-Control-Allow-Origin"));
618 EXPECT_EQ(0, s.compare("example.com"));
619 s = g_test->get_response(string("Access-Control-Allow-Methods"));
620 EXPECT_EQ(0, s.compare("GET"));
621 s = g_test->get_response(string("Access-Control-Allow-Headers"));
622 EXPECT_EQ(0U, s.length());
623 }
624 g_test->set_extra_header(string("Origin: example.com"));
625 g_test->set_extra_header(string("Access-Control-Request-Method: GET"));
626 g_test->set_extra_header(string("Access-Control-Allow-Headers: Header1"));
627 g_test->send_request(string("OPTIONS"), BUCKET_URL);
628 EXPECT_EQ(200U, g_test->get_resp_code());
629 if(g_test->get_resp_code() == 200){
630 string s = g_test->get_response(string("Access-Control-Allow-Origin"));
631 EXPECT_EQ(0, s.compare("example.com"));
632 s = g_test->get_response(string("Access-Control-Allow-Methods"));
633 EXPECT_EQ(0, s.compare("GET"));
634 s = g_test->get_response(string("Access-Control-Allow-Headers"));
635 EXPECT_EQ(0, s.compare("Header1"));
636 }
637 g_test->set_extra_header(string("Origin: example.com"));
638 g_test->set_extra_header(string("Access-Control-Request-Method: GET"));
639 g_test->set_extra_header(string("Access-Control-Allow-Headers: Header2"));
640 g_test->send_request(string("OPTIONS"), BUCKET_URL);
641 EXPECT_EQ(200U, g_test->get_resp_code());
642 if(g_test->get_resp_code() == 200){
643 string s = g_test->get_response(string("Access-Control-Allow-Origin"));
644 EXPECT_EQ(0, s.compare("example.com"));
645 s = g_test->get_response(string("Access-Control-Allow-Methods"));
646 EXPECT_EQ(0, s.compare("GET"));
647 s = g_test->get_response(string("Access-Control-Allow-Headers"));
648 EXPECT_EQ(0, s.compare("Header2"));
649 }
650 g_test->set_extra_header(string("Origin: example.com"));
651 g_test->set_extra_header(string("Access-Control-Request-Method: GET"));
652 g_test->set_extra_header(string("Access-Control-Allow-Headers: Header2, Header1"));
653 g_test->send_request(string("OPTIONS"), BUCKET_URL);
654 EXPECT_EQ(200U, g_test->get_resp_code());
655 if(g_test->get_resp_code() == 200){
656 string s = g_test->get_response(string("Access-Control-Allow-Origin"));
657 EXPECT_EQ(0, s.compare("example.com"));
658 s = g_test->get_response(string("Access-Control-Allow-Methods"));
659 EXPECT_EQ(0, s.compare("GET"));
660 s = g_test->get_response(string("Access-Control-Allow-Headers"));
661 EXPECT_EQ(0, s.compare("Header2,Header1"));
662 }
663 g_test->set_extra_header(string("Origin: example.com"));
664 g_test->set_extra_header(string("Access-Control-Request-Method: GET"));
665 g_test->set_extra_header(string("Access-Control-Allow-Headers: Header1, Header2"));
666 g_test->send_request(string("OPTIONS"), BUCKET_URL);
667 EXPECT_EQ(200U, g_test->get_resp_code());
668 if(g_test->get_resp_code() == 200){
669 string s = g_test->get_response(string("Access-Control-Allow-Origin"));
670 EXPECT_EQ(0, s.compare("example.com"));
671 s = g_test->get_response(string("Access-Control-Allow-Methods"));
672 EXPECT_EQ(0, s.compare("GET"));
673 s = g_test->get_response(string("Access-Control-Allow-Headers"));
674 EXPECT_EQ(0, s.compare("Header1,Header2"));
675 }
676 g_test->set_extra_header(string("Origin: example.com"));
677 g_test->set_extra_header(string("Access-Control-Request-Method: GET"));
678 g_test->set_extra_header(string("Access-Control-Allow-Headers: Header1, Header2, Header3"));
679 g_test->send_request(string("OPTIONS"), BUCKET_URL);
680 EXPECT_EQ(200U, g_test->get_resp_code());
681 if(g_test->get_resp_code() == 200){
682 string s = g_test->get_response(string("Access-Control-Allow-Origin"));
683 EXPECT_EQ(0, s.compare("example.com"));
684 s = g_test->get_response(string("Access-Control-Allow-Methods"));
685 EXPECT_EQ(0, s.compare("GET"));
686 s = g_test->get_response(string("Access-Control-Allow-Headers"));
687 EXPECT_EQ(0, s.compare("Header1,Header2,Header3"));
688 }
689 ASSERT_EQ(0, delete_bucket());
690 }
691
692 TEST(TestCORS, optionscors_test_options_5){
693 ASSERT_EQ(0, create_bucket());
694 set<string> origins, h;
695 list<string> e;
696
697 origins.insert(origins.end(), "example.com");
698 e.insert(e.end(), "Expose1");
699 e.insert(e.end(), "Expose2");
700 uint8_t flags = RGW_CORS_GET | RGW_CORS_PUT;
701
702 send_cors(origins, h, e, flags, CORS_MAX_AGE_INVALID);
703 EXPECT_EQ(((g_test->get_key_type() == KEY_TYPE_SWIFT)?202U:200U), g_test->get_resp_code());
704
705 g_test->set_extra_header(string("Origin: example.com"));
706 g_test->set_extra_header(string("Access-Control-Request-Method: GET"));
707 g_test->send_request(string("OPTIONS"), BUCKET_URL);
708 EXPECT_EQ(200U, g_test->get_resp_code());
709 if(g_test->get_resp_code() == 200){
710 string s = g_test->get_response(string("Access-Control-Allow-Origin"));
711 EXPECT_EQ(0, s.compare("example.com"));
712 s = g_test->get_response(string("Access-Control-Allow-Methods"));
713 EXPECT_EQ(0, s.compare("GET"));
714 s = g_test->get_response(string("Access-Control-Expose-Headers"));
715 EXPECT_EQ(0, s.compare("Expose1,Expose2"));
716 }
717 ASSERT_EQ(0, delete_bucket());
718 }
719
720 TEST(TestCORS, optionscors_test_options_6){
721 ASSERT_EQ(0, create_bucket());
722 set<string> origins, h;
723 list<string> e;
724 unsigned err = (g_test->get_key_type() == KEY_TYPE_SWIFT)?401U:403U;
725
726 origins.insert(origins.end(), "http://www.example.com");
727 uint8_t flags = RGW_CORS_GET | RGW_CORS_PUT;
728
729 send_cors(origins, h, e, flags, CORS_MAX_AGE_INVALID);
730 EXPECT_EQ(((g_test->get_key_type() == KEY_TYPE_SWIFT)?202U:200U), g_test->get_resp_code());
731
732 g_test->set_extra_header(string("Origin: example.com"));
733 g_test->set_extra_header(string("Access-Control-Request-Method: GET"));
734 g_test->send_request(string("OPTIONS"), BUCKET_URL);
735 EXPECT_EQ(err, g_test->get_resp_code());
736
737 g_test->set_extra_header(string("Origin: http://example.com"));
738 g_test->set_extra_header(string("Access-Control-Request-Method: GET"));
739 g_test->send_request(string("OPTIONS"), BUCKET_URL);
740 EXPECT_EQ(err, g_test->get_resp_code());
741
742 g_test->set_extra_header(string("Origin: www.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://www.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(200U, g_test->get_resp_code());
751
752 origins.erase(origins.begin(), origins.end());
753 origins.insert(origins.end(), "*.example.com");
754 send_cors(origins, h, e, flags, CORS_MAX_AGE_INVALID);
755 EXPECT_EQ(((g_test->get_key_type() == KEY_TYPE_SWIFT)?202U:200U), g_test->get_resp_code());
756
757 g_test->set_extra_header(string("Origin: .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 g_test->set_extra_header(string("Origin: http://example.com"));
763 g_test->set_extra_header(string("Access-Control-Request-Method: GET"));
764 g_test->send_request(string("OPTIONS"), BUCKET_URL);
765 EXPECT_EQ(err, g_test->get_resp_code());
766
767 g_test->set_extra_header(string("Origin: www.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://www.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(200U, g_test->get_resp_code());
776
777 g_test->set_extra_header(string("Origin: https://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 origins.erase(origins.begin(), origins.end());
783 origins.insert(origins.end(), "https://example*.com");
784 send_cors(origins, h, e, flags, CORS_MAX_AGE_INVALID);
785 EXPECT_EQ(((g_test->get_key_type() == KEY_TYPE_SWIFT)?202U:200U), g_test->get_resp_code());
786
787 g_test->set_extra_header(string("Origin: https://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 g_test->set_extra_header(string("Origin: http://example.com"));
793 g_test->set_extra_header(string("Access-Control-Request-Method: GET"));
794 g_test->send_request(string("OPTIONS"), BUCKET_URL);
795 EXPECT_EQ(err, g_test->get_resp_code());
796
797 g_test->set_extra_header(string("Origin: www.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(err, g_test->get_resp_code());
801
802 g_test->set_extra_header(string("Origin: https://example.a.b.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(200U, g_test->get_resp_code());
806
807 ASSERT_EQ(0, delete_bucket());
808 }
809
810 TEST(TestCORS, optionscors_test_options_7){
811 ASSERT_EQ(0, create_bucket());
812 set<string> origins, h;
813 list<string> e;
814
815 origins.insert(origins.end(), "example.com");
816 h.insert(h.end(), "Header*");
817 h.insert(h.end(), "Hdr-*-Length");
818 h.insert(h.end(), "*-Length");
819 h.insert(h.end(), "foo*foo");
820 uint8_t flags = RGW_CORS_GET | RGW_CORS_PUT;
821
822 send_cors(origins, h, e, flags, CORS_MAX_AGE_INVALID);
823 EXPECT_EQ(((g_test->get_key_type() == KEY_TYPE_SWIFT)?202U:200U), g_test->get_resp_code());
824
825 g_test->set_extra_header(string("Origin: example.com"));
826 g_test->set_extra_header(string("Access-Control-Request-Method: GET"));
827 g_test->set_extra_header(string("Access-Control-Allow-Headers: Header1, Header2, Header3, "
828 "Hdr--Length, Hdr-1-Length, Header-Length, Content-Length, foofoofoo"));
829 g_test->send_request(string("OPTIONS"), BUCKET_URL);
830 EXPECT_EQ(200U, g_test->get_resp_code());
831 if(g_test->get_resp_code() == 200){
832 string s = g_test->get_response(string("Access-Control-Allow-Origin"));
833 EXPECT_EQ(0, s.compare("example.com"));
834 s = g_test->get_response(string("Access-Control-Allow-Methods"));
835 EXPECT_EQ(0, s.compare("GET"));
836 s = g_test->get_response(string("Access-Control-Allow-Headers"));
837 EXPECT_EQ(0, s.compare("Header1,Header2,Header3,"
838 "Hdr--Length,Hdr-1-Length,Header-Length,Content-Length,foofoofoo"));
839 }
840 ASSERT_EQ(0, delete_bucket());
841 }
842
843 TEST(TestCORS, deletecors_firsttime){
844 if(g_test->get_key_type() == KEY_TYPE_SWIFT)return;
845 ASSERT_EQ(0, create_bucket());
846 g_test->send_request("DELETE", "/" S3_BUCKET_NAME "?cors");
847 EXPECT_EQ(204U, g_test->get_resp_code());
848 ASSERT_EQ(0, delete_bucket());
849 }
850
851 TEST(TestCORS, deletecors_test){
852 set<string> origins, h;
853 list<string> e;
854 if(g_test->get_key_type() == KEY_TYPE_SWIFT)return;
855 ASSERT_EQ(0, create_bucket());
856 origins.insert(origins.end(), "example.com");
857 uint8_t flags = RGW_CORS_GET | RGW_CORS_PUT;
858
859 send_cors(origins, h, e, flags, CORS_MAX_AGE_INVALID);
860 EXPECT_EQ(((g_test->get_key_type() == KEY_TYPE_SWIFT)?202U:200U), g_test->get_resp_code());
861
862 g_test->send_request("GET", "/" S3_BUCKET_NAME "?cors");
863 EXPECT_EQ(200U, g_test->get_resp_code());
864 g_test->send_request("DELETE", "/" S3_BUCKET_NAME "?cors");
865 EXPECT_EQ(204U, g_test->get_resp_code());
866 g_test->send_request("GET", "/" S3_BUCKET_NAME "?cors");
867 EXPECT_EQ(404U, g_test->get_resp_code());
868 ASSERT_EQ(0, delete_bucket());
869 }
870
871 int main(int argc, char *argv[]){
872 vector<const char*> args;
873 argv_to_vec(argc, (const char **)argv, args);
874
875 auto cct = global_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT,
876 CODE_ENVIRONMENT_UTILITY,
877 CINIT_FLAG_NO_DEFAULT_CONFIG_FILE);
878 common_init_finish(g_ceph_context);
879 g_test = new test_cors_helper();
880 finisher = new Finisher(g_ceph_context);
881 #ifdef GTEST
882 ::testing::InitGoogleTest(&argc, argv);
883 #endif
884 finisher->start();
885
886 if(g_test->extract_input((unsigned)argc, argv) < 0){
887 print_usage(argv[0]);
888 return -1;
889 }
890 #ifdef GTEST
891 int r = RUN_ALL_TESTS();
892 if (r >= 0) {
893 cout << "There are failures in the test case\n";
894 return -1;
895 }
896 #endif
897 finisher->stop();
898 delete g_test;
899 delete finisher;
900 return 0;
901 }
902