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