return 0;
}
+/* XXX can't call these virtual methods from non-REST handler */
+static int valid_s3_bucket_name(const string& name, bool relaxed=false)
+{
+ // This function enforces Amazon's spec for bucket names.
+ // (The requirements, not the recommendations.)
+ int len = name.size();
+ if (len < 3) {
+ // Name too short
+ return -ERR_INVALID_BUCKET_NAME;
+ } else if (len > 255) {
+ // Name too long
+ return -ERR_INVALID_BUCKET_NAME;
+ }
+
+ // bucket names must start with a number, letter, or underscore
+ if (!(isalpha(name[0]) || isdigit(name[0]))) {
+ if (!relaxed)
+ return -ERR_INVALID_BUCKET_NAME;
+ else if (!(name[0] == '_' || name[0] == '.' || name[0] == '-'))
+ return -ERR_INVALID_BUCKET_NAME;
+ }
+
+ for (const char *s = name.c_str(); *s; ++s) {
+ char c = *s;
+ if (isdigit(c) || (c == '.'))
+ continue;
+ if (isalpha(c))
+ continue;
+ if ((c == '-') || (c == '_'))
+ continue;
+ // Invalid character
+ return -ERR_INVALID_BUCKET_NAME;
+ }
+
+ if (looks_like_ip_address(name.c_str()))
+ return -ERR_INVALID_BUCKET_NAME;
+
+ return 0;
+}
+
/*
generic create -- creates a regular file
*/
if (parent->is_root()) {
/* bucket */
- string uri = "/"; /* XXX get rid of URI some day soon */
- uri += name;
+ string bname{name};
+ /* enforce S3 name restrictions */
+ rc = valid_s3_bucket_name(bname, false /* relaxed */);
+ if (rc != 0)
+ return -EINVAL;
+ string uri = "/" + bname; /* XXX get rid of URI some day soon */
RGWCreateBucketRequest req(cct, fs->get_user(), uri);
rc = rgwlib.get_fe()->execute_req(&req);
rc2 = req.get_ret();
return 0;
}
-static bool looks_like_ip_address(const char *bucket)
-{
- int num_periods = 0;
- bool expect_period = false;
- for (const char *b = bucket; *b; ++b) {
- if (*b == '.') {
- if (!expect_period)
- return false;
- ++num_periods;
- if (num_periods > 3)
- return false;
- expect_period = false;
- }
- else if (isdigit(*b)) {
- expect_period = true;
- }
- else {
- return false;
- }
- }
- return (num_periods == 3);
-}
-
int RGWHandler_REST_S3::validate_bucket_name(const string& bucket,
- bool relaxed_names)
+ bool relaxed_names)
{
int ret = RGWHandler_REST::validate_bucket_name(bucket);
if (ret < 0)
// vim: ts=8 sw=2 smarttab
#ifndef CEPH_RGW_REST_S3_H
+
#define CEPH_RGW_REST_S3_H
#define TIME_BUF_SIZE 128
class RGWHandler_REST_Obj_S3Website;
-#endif
+static inline bool looks_like_ip_address(const char *bucket)
+{
+ int num_periods = 0;
+ bool expect_period = false;
+ for (const char *b = bucket; *b; ++b) {
+ if (*b == '.') {
+ if (!expect_period)
+ return false;
+ ++num_periods;
+ if (num_periods > 3)
+ return false;
+ expect_period = false;
+ }
+ else if (isdigit(*b)) {
+ expect_period = true;
+ }
+ else {
+ return false;
+ }
+ }
+ return (num_periods == 3);
+}
+
+#endif /* CEPH_RGW_REST_S3_H */