2010-03-26 23:29:11 +00:00
|
|
|
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
|
|
|
|
// vim: ts=8 sw=2 smarttab
|
|
|
|
/*
|
|
|
|
* Ceph - scalable distributed file system
|
|
|
|
*
|
|
|
|
* Copyright (C) 2004-2009 Sage Weil <sage@newdream.net>
|
|
|
|
*
|
|
|
|
* This is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License version 2.1, as published by the Free Software
|
|
|
|
* Foundation. See file COPYING.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2010-06-12 13:04:11 +00:00
|
|
|
#ifndef CEPH_RGW_COMMON_H
|
|
|
|
#define CEPH_RGW_COMMON_H
|
2009-07-18 00:49:59 +00:00
|
|
|
|
2011-03-08 21:49:56 +00:00
|
|
|
#include "common/ceph_crypto.h"
|
2011-05-10 21:08:42 +00:00
|
|
|
#include "common/debug.h"
|
2009-07-18 00:49:59 +00:00
|
|
|
#include "fcgiapp.h"
|
|
|
|
|
2011-06-07 21:13:59 +00:00
|
|
|
#include <errno.h>
|
2010-12-03 22:45:59 +00:00
|
|
|
#include <string.h>
|
2009-07-18 00:49:59 +00:00
|
|
|
#include <string>
|
|
|
|
#include <map>
|
|
|
|
#include "include/types.h"
|
2011-03-09 00:49:49 +00:00
|
|
|
#include "include/utime.h"
|
2009-07-18 00:49:59 +00:00
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
2011-03-16 17:57:48 +00:00
|
|
|
using ceph::crypto::MD5;
|
|
|
|
|
2011-04-13 17:38:11 +00:00
|
|
|
extern string rgw_root_bucket;
|
|
|
|
|
|
|
|
#define RGW_ROOT_BUCKET ".rgw"
|
|
|
|
|
2011-07-01 00:13:42 +00:00
|
|
|
#define RGW_CONTROL_BUCKET ".rgw.control"
|
|
|
|
|
2009-08-07 17:46:29 +00:00
|
|
|
#define RGW_ATTR_PREFIX "user.rgw."
|
2009-07-18 00:49:59 +00:00
|
|
|
|
2009-08-07 17:46:29 +00:00
|
|
|
#define RGW_ATTR_ACL RGW_ATTR_PREFIX "acl"
|
|
|
|
#define RGW_ATTR_ETAG RGW_ATTR_PREFIX "etag"
|
2010-03-11 22:49:27 +00:00
|
|
|
#define RGW_ATTR_BUCKETS RGW_ATTR_PREFIX "buckets"
|
2009-08-07 17:46:29 +00:00
|
|
|
#define RGW_ATTR_META_PREFIX RGW_ATTR_PREFIX "x-amz-meta-"
|
|
|
|
#define RGW_ATTR_CONTENT_TYPE RGW_ATTR_PREFIX "content_type"
|
2009-07-18 00:49:59 +00:00
|
|
|
|
2011-02-28 23:32:05 +00:00
|
|
|
#define RGW_BUCKETS_OBJ_PREFIX ".buckets"
|
|
|
|
|
2011-06-16 23:53:38 +00:00
|
|
|
#define USER_INFO_VER 7
|
2009-07-18 00:49:59 +00:00
|
|
|
|
2011-06-21 00:09:27 +00:00
|
|
|
#define RGW_MAX_CHUNK_SIZE (512*1024)
|
|
|
|
#define RGW_MAX_PENDING_CHUNKS 16
|
2010-07-19 23:50:43 +00:00
|
|
|
|
2010-07-28 16:48:33 +00:00
|
|
|
#define RGW_LOG_BEGIN "RADOS S3 Gateway:"
|
2011-06-07 17:38:54 +00:00
|
|
|
#define RGW_LOG(x) pdout(x, g_conf->rgw_log)
|
2011-06-23 22:26:08 +00:00
|
|
|
#define LRGW_LOG(cct, x) lpdout(cct, x, cct->_conf->rgw_log)
|
2010-07-28 16:48:33 +00:00
|
|
|
|
2011-02-16 01:30:07 +00:00
|
|
|
#define RGW_FORMAT_XML 1
|
|
|
|
#define RGW_FORMAT_JSON 2
|
|
|
|
|
2011-03-23 23:50:21 +00:00
|
|
|
#define RGW_REST_OPENSTACK 0x1
|
|
|
|
#define RGW_REST_OPENSTACK_AUTH 0x2
|
|
|
|
|
2011-06-17 16:26:32 +00:00
|
|
|
#define RGW_SUSPENDED_USER_AUID (uint64_t)-2
|
2011-06-16 23:53:38 +00:00
|
|
|
|
2011-03-09 00:49:49 +00:00
|
|
|
#define CGI_PRINTF(state, format, ...) do { \
|
|
|
|
int __ret = FCGX_FPrintF(state->fcgx->out, format, __VA_ARGS__); \
|
|
|
|
if (state->header_ended) \
|
2011-04-29 23:14:22 +00:00
|
|
|
state->bytes_sent += __ret; \
|
2011-02-19 00:19:43 +00:00
|
|
|
printf(">" format, __VA_ARGS__); \
|
2011-02-16 01:30:07 +00:00
|
|
|
} while (0)
|
|
|
|
|
2011-04-29 23:14:22 +00:00
|
|
|
#define CGI_PutStr(state, buf, len) do { \
|
|
|
|
FCGX_PutStr(buf, len, state->fcgx->out); \
|
|
|
|
if (state->header_ended) \
|
|
|
|
state->bytes_sent += len; \
|
|
|
|
} while (0)
|
2011-02-16 01:30:07 +00:00
|
|
|
|
2011-04-30 00:17:23 +00:00
|
|
|
#define CGI_GetStr(state, buf, buf_len, olen) do { \
|
|
|
|
olen = FCGX_GetStr(buf, buf_len, state->fcgx->in); \
|
|
|
|
state->bytes_received += olen; \
|
|
|
|
} while (0)
|
|
|
|
|
2011-04-13 20:29:24 +00:00
|
|
|
#define ERR_INVALID_BUCKET_NAME 2000
|
|
|
|
#define ERR_INVALID_OBJECT_NAME 2001
|
|
|
|
#define ERR_NO_SUCH_BUCKET 2002
|
|
|
|
#define ERR_METHOD_NOT_ALLOWED 2003
|
2011-04-14 23:14:48 +00:00
|
|
|
#define ERR_INVALID_DIGEST 2004
|
2011-04-18 19:54:02 +00:00
|
|
|
#define ERR_BAD_DIGEST 2005
|
|
|
|
#define ERR_UNRESOLVABLE_EMAIL 2006
|
2011-06-03 21:02:51 +00:00
|
|
|
#define ERR_INVALID_PART 2007
|
|
|
|
#define ERR_INVALID_PART_ORDER 2008
|
|
|
|
#define ERR_NO_SUCH_UPLOAD 2009
|
2011-04-13 15:45:43 +00:00
|
|
|
|
2011-06-16 23:53:38 +00:00
|
|
|
#define ERR_USER_SUSPENDED 2100
|
|
|
|
|
2009-08-07 17:46:29 +00:00
|
|
|
typedef void *RGWAccessHandle;
|
2009-07-18 00:49:59 +00:00
|
|
|
|
2011-05-27 21:22:55 +00:00
|
|
|
/* size should be the required string size + 1 */
|
|
|
|
extern int gen_rand_base64(char *dest, int size);
|
|
|
|
extern int gen_rand_alphanumeric(char *dest, int size);
|
|
|
|
extern int gen_rand_alphanumeric_upper(char *dest, int size);
|
|
|
|
|
2010-03-11 22:49:27 +00:00
|
|
|
/** Store error returns for output at a different point in the program */
|
2009-08-07 17:46:29 +00:00
|
|
|
struct rgw_err {
|
2011-04-14 23:14:48 +00:00
|
|
|
rgw_err();
|
2011-04-15 17:52:14 +00:00
|
|
|
rgw_err(int http, const std::string &s3);
|
2011-04-14 23:14:48 +00:00
|
|
|
void clear();
|
|
|
|
bool is_clear() const;
|
2011-04-15 18:15:11 +00:00
|
|
|
bool is_err() const;
|
2011-04-14 23:14:48 +00:00
|
|
|
friend std::ostream& operator<<(std::ostream& oss, const rgw_err &err);
|
|
|
|
|
2011-04-15 17:52:14 +00:00
|
|
|
int http_ret;
|
2011-05-17 11:15:10 +00:00
|
|
|
int ret;
|
2011-04-15 17:52:14 +00:00
|
|
|
std::string s3_code;
|
2011-04-14 23:14:48 +00:00
|
|
|
std::string message;
|
2009-07-18 00:49:59 +00:00
|
|
|
};
|
|
|
|
|
2010-03-11 22:49:27 +00:00
|
|
|
/* Helper class used for XMLArgs parsing */
|
2009-07-18 00:49:59 +00:00
|
|
|
class NameVal
|
|
|
|
{
|
|
|
|
string str;
|
|
|
|
string name;
|
|
|
|
string val;
|
|
|
|
public:
|
|
|
|
NameVal(string nv) : str(nv) {}
|
|
|
|
|
|
|
|
int parse();
|
|
|
|
|
|
|
|
string& get_name() { return name; }
|
|
|
|
string& get_val() { return val; }
|
|
|
|
};
|
|
|
|
|
2010-03-11 22:49:27 +00:00
|
|
|
/** Stores the XML arguments associated with the HTTP request in req_state*/
|
2009-07-18 00:49:59 +00:00
|
|
|
class XMLArgs
|
|
|
|
{
|
|
|
|
string str, empty_str;
|
|
|
|
map<string, string> val_map;
|
2011-05-27 20:35:47 +00:00
|
|
|
map<string, string> sub_resources;
|
2009-07-18 00:49:59 +00:00
|
|
|
public:
|
|
|
|
XMLArgs() {}
|
|
|
|
XMLArgs(string s) : str(s) {}
|
2010-03-11 22:49:27 +00:00
|
|
|
/** Set the arguments; as received */
|
2011-05-27 20:35:47 +00:00
|
|
|
void set(string s) { val_map.clear(); sub_resources.clear(); str = s; }
|
2010-03-11 22:49:27 +00:00
|
|
|
/** parse the received arguments */
|
2009-07-18 00:49:59 +00:00
|
|
|
int parse();
|
2010-03-11 22:49:27 +00:00
|
|
|
/** Get the value for a specific argument parameter */
|
2009-07-18 00:49:59 +00:00
|
|
|
string& get(string& name);
|
|
|
|
string& get(const char *name);
|
2010-03-11 22:49:27 +00:00
|
|
|
/** see if a parameter is contained in this XMLArgs */
|
2009-07-18 00:49:59 +00:00
|
|
|
bool exists(const char *name) {
|
|
|
|
map<string, string>::iterator iter = val_map.find(name);
|
|
|
|
return (iter != val_map.end());
|
|
|
|
}
|
2011-05-27 20:35:47 +00:00
|
|
|
map<string, string>& get_sub_resources() { return sub_resources; }
|
2009-07-18 00:49:59 +00:00
|
|
|
};
|
|
|
|
|
2011-07-11 20:41:40 +00:00
|
|
|
class RGWConf;
|
|
|
|
|
|
|
|
class RGWEnv {
|
|
|
|
std::map<string, string> env_map;
|
|
|
|
public:
|
|
|
|
RGWConf *conf;
|
|
|
|
|
2011-07-11 21:26:16 +00:00
|
|
|
RGWEnv();
|
2011-07-11 20:41:40 +00:00
|
|
|
~RGWEnv();
|
|
|
|
void reinit(char **envp);
|
|
|
|
const char *get(const char *name, const char *def_val = NULL);
|
|
|
|
int get_int(const char *name, int def_val = 0);
|
2011-07-14 22:55:05 +00:00
|
|
|
bool get_bool(const char *name, bool def_val = 0);
|
2011-07-11 20:41:40 +00:00
|
|
|
size_t get_size(const char *name, size_t def_val = 0);
|
|
|
|
};
|
|
|
|
|
|
|
|
class RGWConf {
|
|
|
|
friend class RGWEnv;
|
|
|
|
protected:
|
|
|
|
void init(RGWEnv * env);
|
|
|
|
public:
|
|
|
|
RGWConf() :
|
2011-07-11 23:55:05 +00:00
|
|
|
max_cache_lru(10000),
|
2011-07-11 20:41:40 +00:00
|
|
|
log_level(0),
|
2011-07-11 23:55:05 +00:00
|
|
|
should_log(1) {}
|
2011-07-11 20:41:40 +00:00
|
|
|
|
|
|
|
size_t max_cache_lru;
|
|
|
|
int log_level;
|
|
|
|
int should_log;
|
|
|
|
};
|
|
|
|
|
|
|
|
extern RGWEnv rgw_env;
|
|
|
|
|
|
|
|
#define rgwconf rgw_env.conf
|
|
|
|
|
2009-07-18 00:49:59 +00:00
|
|
|
enum http_op {
|
|
|
|
OP_GET,
|
|
|
|
OP_PUT,
|
|
|
|
OP_DELETE,
|
|
|
|
OP_HEAD,
|
2011-05-26 22:18:48 +00:00
|
|
|
OP_POST,
|
2009-07-18 00:49:59 +00:00
|
|
|
OP_UNKNOWN,
|
|
|
|
};
|
|
|
|
|
|
|
|
struct fcgx_state {
|
|
|
|
FCGX_ParamArray envp;
|
|
|
|
FCGX_Stream *in;
|
|
|
|
FCGX_Stream *out;
|
|
|
|
FCGX_Stream *err;
|
|
|
|
};
|
|
|
|
|
2009-08-07 17:46:29 +00:00
|
|
|
class RGWAccessControlPolicy;
|
2009-07-18 00:49:59 +00:00
|
|
|
|
2011-05-20 22:15:48 +00:00
|
|
|
struct RGWAccessKey {
|
|
|
|
string id;
|
|
|
|
string key;
|
|
|
|
string subuser;
|
|
|
|
|
|
|
|
RGWAccessKey() {}
|
|
|
|
void encode(bufferlist& bl) const {
|
|
|
|
__u32 ver = 1;
|
|
|
|
::encode(ver, bl);
|
|
|
|
::encode(id, bl);
|
|
|
|
::encode(key, bl);
|
|
|
|
::encode(subuser, bl);
|
|
|
|
}
|
|
|
|
|
|
|
|
void decode(bufferlist::iterator& bl) {
|
|
|
|
__u32 ver;
|
|
|
|
::decode(ver, bl);
|
|
|
|
::decode(id, bl);
|
|
|
|
::decode(key, bl);
|
|
|
|
::decode(subuser, bl);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
WRITE_CLASS_ENCODER(RGWAccessKey);
|
|
|
|
|
|
|
|
struct RGWSubUser {
|
|
|
|
string name;
|
2011-05-23 22:12:48 +00:00
|
|
|
uint32_t perm_mask;
|
2011-05-20 22:15:48 +00:00
|
|
|
|
2011-05-23 22:12:48 +00:00
|
|
|
RGWSubUser() : perm_mask(0) {}
|
2011-05-20 22:15:48 +00:00
|
|
|
void encode(bufferlist& bl) const {
|
|
|
|
__u32 ver = 1;
|
|
|
|
::encode(ver, bl);
|
|
|
|
::encode(name, bl);
|
2011-05-23 22:12:48 +00:00
|
|
|
::encode(perm_mask, bl);
|
2011-05-20 22:15:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void decode(bufferlist::iterator& bl) {
|
|
|
|
__u32 ver;
|
|
|
|
::decode(ver, bl);
|
|
|
|
::decode(name, bl);
|
2011-05-23 22:12:48 +00:00
|
|
|
::decode(perm_mask, bl);
|
2011-05-20 22:15:48 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
WRITE_CLASS_ENCODER(RGWSubUser);
|
|
|
|
|
2009-07-18 00:49:59 +00:00
|
|
|
|
2009-08-07 17:46:29 +00:00
|
|
|
struct RGWUserInfo
|
2009-07-18 00:49:59 +00:00
|
|
|
{
|
2010-05-07 21:33:42 +00:00
|
|
|
uint64_t auid;
|
2009-07-18 00:49:59 +00:00
|
|
|
string user_id;
|
|
|
|
string display_name;
|
|
|
|
string user_email;
|
2011-02-14 21:23:27 +00:00
|
|
|
string openstack_name;
|
2011-03-22 18:32:31 +00:00
|
|
|
string openstack_key;
|
2011-05-20 22:15:48 +00:00
|
|
|
map<string, RGWAccessKey> access_keys;
|
|
|
|
map<string, RGWSubUser> subusers;
|
2011-06-16 23:53:38 +00:00
|
|
|
__u8 suspended;
|
2009-07-18 00:49:59 +00:00
|
|
|
|
2011-06-24 19:55:25 +00:00
|
|
|
RGWUserInfo() : auid(0), suspended(0) {}
|
2010-03-26 23:29:11 +00:00
|
|
|
|
2009-07-18 00:49:59 +00:00
|
|
|
void encode(bufferlist& bl) const {
|
|
|
|
__u32 ver = USER_INFO_VER;
|
|
|
|
::encode(ver, bl);
|
2010-03-26 23:29:11 +00:00
|
|
|
::encode(auid, bl);
|
2011-05-20 22:15:48 +00:00
|
|
|
string access_key;
|
|
|
|
string secret_key;
|
|
|
|
if (!access_keys.empty()) {
|
|
|
|
map<string, RGWAccessKey>::const_iterator iter = access_keys.begin();
|
|
|
|
const RGWAccessKey& k = iter->second;
|
|
|
|
access_key = k.id;
|
|
|
|
secret_key = k.key;
|
|
|
|
}
|
2011-04-16 00:20:44 +00:00
|
|
|
::encode(access_key, bl);
|
2009-07-18 00:49:59 +00:00
|
|
|
::encode(secret_key, bl);
|
|
|
|
::encode(display_name, bl);
|
|
|
|
::encode(user_email, bl);
|
2011-02-14 21:23:27 +00:00
|
|
|
::encode(openstack_name, bl);
|
2011-03-22 18:32:31 +00:00
|
|
|
::encode(openstack_key, bl);
|
2011-04-16 00:20:44 +00:00
|
|
|
::encode(user_id, bl);
|
2011-05-20 22:15:48 +00:00
|
|
|
::encode(access_keys, bl);
|
|
|
|
::encode(subusers, bl);
|
2011-06-16 23:53:38 +00:00
|
|
|
::encode(suspended, bl);
|
2009-07-18 00:49:59 +00:00
|
|
|
}
|
|
|
|
void decode(bufferlist::iterator& bl) {
|
|
|
|
__u32 ver;
|
|
|
|
::decode(ver, bl);
|
2010-03-26 23:29:11 +00:00
|
|
|
if (ver >= 2) ::decode(auid, bl);
|
|
|
|
else auid = CEPH_AUTH_UID_DEFAULT;
|
2011-05-20 22:15:48 +00:00
|
|
|
string access_key;
|
|
|
|
string secret_key;
|
2011-04-16 00:20:44 +00:00
|
|
|
::decode(access_key, bl);
|
2009-07-18 00:49:59 +00:00
|
|
|
::decode(secret_key, bl);
|
2011-05-20 22:15:48 +00:00
|
|
|
if (ver < 6) {
|
|
|
|
RGWAccessKey k;
|
|
|
|
k.id = access_key;
|
|
|
|
k.key = secret_key;
|
|
|
|
access_keys[access_key] = k;
|
|
|
|
}
|
2009-07-18 00:49:59 +00:00
|
|
|
::decode(display_name, bl);
|
|
|
|
::decode(user_email, bl);
|
2011-02-14 21:23:27 +00:00
|
|
|
if (ver >= 3) ::decode(openstack_name, bl);
|
2011-03-22 18:32:31 +00:00
|
|
|
if (ver >= 4) ::decode(openstack_key, bl);
|
2011-04-16 00:20:44 +00:00
|
|
|
if (ver >= 5)
|
|
|
|
::decode(user_id, bl);
|
|
|
|
else
|
|
|
|
user_id = access_key;
|
2011-05-20 22:15:48 +00:00
|
|
|
if (ver >= 6) {
|
|
|
|
::decode(access_keys, bl);
|
|
|
|
::decode(subusers, bl);
|
|
|
|
}
|
2011-06-16 23:53:38 +00:00
|
|
|
suspended = 0;
|
|
|
|
if (ver >= 7) {
|
|
|
|
::decode(suspended, bl);
|
|
|
|
}
|
2009-07-18 00:49:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void clear() {
|
|
|
|
user_id.clear();
|
|
|
|
display_name.clear();
|
|
|
|
user_email.clear();
|
2010-03-26 23:29:11 +00:00
|
|
|
auid = CEPH_AUTH_UID_DEFAULT;
|
2011-05-20 22:15:48 +00:00
|
|
|
access_keys.clear();
|
2011-06-16 23:53:38 +00:00
|
|
|
suspended = 0;
|
2009-07-18 00:49:59 +00:00
|
|
|
}
|
|
|
|
};
|
2009-08-07 17:46:29 +00:00
|
|
|
WRITE_CLASS_ENCODER(RGWUserInfo)
|
2009-07-18 00:49:59 +00:00
|
|
|
|
2011-06-13 22:27:38 +00:00
|
|
|
struct RGWPoolInfo
|
|
|
|
{
|
|
|
|
string bucket;
|
|
|
|
string owner;
|
|
|
|
|
|
|
|
void encode(bufferlist& bl) const {
|
|
|
|
__u32 ver = 1;
|
|
|
|
::encode(ver, bl);
|
|
|
|
::encode(bucket, bl);
|
|
|
|
::encode(owner, bl);
|
|
|
|
}
|
|
|
|
void decode(bufferlist::iterator& bl) {
|
|
|
|
__u32 ver;
|
|
|
|
::decode(ver, bl);
|
|
|
|
::decode(bucket, bl);
|
|
|
|
::decode(owner, bl);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
WRITE_CLASS_ENCODER(RGWPoolInfo)
|
|
|
|
|
2011-02-16 01:30:07 +00:00
|
|
|
struct req_state;
|
|
|
|
|
|
|
|
class RGWFormatter {
|
|
|
|
protected:
|
2011-03-17 21:31:30 +00:00
|
|
|
char *buf;
|
|
|
|
int len;
|
|
|
|
int max_len;
|
2011-02-16 01:30:07 +00:00
|
|
|
|
|
|
|
virtual void formatter_init() = 0;
|
|
|
|
public:
|
2011-03-17 21:31:30 +00:00
|
|
|
RGWFormatter() : buf(NULL), len(0), max_len(0) {}
|
2011-03-16 17:45:43 +00:00
|
|
|
virtual ~RGWFormatter() {}
|
2011-06-13 22:27:38 +00:00
|
|
|
void init() {
|
2011-03-17 21:31:30 +00:00
|
|
|
if (buf)
|
|
|
|
free(buf);
|
|
|
|
buf = NULL;
|
|
|
|
len = 0;
|
|
|
|
max_len = 0;
|
2011-02-16 01:30:07 +00:00
|
|
|
formatter_init();
|
|
|
|
}
|
2011-06-13 22:27:38 +00:00
|
|
|
void reset();
|
2011-03-17 21:31:30 +00:00
|
|
|
void write_data(const char *fmt, ...);
|
2011-06-13 22:27:38 +00:00
|
|
|
virtual void flush(struct req_state *s);
|
|
|
|
virtual void flush(ostream& os);
|
2011-03-17 21:31:30 +00:00
|
|
|
virtual int get_len() { return (len ? len - 1 : 0); } // don't include null termination in length
|
2011-02-16 01:30:07 +00:00
|
|
|
virtual void open_array_section(const char *name) = 0;
|
|
|
|
virtual void open_obj_section(const char *name) = 0;
|
|
|
|
virtual void close_section(const char *name) = 0;
|
|
|
|
virtual void dump_value_int(const char *name, const char *fmt, ...) = 0;
|
|
|
|
virtual void dump_value_str(const char *name, const char *fmt, ...) = 0;
|
|
|
|
};
|
|
|
|
|
2010-03-11 22:49:27 +00:00
|
|
|
/** Store all the state necessary to complete and respond to an HTTP request*/
|
2009-07-18 00:49:59 +00:00
|
|
|
struct req_state {
|
|
|
|
struct fcgx_state *fcgx;
|
|
|
|
http_op op;
|
|
|
|
bool content_started;
|
2011-02-16 01:30:07 +00:00
|
|
|
int format;
|
|
|
|
RGWFormatter *formatter;
|
2009-07-18 00:49:59 +00:00
|
|
|
const char *path_name;
|
|
|
|
string path_name_url;
|
|
|
|
const char *host;
|
|
|
|
const char *method;
|
|
|
|
const char *query;
|
|
|
|
const char *length;
|
|
|
|
const char *content_type;
|
2009-08-07 17:46:29 +00:00
|
|
|
struct rgw_err err;
|
2010-09-27 16:37:07 +00:00
|
|
|
bool expect_cont;
|
2011-03-09 00:49:49 +00:00
|
|
|
bool header_ended;
|
|
|
|
uint64_t bytes_sent; // bytes sent as a response, excluding header
|
2011-04-30 00:17:23 +00:00
|
|
|
uint64_t bytes_received; // data received
|
2011-04-29 23:14:22 +00:00
|
|
|
uint64_t obj_size;
|
2011-03-10 18:01:24 +00:00
|
|
|
bool should_log;
|
2011-05-23 22:12:48 +00:00
|
|
|
uint32_t perm_mask;
|
2009-07-18 00:49:59 +00:00
|
|
|
|
|
|
|
XMLArgs args;
|
|
|
|
|
|
|
|
const char *bucket;
|
|
|
|
const char *object;
|
|
|
|
|
|
|
|
const char *host_bucket;
|
|
|
|
|
|
|
|
string bucket_str;
|
|
|
|
string object_str;
|
|
|
|
|
|
|
|
map<string, string> x_amz_map;
|
|
|
|
|
|
|
|
vector<pair<string, string> > x_amz_meta;
|
|
|
|
|
2009-08-07 17:46:29 +00:00
|
|
|
RGWUserInfo user;
|
|
|
|
RGWAccessControlPolicy *acl;
|
2009-07-18 00:49:59 +00:00
|
|
|
|
2009-07-20 23:41:25 +00:00
|
|
|
string canned_acl;
|
|
|
|
const char *copy_source;
|
|
|
|
const char *http_auth;
|
|
|
|
|
2011-02-12 01:18:24 +00:00
|
|
|
int prot_flags;
|
|
|
|
|
2011-07-11 20:41:40 +00:00
|
|
|
const char *os_auth_token;
|
2011-02-14 21:23:27 +00:00
|
|
|
char *os_user;
|
|
|
|
char *os_groups;
|
2011-02-12 01:18:24 +00:00
|
|
|
|
2011-03-09 00:49:49 +00:00
|
|
|
utime_t time;
|
|
|
|
|
2011-06-13 22:27:38 +00:00
|
|
|
int pool_id;
|
|
|
|
|
2011-07-14 22:29:36 +00:00
|
|
|
req_state();
|
|
|
|
~req_state();
|
2009-07-18 00:49:59 +00:00
|
|
|
};
|
|
|
|
|
2010-03-11 22:49:27 +00:00
|
|
|
/** Store basic data on an object */
|
2009-08-07 17:46:29 +00:00
|
|
|
struct RGWObjEnt {
|
2009-07-18 00:49:59 +00:00
|
|
|
std::string name;
|
2011-06-10 22:01:04 +00:00
|
|
|
std::string owner;
|
|
|
|
std::string owner_display_name;
|
2009-07-18 00:49:59 +00:00
|
|
|
size_t size;
|
|
|
|
time_t mtime;
|
2011-03-08 21:49:56 +00:00
|
|
|
// two md5 digests and a terminator
|
2011-03-23 22:23:57 +00:00
|
|
|
char etag[CEPH_CRYPTO_MD5_DIGESTSIZE * 2 + 1];
|
2011-03-23 23:50:21 +00:00
|
|
|
string content_type;
|
2011-06-16 20:26:19 +00:00
|
|
|
|
|
|
|
void clear() { // not clearing etag
|
|
|
|
name="";
|
|
|
|
size = 0;
|
|
|
|
mtime = 0;
|
|
|
|
content_type="";
|
|
|
|
}
|
2009-07-18 00:49:59 +00:00
|
|
|
};
|
|
|
|
|
2011-03-03 22:14:19 +00:00
|
|
|
/** Store basic data on an object */
|
|
|
|
struct RGWBucketEnt {
|
|
|
|
std::string name;
|
|
|
|
size_t size;
|
|
|
|
time_t mtime;
|
2011-03-23 22:23:57 +00:00
|
|
|
char etag[CEPH_CRYPTO_MD5_DIGESTSIZE * 2 + 1];
|
2011-03-03 22:14:19 +00:00
|
|
|
uint64_t count;
|
|
|
|
|
|
|
|
void encode(bufferlist& bl) const {
|
|
|
|
__u8 struct_v = 2;
|
|
|
|
::encode(struct_v, bl);
|
|
|
|
uint64_t s = size;
|
|
|
|
__u32 mt = mtime;
|
|
|
|
::encode(name, bl);
|
|
|
|
::encode(s, bl);
|
|
|
|
::encode(mt, bl);
|
|
|
|
::encode(count, bl);
|
|
|
|
}
|
|
|
|
void decode(bufferlist::iterator& bl) {
|
|
|
|
__u8 struct_v;
|
|
|
|
::decode(struct_v, bl);
|
|
|
|
__u32 mt;
|
|
|
|
uint64_t s;
|
|
|
|
::decode(name, bl);
|
|
|
|
::decode(s, bl);
|
|
|
|
::decode(mt, bl);
|
|
|
|
size = s;
|
|
|
|
mtime = mt;
|
|
|
|
if (struct_v >= 2)
|
|
|
|
::decode(count, bl);
|
|
|
|
}
|
2011-03-04 21:57:03 +00:00
|
|
|
void clear() {
|
|
|
|
name="";
|
|
|
|
size = 0;
|
|
|
|
mtime = 0;
|
|
|
|
memset(etag, 0, sizeof(etag));
|
|
|
|
count = 0;
|
|
|
|
}
|
2011-03-03 22:14:19 +00:00
|
|
|
};
|
|
|
|
WRITE_CLASS_ENCODER(RGWBucketEnt)
|
|
|
|
|
2011-06-02 17:28:24 +00:00
|
|
|
struct RGWUploadPartInfo {
|
|
|
|
uint32_t num;
|
|
|
|
uint64_t size;
|
|
|
|
string etag;
|
2011-06-02 20:45:20 +00:00
|
|
|
utime_t modified;
|
2011-06-02 17:28:24 +00:00
|
|
|
|
|
|
|
void encode(bufferlist& bl) const {
|
|
|
|
__u8 struct_v = 1;
|
|
|
|
::encode(struct_v, bl);
|
|
|
|
::encode(num, bl);
|
|
|
|
::encode(size, bl);
|
|
|
|
::encode(etag, bl);
|
2011-06-02 20:45:20 +00:00
|
|
|
::encode(modified, bl);
|
2011-06-02 17:28:24 +00:00
|
|
|
}
|
|
|
|
void decode(bufferlist::iterator& bl) {
|
|
|
|
__u8 struct_v;
|
|
|
|
::decode(struct_v, bl);
|
|
|
|
::decode(num, bl);
|
|
|
|
::decode(size, bl);
|
|
|
|
::decode(etag, bl);
|
2011-06-02 20:45:20 +00:00
|
|
|
::decode(modified, bl);
|
2011-06-02 17:28:24 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
WRITE_CLASS_ENCODER(RGWUploadPartInfo)
|
|
|
|
|
2011-06-08 19:32:50 +00:00
|
|
|
class rgw_obj {
|
2011-06-09 20:25:46 +00:00
|
|
|
std::string orig_obj;
|
|
|
|
std::string orig_key;
|
2011-06-08 19:32:50 +00:00
|
|
|
public:
|
|
|
|
std::string bucket;
|
2011-06-08 20:10:01 +00:00
|
|
|
std::string key;
|
2011-06-09 20:25:46 +00:00
|
|
|
std::string ns;
|
|
|
|
std::string object;
|
2011-06-08 19:32:50 +00:00
|
|
|
|
|
|
|
rgw_obj() {}
|
2011-06-08 20:10:01 +00:00
|
|
|
rgw_obj(std::string& b, std::string& o) {
|
|
|
|
init(b, o);
|
|
|
|
}
|
|
|
|
rgw_obj(std::string& b, std::string& o, std::string& k) {
|
|
|
|
init(b, o, k);
|
|
|
|
}
|
2011-06-09 20:25:46 +00:00
|
|
|
rgw_obj(std::string& b, std::string& o, std::string& k, std::string& n) {
|
|
|
|
init(b, o, k, n);
|
|
|
|
}
|
|
|
|
void init(std::string& b, std::string& o, std::string& k, std::string& n) {
|
|
|
|
bucket = b;
|
|
|
|
set_ns(n);
|
|
|
|
set_obj(o);
|
|
|
|
set_key(k);
|
|
|
|
}
|
2011-06-08 20:10:01 +00:00
|
|
|
void init(std::string& b, std::string& o, std::string& k) {
|
|
|
|
bucket = b;
|
2011-06-09 20:25:46 +00:00
|
|
|
set_obj(o);
|
|
|
|
set_key(k);
|
2011-06-08 20:10:01 +00:00
|
|
|
}
|
2011-06-08 19:32:50 +00:00
|
|
|
void init(std::string& b, std::string& o) {
|
|
|
|
bucket = b;
|
2011-06-09 20:25:46 +00:00
|
|
|
set_obj(o);
|
|
|
|
orig_key = key = "";
|
|
|
|
}
|
|
|
|
int set_ns(const char *n) {
|
|
|
|
if (!n)
|
|
|
|
return -EINVAL;
|
|
|
|
string ns_str(n);
|
|
|
|
return set_ns(ns_str);
|
|
|
|
}
|
|
|
|
int set_ns(string& n) {
|
|
|
|
if (n[0] == '_')
|
|
|
|
return -EINVAL;
|
|
|
|
ns = n;
|
|
|
|
set_obj(orig_obj);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void set_key(string& k) {
|
|
|
|
orig_key = k;
|
|
|
|
if (k.compare(object) == 0)
|
|
|
|
key = "";
|
|
|
|
else
|
|
|
|
key = k;
|
|
|
|
}
|
|
|
|
|
|
|
|
void set_obj(string& o) {
|
|
|
|
orig_obj = o;
|
|
|
|
if (ns.empty()) {
|
|
|
|
if (o.empty())
|
|
|
|
return;
|
|
|
|
if (o.size() < 1 || o[0] != '_') {
|
|
|
|
object = o;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
object = "__";
|
|
|
|
object.append(o);
|
|
|
|
} else {
|
|
|
|
object = "_";
|
|
|
|
object.append(ns);
|
|
|
|
object.append("_");
|
|
|
|
object.append(o);
|
|
|
|
}
|
|
|
|
set_key(orig_key);
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool translate_raw_obj(string& obj, string& ns) {
|
|
|
|
if (ns.empty()) {
|
|
|
|
if (obj[0] != '_')
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if (obj.size() >= 2 && obj[1] == '_') {
|
|
|
|
obj = obj.substr(1);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (obj[0] != '_' || obj.size() < 3) // for namespace, min size would be 3: _x_
|
|
|
|
return false;
|
|
|
|
|
|
|
|
int pos = obj.find('_', 1);
|
|
|
|
if (pos <= 1) // if it starts with __, it's not in our namespace
|
|
|
|
return false;
|
|
|
|
|
|
|
|
string obj_ns = obj.substr(1, pos - 1);
|
|
|
|
if (obj_ns.compare(ns) != 0)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
obj = obj.substr(pos + 1);
|
|
|
|
return true;
|
2011-06-08 19:32:50 +00:00
|
|
|
}
|
2011-07-01 00:13:42 +00:00
|
|
|
|
|
|
|
void encode(bufferlist& bl) const {
|
|
|
|
__u8 struct_v = 1;
|
|
|
|
::encode(struct_v, bl);
|
|
|
|
::encode(bucket, bl);
|
|
|
|
::encode(key, bl);
|
|
|
|
::encode(ns, bl);
|
|
|
|
::encode(object, bl);
|
|
|
|
}
|
|
|
|
void decode(bufferlist::iterator& bl) {
|
|
|
|
__u8 struct_v;
|
|
|
|
::decode(struct_v, bl);
|
|
|
|
::decode(bucket, bl);
|
|
|
|
::decode(key, bl);
|
|
|
|
::decode(ns, bl);
|
|
|
|
::decode(object, bl);
|
|
|
|
}
|
2011-06-08 19:32:50 +00:00
|
|
|
};
|
2011-07-01 00:13:42 +00:00
|
|
|
WRITE_CLASS_ENCODER(rgw_obj)
|
2011-06-08 19:32:50 +00:00
|
|
|
|
2011-06-24 19:55:25 +00:00
|
|
|
inline ostream& operator<<(ostream& out, const rgw_obj o) {
|
2011-06-27 19:20:22 +00:00
|
|
|
return out << o.bucket << ":" << o.object;
|
2011-06-24 19:55:25 +00:00
|
|
|
}
|
|
|
|
|
2009-07-20 23:41:25 +00:00
|
|
|
static inline void buf_to_hex(const unsigned char *buf, int len, char *str)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
str[0] = '\0';
|
|
|
|
for (i = 0; i < len; i++) {
|
|
|
|
sprintf(&str[i*2], "%02x", (int)buf[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-06-07 21:13:59 +00:00
|
|
|
static inline int hexdigit(char c)
|
|
|
|
{
|
|
|
|
if (c >= '0' && c <= '9')
|
|
|
|
return (c - '0');
|
|
|
|
c = toupper(c);
|
|
|
|
if (c >= 'A' && c <= 'F')
|
|
|
|
return c - 'A' + 0xa;
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int hex_to_buf(const char *hex, char *buf, int len)
|
|
|
|
{
|
|
|
|
int i = 0;
|
|
|
|
const char *p = hex;
|
|
|
|
while (*p) {
|
|
|
|
if (i >= len)
|
|
|
|
return -EINVAL;
|
|
|
|
buf[i] = 0;
|
|
|
|
int d = hexdigit(*p);
|
|
|
|
if (d < 0)
|
|
|
|
return d;
|
|
|
|
buf[i] = d << 4;
|
|
|
|
p++;
|
|
|
|
if (!*p)
|
|
|
|
return -EINVAL;
|
|
|
|
d = hexdigit(*p);
|
|
|
|
if (d < 0)
|
|
|
|
return -d;
|
|
|
|
buf[i] += d;
|
|
|
|
i++;
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
2011-03-10 18:01:24 +00:00
|
|
|
static inline int rgw_str_to_bool(const char *s, int def_val)
|
|
|
|
{
|
|
|
|
if (!s)
|
|
|
|
return def_val;
|
|
|
|
|
|
|
|
return (strcasecmp(s, "on") == 0 ||
|
|
|
|
strcasecmp(s, "yes") == 0 ||
|
2011-03-24 21:24:11 +00:00
|
|
|
strcasecmp(s, "1") == 0);
|
2011-03-10 18:01:24 +00:00
|
|
|
}
|
|
|
|
|
2011-06-24 21:50:01 +00:00
|
|
|
static inline void append_rand_alpha(string& src, string& dest, int len)
|
|
|
|
{
|
|
|
|
dest = src;
|
|
|
|
char buf[len + 1];
|
|
|
|
gen_rand_alphanumeric(buf, len);
|
|
|
|
dest.append("_");
|
|
|
|
dest.append(buf);
|
|
|
|
}
|
|
|
|
|
2010-03-11 22:49:27 +00:00
|
|
|
/** */
|
2009-07-18 00:49:59 +00:00
|
|
|
extern int parse_time(const char *time_str, time_t *time);
|
2010-03-11 22:49:27 +00:00
|
|
|
/** Check if a user has a permission on that ACL */
|
2011-05-23 22:12:48 +00:00
|
|
|
extern bool verify_permission(RGWAccessControlPolicy *policy, string& uid, int user_perm_mask, int perm);
|
2010-03-11 22:49:27 +00:00
|
|
|
/** Check if the req_state's user has the necessary permissions
|
|
|
|
* to do the requested action */
|
2009-07-20 23:41:25 +00:00
|
|
|
extern bool verify_permission(struct req_state *s, int perm);
|
2010-03-11 22:49:27 +00:00
|
|
|
/** Convert an input URL into a sane object name
|
|
|
|
* by converting %-escaped strings into characters, etc*/
|
2009-07-20 23:41:25 +00:00
|
|
|
extern bool url_decode(string& src_str, string& dest_str);
|
2009-07-18 00:49:59 +00:00
|
|
|
|
2011-03-24 05:42:02 +00:00
|
|
|
extern void calc_hmac_sha1(const char *key, int key_len,
|
|
|
|
const char *msg, int msg_len, char *dest);
|
|
|
|
/* destination should be CEPH_CRYPTO_HMACSHA1_DIGESTSIZE bytes long */
|
|
|
|
|
2009-07-18 00:49:59 +00:00
|
|
|
#endif
|