~ubuntu-branches/ubuntu/raring/ceph/raring

« back to all changes in this revision

Viewing changes to .pc/extra-byte-for-null.patch/src/rgw/rgw_common.cc

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2012-09-26 13:28:15 UTC
  • Revision ID: package-import@ubuntu.com-20120926132815-mqknhlfbqvzutm0s
Tags: 0.48.2-0ubuntu2
* Fix crash in radosgw on armhf architecture (LP: #1049582):
  - debian/patches/extra-byte-for-null.patch: Cherry picked patch
    from upstream VCS. Thanks to Yehuda Sadeh for pointing to this
    fix.
* d/ceph.lintian-overrides: Added libcls_rgw.so.1.0.0 to binaries
  which are not stripped.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include <errno.h>
 
2
 
 
3
#include "rgw_common.h"
 
4
#include "rgw_acl.h"
 
5
 
 
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"
 
13
 
 
14
#include <sstream>
 
15
 
 
16
#define dout_subsys ceph_subsys_rgw
 
17
 
 
18
PerfCounters *perfcounter = NULL;
 
19
 
 
20
int rgw_perf_start(CephContext *cct)
 
21
{
 
22
  PerfCountersBuilder plb(cct, cct->_conf->name.to_str(), l_rgw_first, l_rgw_last);
 
23
 
 
24
  plb.add_u64_counter(l_rgw_req, "req");
 
25
  plb.add_u64_counter(l_rgw_failed_req, "failed_req");
 
26
 
 
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");
 
33
 
 
34
  plb.add_u64(l_rgw_qlen, "qlen");
 
35
  plb.add_u64(l_rgw_qactive, "qactive");
 
36
 
 
37
  plb.add_u64_counter(l_rgw_cache_hit, "cache_hit");
 
38
  plb.add_u64_counter(l_rgw_cache_miss, "cache_miss");
 
39
 
 
40
  perfcounter = plb.create_perf_counters();
 
41
  cct->get_perfcounters_collection()->add(perfcounter);
 
42
  return 0;
 
43
}
 
44
 
 
45
void rgw_perf_stop(CephContext *cct)
 
46
{
 
47
  assert(perfcounter);
 
48
  cct->get_perfcounters_collection()->remove(perfcounter);
 
49
  delete perfcounter;
 
50
}
 
51
 
 
52
using namespace ceph::crypto;
 
53
 
 
54
rgw_err::
 
55
rgw_err()
 
56
{
 
57
  clear();
 
58
}
 
59
 
 
60
rgw_err::
 
61
rgw_err(int http, const std::string& s3)
 
62
    : http_ret(http), s3_code(s3)
 
63
{
 
64
}
 
65
 
 
66
void rgw_err::
 
67
clear()
 
68
{
 
69
  http_ret = 200;
 
70
  ret = 0;
 
71
  s3_code.clear();
 
72
}
 
73
 
 
74
bool rgw_err::
 
75
is_clear() const
 
76
{
 
77
  return (http_ret == 200);
 
78
}
 
79
 
 
80
bool rgw_err::
 
81
is_err() const
 
82
{
 
83
  return !(http_ret >= 200 && http_ret <= 299);
 
84
}
 
85
 
 
86
 
 
87
req_state::req_state(CephContext *_cct, struct RGWEnv *e) : cct(_cct), os_auth_token(NULL), os_user(NULL), os_groups(NULL), env(e)
 
88
{
 
89
  enable_ops_log = env->conf->enable_ops_log;
 
90
  enable_usage_log = env->conf->enable_usage_log;
 
91
  content_started = false;
 
92
  format = 0;
 
93
  bucket_acl = NULL;
 
94
  object_acl = NULL;
 
95
  expect_cont = false;
 
96
 
 
97
  os_auth_token = NULL;
 
98
  os_user = NULL;
 
99
  os_groups = NULL;
 
100
  time = ceph_clock_now(cct);
 
101
  perm_mask = 0;
 
102
  content_length = 0;
 
103
  object = NULL;
 
104
  bucket_name = NULL;
 
105
  has_bad_meta = false;
 
106
  method = NULL;
 
107
  host_bucket = NULL;
 
108
}
 
109
 
 
110
req_state::~req_state() {
 
111
  delete formatter;
 
112
  delete bucket_acl;
 
113
  delete object_acl;
 
114
  free(os_user);
 
115
  free(os_groups);
 
116
  free((void *)object);
 
117
  free((void *)bucket_name);
 
118
}
 
119
 
 
120
std::ostream& operator<<(std::ostream& oss, const rgw_err &err)
 
121
{
 
122
  oss << "rgw_err(http_ret=" << err.http_ret << ", s3='" << err.s3_code << "') ";
 
123
  return oss;
 
124
}
 
125
 
 
126
static bool check_str_end(const char *s)
 
127
{
 
128
  if (!s)
 
129
    return false;
 
130
 
 
131
  while (*s) {
 
132
    if (!isspace(*s))
 
133
      return false;
 
134
    s++;
 
135
  }
 
136
  return true;
 
137
}
 
138
 
 
139
static bool check_gmt_end(const char *s)
 
140
{
 
141
  if (!s || !*s)
 
142
    return false;
 
143
 
 
144
  while (isspace(*s)) {
 
145
    ++s;
 
146
  }
 
147
 
 
148
  /* check for correct timezone */
 
149
  if ((strncmp(s, "GMT", 3) != 0) &&
 
150
      (strncmp(s, "UTC", 3) != 0)) {
 
151
    return false;
 
152
  }
 
153
 
 
154
  /* trailing space */
 
155
  s += 3;
 
156
  while (isspace(*s)) {
 
157
    ++s;
 
158
  }
 
159
  if (*s)
 
160
    return false;
 
161
 
 
162
  return true;
 
163
}
 
164
 
 
165
static bool parse_rfc850(const char *s, struct tm *t)
 
166
{
 
167
  memset(t, 0, sizeof(*t));
 
168
  return check_gmt_end(strptime(s, "%A, %d-%b-%y %H:%M:%S ", t));
 
169
}
 
170
 
 
171
static bool parse_asctime(const char *s, struct tm *t)
 
172
{
 
173
  memset(t, 0, sizeof(*t));
 
174
  return check_str_end(strptime(s, "%a %b %d %H:%M:%S %Y", t));
 
175
}
 
176
 
 
177
static bool parse_rfc1123(const char *s, struct tm *t)
 
178
{
 
179
  memset(t, 0, sizeof(*t));
 
180
  return check_gmt_end(strptime(s, "%a, %d %b %Y %H:%M:%S ", t));
 
181
}
 
182
 
 
183
static bool parse_rfc1123_alt(const char *s, struct tm *t)
 
184
{
 
185
  memset(t, 0, sizeof(*t));
 
186
  return check_str_end(strptime(s, "%a, %d %b %Y %H:%M:%S %z", t));
 
187
}
 
188
 
 
189
bool parse_rfc2616(const char *s, struct tm *t)
 
190
{
 
191
  return parse_rfc850(s, t) || parse_asctime(s, t) || parse_rfc1123(s, t) || parse_rfc1123_alt(s,t);
 
192
}
 
193
 
 
194
int parse_time(const char *time_str, time_t *time)
 
195
{
 
196
  struct tm tm;
 
197
 
 
198
  if (!parse_rfc2616(time_str, &tm))
 
199
    return -EINVAL;
 
200
 
 
201
  *time = timegm(&tm);
 
202
 
 
203
  return 0;
 
204
}
 
205
 
 
206
/*
 
207
 * calculate the sha1 value of a given msg and key
 
208
 */
 
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 */
 
212
{
 
213
  HMACSHA1 hmac((const unsigned char *)key, key_len);
 
214
  hmac.Update((const unsigned char *)msg, msg_len);
 
215
  hmac.Final((unsigned char *)dest);
 
216
  
 
217
  char hex_str[(CEPH_CRYPTO_HMACSHA1_DIGESTSIZE * 2) + 1];
 
218
  buf_to_hex((unsigned char *)dest, CEPH_CRYPTO_HMACSHA1_DIGESTSIZE, hex_str);
 
219
}
 
220
 
 
221
int gen_rand_base64(CephContext *cct, char *dest, int size) /* size should be the required string size + 1 */
 
222
{
 
223
  char buf[size];
 
224
  char tmp_dest[size + 4]; /* so that there's space for the extra '=' characters, and some */
 
225
  int ret;
 
226
 
 
227
  ret = get_random_bytes(buf, sizeof(buf));
 
228
  if (ret < 0) {
 
229
    lderr(cct) << "cannot get random bytes: " << cpp_strerror(-ret) << dendl;
 
230
    return -1;
 
231
  }
 
232
 
 
233
  ret = ceph_armor(tmp_dest, &tmp_dest[sizeof(tmp_dest)],
 
234
                   (const char *)buf, ((const char *)buf) + ((size - 1) * 3 + 4 - 1) / 4);
 
235
  if (ret < 0) {
 
236
    lderr(cct) << "ceph_armor failed" << dendl;
 
237
    return -1;
 
238
  }
 
239
  tmp_dest[ret] = '\0';
 
240
  memcpy(dest, tmp_dest, size);
 
241
  dest[size] = '\0';
 
242
 
 
243
  return 0;
 
244
}
 
245
 
 
246
static const char alphanum_upper_table[]="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
 
247
 
 
248
int gen_rand_alphanumeric_upper(CephContext *cct, char *dest, int size) /* size should be the required string size + 1 */
 
249
{
 
250
  int ret = get_random_bytes(dest, size);
 
251
  if (ret < 0) {
 
252
    lderr(cct) << "cannot get random bytes: " << cpp_strerror(-ret) << dendl;
 
253
    return -1;
 
254
  }
 
255
 
 
256
  int i;
 
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)];
 
260
  }
 
261
  dest[i] = '\0';
 
262
 
 
263
  return 0;
 
264
}
 
265
 
 
266
 
 
267
// this is basically a modified base64 charset, url friendly
 
268
static const char alphanum_table[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
 
269
 
 
270
int gen_rand_alphanumeric(CephContext *cct, char *dest, int size) /* size should be the required string size + 1 */
 
271
{
 
272
  int ret = get_random_bytes(dest, size);
 
273
  if (ret < 0) {
 
274
    lderr(cct) << "cannot get random bytes: " << cpp_strerror(-ret) << dendl;
 
275
    return -1;
 
276
  }
 
277
 
 
278
  int i;
 
279
  for (i=0; i<size - 1; i++) {
 
280
    int pos = (unsigned)dest[i];
 
281
    dest[i] = alphanum_table[pos & 63];
 
282
  }
 
283
  dest[i] = '\0';
 
284
 
 
285
  return 0;
 
286
}
 
287
 
 
288
int NameVal::parse()
 
289
{
 
290
  int delim_pos = str.find('=');
 
291
  int ret = 0;
 
292
 
 
293
  if (delim_pos < 0) {
 
294
    name = str;
 
295
    val = "";
 
296
    ret = 1;
 
297
  } else {
 
298
    name = str.substr(0, delim_pos);
 
299
    val = str.substr(delim_pos + 1);
 
300
  }
 
301
 
 
302
  return ret; 
 
303
}
 
304
 
 
305
int XMLArgs::parse()
 
306
{
 
307
  int pos = 0, fpos;
 
308
  bool end = false;
 
309
  if (str[pos] == '?') pos++;
 
310
 
 
311
  while (!end) {
 
312
    fpos = str.find('&', pos);
 
313
    if (fpos  < pos) {
 
314
       end = true;
 
315
       fpos = str.size(); 
 
316
    }
 
317
    string substr, nameval;
 
318
    substr = str.substr(pos, fpos - pos);
 
319
    url_decode(substr, nameval);
 
320
    NameVal nv(nameval);
 
321
    int ret = nv.parse();
 
322
    if (ret >= 0) {
 
323
      string& name = nv.get_name();
 
324
      string& val = nv.get_val();
 
325
      val_map[name] = val;
 
326
 
 
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;
 
344
        }
 
345
      }
 
346
    }
 
347
 
 
348
    pos = fpos + 1;  
 
349
  }
 
350
 
 
351
  return 0;
 
352
}
 
353
 
 
354
string& XMLArgs::get(string& name, bool *exists)
 
355
{
 
356
  map<string, string>::iterator iter;
 
357
  iter = val_map.find(name);
 
358
  bool e = (iter != val_map.end());
 
359
  if (exists)
 
360
    *exists = e;
 
361
  if (e)
 
362
    return iter->second;
 
363
  return empty_str;
 
364
}
 
365
 
 
366
string& XMLArgs::get(const char *name, bool *exists)
 
367
{
 
368
  string s(name);
 
369
  return get(s, exists);
 
370
}
 
371
 
 
372
bool verify_bucket_permission(struct req_state *s, int perm)
 
373
{
 
374
  if (!s->bucket_acl)
 
375
    return false;
 
376
 
 
377
  if ((perm & (int)s->perm_mask) != perm)
 
378
    return false;
 
379
 
 
380
  if (s->bucket_acl->verify_permission(s->user.user_id, perm, perm))
 
381
    return true;
 
382
 
 
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;
 
387
 
 
388
  return s->bucket_acl->verify_permission(s->user.user_id, perm, perm);
 
389
}
 
390
 
 
391
bool verify_object_permission(struct req_state *s, int perm)
 
392
{
 
393
  if (!s->object_acl)
 
394
    return false;
 
395
 
 
396
  bool ret = s->object_acl->verify_permission(s->user.user_id, s->perm_mask, perm);
 
397
  if (ret)
 
398
    return true;
 
399
 
 
400
  if (!s->cct->_conf->rgw_enforce_swift_acls)
 
401
    return ret;
 
402
 
 
403
  if ((perm & (int)s->perm_mask) != perm)
 
404
    return false;
 
405
 
 
406
  int swift_perm = 0;
 
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;
 
411
 
 
412
  if (!swift_perm)
 
413
    return false;
 
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);
 
417
}
 
418
 
 
419
static char hex_to_num(char c)
 
420
{
 
421
  static char table[256];
 
422
  static bool initialized = false;
 
423
 
 
424
 
 
425
  if (!initialized) {
 
426
    memset(table, -1, sizeof(table));
 
427
    int i;
 
428
    for (i = '0'; i<='9'; i++)
 
429
      table[i] = i - '0';
 
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;
 
434
  }
 
435
  return table[(int)c];
 
436
}
 
437
 
 
438
bool url_decode(string& src_str, string& dest_str)
 
439
{
 
440
  const char *src = src_str.c_str();
 
441
  char dest[src_str.size()];
 
442
  int pos = 0;
 
443
  char c;
 
444
 
 
445
  while (*src) {
 
446
    if (*src != '%') {
 
447
      if (*src != '+') {
 
448
        dest[pos++] = *src++;
 
449
      } else {
 
450
        dest[pos++] = ' ';
 
451
        ++src;
 
452
      }
 
453
    } else {
 
454
      src++;
 
455
      if (!*src)
 
456
        break;
 
457
      char c1 = hex_to_num(*src++);
 
458
      if (!*src)
 
459
        break;
 
460
      c = c1 << 4;
 
461
      if (c1 < 0)
 
462
        return false;
 
463
      c1 = hex_to_num(*src++);
 
464
      if (c1 < 0)
 
465
        return false;
 
466
      c |= c1;
 
467
      dest[pos++] = c;
 
468
    }
 
469
  }
 
470
  dest[pos] = 0;
 
471
  dest_str = dest;
 
472
 
 
473
  return true;
 
474
}