From: Matt Benjamin Date: Tue, 2 Feb 2016 14:38:51 +0000 (-0500) Subject: librgw: consolidate S3 bucket name validation X-Git-Tag: v10.1.0~382^2~6 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=2f706ef08411d6a395dba3ca9068cba7abb4baf7;p=ceph.git librgw: consolidate S3 bucket name validation There is more cleanup potential here, but it is intrusive, as the validators for bucket and object names have been factored through the handler inheritance hierarchy. This change just deletes the S3 validate_bucket_name for now, as that method was large. The corresponding object name validator was not defined in RGWHandler_REST_S3, so I've left it as is, for now. Signed-off-by: Matt Benjamin --- diff --git a/src/rgw/rgw_file.cc b/src/rgw/rgw_file.cc index 9e1ce6808c9..60364be2b69 100644 --- a/src/rgw/rgw_file.cc +++ b/src/rgw/rgw_file.cc @@ -704,46 +704,6 @@ int rgw_statfs(struct rgw_fs *rgw_fs, 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 -- create an empty regular file */ diff --git a/src/rgw/rgw_file.h b/src/rgw/rgw_file.h index fe70fa71790..1cafcfb04dd 100644 --- a/src/rgw/rgw_file.h +++ b/src/rgw/rgw_file.h @@ -1219,18 +1219,6 @@ public: }; /* RGWDeleteBucketRequest */ -static inline bool valid_s3_object_name(const string& name) { - if (name.size() > 1024) { - // Name too long - return false; - } - if (check_utf8(name.c_str(), name.size())) { - // Object names must be valid UTF-8. - return false; - } - return true; -} - /* put object */ diff --git a/src/rgw/rgw_rest_s3.cc b/src/rgw/rgw_rest_s3.cc index 7c798f36019..9cbbd860aac 100644 --- a/src/rgw/rgw_rest_s3.cc +++ b/src/rgw/rgw_rest_s3.cc @@ -2508,7 +2508,7 @@ int RGWHandler_REST_S3::postauth_init() ret = validate_tenant_name(s->bucket_tenant); if (ret) return ret; - ret = validate_bucket_name(s->bucket_name, relaxed_names); + ret = valid_s3_bucket_name(s->bucket_name, relaxed_names); if (ret) return ret; ret = validate_object_name(s->object.name); @@ -2521,55 +2521,30 @@ int RGWHandler_REST_S3::postauth_init() ret = validate_tenant_name(s->src_tenant_name); if (ret) return ret; - ret = validate_bucket_name(s->src_bucket_name, relaxed_names); + ret = valid_s3_bucket_name(s->src_bucket_name, relaxed_names); if (ret) return ret; } return 0; } -int RGWHandler_REST_S3::validate_bucket_name(const string& bucket, - bool relaxed_names) -{ - int ret = RGWHandler_REST::validate_bucket_name(bucket); - if (ret < 0) - return ret; - - if (bucket.size() == 0) - return 0; - - // bucket names must start with a number, letter, or underscore - if (!(isalpha(bucket[0]) || isdigit(bucket[0]))) { - if (!relaxed_names) - return -ERR_INVALID_BUCKET_NAME; - else if (!(bucket[0] == '_' || bucket[0] == '.' || bucket[0] == '-')) - return -ERR_INVALID_BUCKET_NAME; - } - - for (const char *s = bucket.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(bucket.c_str())) - return -ERR_INVALID_BUCKET_NAME; - - return 0; -} - int RGWHandler_REST_S3::init(RGWRados *store, struct req_state *s, - RGWClientIO *cio) + RGWClientIO *cio) { int ret; s->dialect = "s3"; + + ret = validate_tenant_name(s->bucket_tenant); + if (ret) + return ret; + bool relaxed_names = s->cct->_conf->rgw_relaxed_s3_bucket_names; + ret = valid_s3_bucket_name(s->bucket_name, relaxed_names); + if (ret) + return ret; + ret = validate_object_name(s->object.name); + if (ret) + return ret; const char *cacl = s->info.env->get("HTTP_X_AMZ_ACL"); if (cacl) diff --git a/src/rgw/rgw_rest_s3.h b/src/rgw/rgw_rest_s3.h index e7b23d08b17..129934a9fdb 100644 --- a/src/rgw/rgw_rest_s3.h +++ b/src/rgw/rgw_rest_s3.h @@ -416,11 +416,9 @@ public: RGWHandler_REST_S3() : RGWHandler_REST() {} virtual ~RGWHandler_REST_S3() {} - int validate_bucket_name(const string& bucket, bool relaxed_names); - int get_errordoc(const string& errordoc_key, string* error_content); + int validate_bucket_name(const string& bucket, bool relaxed_names) = delete; + int get_errordoc(const string& errordoc_key, string* error_content); - using RGWHandler_REST::validate_bucket_name; - virtual int init(RGWRados *store, struct req_state *s, RGWClientIO *cio); virtual int authorize() { return RGW_Auth_S3::authorize(store, s); @@ -530,4 +528,53 @@ static inline bool looks_like_ip_address(const char *bucket) return (num_periods == 3); } +static inline bool valid_s3_object_name(const string& name) { + if (name.size() > 1024) { + return false; + } + if (check_utf8(name.c_str(), name.size())) { + return false; + } + return true; +} + +static inline 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; +} + #endif /* CEPH_RGW_REST_S3_H */