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 9e1ce6808c9c..60364be2b690 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 fe70fa717909..1cafcfb04dd7 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 7c798f36019b..9cbbd860aace 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 e7b23d08b17e..129934a9fdb2 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 */