3
#include "rgw_common.h"
6
#include "common/ceph_crypto.h"
7
#include "common/armor.h"
8
#include "common/errno.h"
9
#include "common/Clock.h"
10
#include "common/Formatter.h"
11
#include "common/perf_counters.h"
12
#include "auth/Crypto.h"
16
#define dout_subsys ceph_subsys_rgw
18
PerfCounters *perfcounter = NULL;
20
int rgw_perf_start(CephContext *cct)
22
PerfCountersBuilder plb(cct, cct->_conf->name.to_str(), l_rgw_first, l_rgw_last);
24
plb.add_u64_counter(l_rgw_req, "req");
25
plb.add_u64_counter(l_rgw_failed_req, "failed_req");
27
plb.add_u64_counter(l_rgw_get, "get");
28
plb.add_u64_counter(l_rgw_get_b, "get_b");
29
plb.add_fl_avg(l_rgw_get_lat, "get_initial_lat");
30
plb.add_u64_counter(l_rgw_put, "put");
31
plb.add_u64_counter(l_rgw_put_b, "put_b");
32
plb.add_fl_avg(l_rgw_put_lat, "put_initial_lat");
34
plb.add_u64(l_rgw_qlen, "qlen");
35
plb.add_u64(l_rgw_qactive, "qactive");
37
plb.add_u64_counter(l_rgw_cache_hit, "cache_hit");
38
plb.add_u64_counter(l_rgw_cache_miss, "cache_miss");
40
perfcounter = plb.create_perf_counters();
41
cct->get_perfcounters_collection()->add(perfcounter);
45
void rgw_perf_stop(CephContext *cct)
48
cct->get_perfcounters_collection()->remove(perfcounter);
52
using namespace ceph::crypto;
61
rgw_err(int http, const std::string& s3)
62
: http_ret(http), s3_code(s3)
77
return (http_ret == 200);
83
return !(http_ret >= 200 && http_ret <= 299);
87
req_state::req_state(CephContext *_cct, struct RGWEnv *e) : cct(_cct), os_auth_token(NULL), os_user(NULL), os_groups(NULL), env(e)
89
enable_ops_log = env->conf->enable_ops_log;
90
enable_usage_log = env->conf->enable_usage_log;
91
content_started = false;
100
time = ceph_clock_now(cct);
105
has_bad_meta = false;
110
req_state::~req_state() {
116
free((void *)object);
117
free((void *)bucket_name);
120
std::ostream& operator<<(std::ostream& oss, const rgw_err &err)
122
oss << "rgw_err(http_ret=" << err.http_ret << ", s3='" << err.s3_code << "') ";
126
static bool check_str_end(const char *s)
139
static bool check_gmt_end(const char *s)
144
while (isspace(*s)) {
148
/* check for correct timezone */
149
if ((strncmp(s, "GMT", 3) != 0) &&
150
(strncmp(s, "UTC", 3) != 0)) {
156
while (isspace(*s)) {
165
static bool parse_rfc850(const char *s, struct tm *t)
167
memset(t, 0, sizeof(*t));
168
return check_gmt_end(strptime(s, "%A, %d-%b-%y %H:%M:%S ", t));
171
static bool parse_asctime(const char *s, struct tm *t)
173
memset(t, 0, sizeof(*t));
174
return check_str_end(strptime(s, "%a %b %d %H:%M:%S %Y", t));
177
static bool parse_rfc1123(const char *s, struct tm *t)
179
memset(t, 0, sizeof(*t));
180
return check_gmt_end(strptime(s, "%a, %d %b %Y %H:%M:%S ", t));
183
static bool parse_rfc1123_alt(const char *s, struct tm *t)
185
memset(t, 0, sizeof(*t));
186
return check_str_end(strptime(s, "%a, %d %b %Y %H:%M:%S %z", t));
189
bool parse_rfc2616(const char *s, struct tm *t)
191
return parse_rfc850(s, t) || parse_asctime(s, t) || parse_rfc1123(s, t) || parse_rfc1123_alt(s,t);
194
int parse_time(const char *time_str, time_t *time)
198
if (!parse_rfc2616(time_str, &tm))
207
* calculate the sha1 value of a given msg and key
209
void calc_hmac_sha1(const char *key, int key_len,
210
const char *msg, int msg_len, char *dest)
211
/* destination should be CEPH_CRYPTO_HMACSHA1_DIGESTSIZE bytes long */
213
HMACSHA1 hmac((const unsigned char *)key, key_len);
214
hmac.Update((const unsigned char *)msg, msg_len);
215
hmac.Final((unsigned char *)dest);
217
char hex_str[(CEPH_CRYPTO_HMACSHA1_DIGESTSIZE * 2) + 1];
218
buf_to_hex((unsigned char *)dest, CEPH_CRYPTO_HMACSHA1_DIGESTSIZE, hex_str);
221
int gen_rand_base64(CephContext *cct, char *dest, int size) /* size should be the required string size + 1 */
224
char tmp_dest[size + 4]; /* so that there's space for the extra '=' characters, and some */
227
ret = get_random_bytes(buf, sizeof(buf));
229
lderr(cct) << "cannot get random bytes: " << cpp_strerror(-ret) << dendl;
233
ret = ceph_armor(tmp_dest, &tmp_dest[sizeof(tmp_dest)],
234
(const char *)buf, ((const char *)buf) + ((size - 1) * 3 + 4 - 1) / 4);
236
lderr(cct) << "ceph_armor failed" << dendl;
239
tmp_dest[ret] = '\0';
240
memcpy(dest, tmp_dest, size);
246
static const char alphanum_upper_table[]="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
248
int gen_rand_alphanumeric_upper(CephContext *cct, char *dest, int size) /* size should be the required string size + 1 */
250
int ret = get_random_bytes(dest, size);
252
lderr(cct) << "cannot get random bytes: " << cpp_strerror(-ret) << dendl;
257
for (i=0; i<size - 1; i++) {
258
int pos = (unsigned)dest[i];
259
dest[i] = alphanum_upper_table[pos % (sizeof(alphanum_upper_table) - 1)];
267
// this is basically a modified base64 charset, url friendly
268
static const char alphanum_table[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
270
int gen_rand_alphanumeric(CephContext *cct, char *dest, int size) /* size should be the required string size + 1 */
272
int ret = get_random_bytes(dest, size);
274
lderr(cct) << "cannot get random bytes: " << cpp_strerror(-ret) << dendl;
279
for (i=0; i<size - 1; i++) {
280
int pos = (unsigned)dest[i];
281
dest[i] = alphanum_table[pos & 63];
290
int delim_pos = str.find('=');
298
name = str.substr(0, delim_pos);
299
val = str.substr(delim_pos + 1);
309
if (str[pos] == '?') pos++;
312
fpos = str.find('&', pos);
317
string substr, nameval;
318
substr = str.substr(pos, fpos - pos);
319
url_decode(substr, nameval);
321
int ret = nv.parse();
323
string& name = nv.get_name();
324
string& val = nv.get_val();
327
if ((name.compare("acl") == 0) ||
328
(name.compare("location") == 0) ||
329
(name.compare("uploads") == 0) ||
330
(name.compare("partNumber") == 0) ||
331
(name.compare("uploadId") == 0) ||
332
(name.compare("versionId") == 0) ||
333
(name.compare("torrent") == 0)) {
334
sub_resources[name] = val;
335
} else if (name[0] == 'r') { // root of all evil
336
if ((name.compare("response-content-type") == 0) ||
337
(name.compare("response-content-language") == 0) ||
338
(name.compare("response-expires") == 0) ||
339
(name.compare("response-cache-control") == 0) ||
340
(name.compare("response-content-disposition") == 0) ||
341
(name.compare("response-content-encoding") == 0)) {
342
sub_resources[name] = val;
343
has_resp_modifier = true;
354
string& XMLArgs::get(string& name, bool *exists)
356
map<string, string>::iterator iter;
357
iter = val_map.find(name);
358
bool e = (iter != val_map.end());
366
string& XMLArgs::get(const char *name, bool *exists)
369
return get(s, exists);
372
bool verify_bucket_permission(struct req_state *s, int perm)
377
if ((perm & (int)s->perm_mask) != perm)
380
if (s->bucket_acl->verify_permission(s->user.user_id, perm, perm))
383
if (perm & (RGW_PERM_READ | RGW_PERM_READ_ACP))
384
perm |= RGW_PERM_READ_OBJS;
385
if (perm & RGW_PERM_WRITE)
386
perm |= RGW_PERM_WRITE_OBJS;
388
return s->bucket_acl->verify_permission(s->user.user_id, perm, perm);
391
bool verify_object_permission(struct req_state *s, int perm)
396
bool ret = s->object_acl->verify_permission(s->user.user_id, s->perm_mask, perm);
400
if (!s->cct->_conf->rgw_enforce_swift_acls)
403
if ((perm & (int)s->perm_mask) != perm)
407
if (perm & (RGW_PERM_READ | RGW_PERM_READ_ACP))
408
swift_perm |= RGW_PERM_READ_OBJS;
409
if (perm & RGW_PERM_WRITE)
410
swift_perm |= RGW_PERM_WRITE_OBJS;
414
/* we already verified the user mask above, so we pass swift_perm as the mask here,
415
otherwise the mask might not cover the swift permissions bits */
416
return s->bucket_acl->verify_permission(s->user.user_id, swift_perm, swift_perm);
419
static char hex_to_num(char c)
421
static char table[256];
422
static bool initialized = false;
426
memset(table, -1, sizeof(table));
428
for (i = '0'; i<='9'; i++)
430
for (i = 'A'; i<='F'; i++)
431
table[i] = i - 'A' + 0xa;
432
for (i = 'a'; i<='f'; i++)
433
table[i] = i - 'a' + 0xa;
435
return table[(int)c];
438
bool url_decode(string& src_str, string& dest_str)
440
const char *src = src_str.c_str();
441
char dest[src_str.size()];
448
dest[pos++] = *src++;
457
char c1 = hex_to_num(*src++);
463
c1 = hex_to_num(*src++);