From 8f8bb1d2b743a2681d40cd8f25dedd0f221b49c7 Mon Sep 17 00:00:00 2001 From: Casey Bodley Date: Tue, 22 Nov 2022 13:36:40 -0500 Subject: [PATCH] rgw: rgw_parse_url_bucket() rejects empty bucket names after 'tenant:' fail with ERR_INVALID_BUCKET_NAME if rgw_parse_url_bucket() finds a 'tenant:' but empty bucket name Fixes: https://tracker.ceph.com/issues/58111 Signed-off-by: Casey Bodley --- src/rgw/driver/rados/rgw_bucket.h | 7 ++++--- src/rgw/rgw_bucket.cc | 8 ++++++-- src/rgw/rgw_rest_s3.cc | 16 ++++++++++------ 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/src/rgw/driver/rados/rgw_bucket.h b/src/rgw/driver/rados/rgw_bucket.h index 636a1f2f6c029..6d5c73ce97ac9 100644 --- a/src/rgw/driver/rados/rgw_bucket.h +++ b/src/rgw/driver/rados/rgw_bucket.h @@ -45,9 +45,10 @@ extern int rgw_bucket_parse_bucket_key(CephContext *cct, const std::string& key, extern std::string rgw_make_bucket_entry_name(const std::string& tenant_name, const std::string& bucket_name); -extern void rgw_parse_url_bucket(const std::string& bucket, - const std::string& auth_tenant, - std::string &tenant_name, std::string &bucket_name); +[[nodiscard]] int rgw_parse_url_bucket(const std::string& bucket, + const std::string& auth_tenant, + std::string &tenant_name, + std::string &bucket_name); // this is used as a filter to RGWRados::cls_bucket_list_ordered; it // conforms to the type RGWBucketListNameFilter diff --git a/src/rgw/rgw_bucket.cc b/src/rgw/rgw_bucket.cc index 7d8dba72bd8c6..528c6f4bd3d58 100644 --- a/src/rgw/rgw_bucket.cc +++ b/src/rgw/rgw_bucket.cc @@ -101,8 +101,8 @@ std::string rgw_make_bucket_entry_name(const std::string& tenant_name, * Tenants are separated from buckets in URLs by a colon in S3. * This function is not to be used on Swift URLs, not even for COPY arguments. */ -void rgw_parse_url_bucket(const string &bucket, const string& auth_tenant, - string &tenant_name, string &bucket_name) { +int rgw_parse_url_bucket(const string &bucket, const string& auth_tenant, + string &tenant_name, string &bucket_name) { int pos = bucket.find(':'); if (pos >= 0) { @@ -113,9 +113,13 @@ void rgw_parse_url_bucket(const string &bucket, const string& auth_tenant, */ tenant_name = bucket.substr(0, pos); bucket_name = bucket.substr(pos + 1); + if (bucket_name.empty()) { + return -ERR_INVALID_BUCKET_NAME; + } } else { tenant_name = auth_tenant; bucket_name = bucket; } + return 0; } diff --git a/src/rgw/rgw_rest_s3.cc b/src/rgw/rgw_rest_s3.cc index 6a2ec4a0b9f6e..e5cb2d8063306 100644 --- a/src/rgw/rgw_rest_s3.cc +++ b/src/rgw/rgw_rest_s3.cc @@ -4873,9 +4873,11 @@ int RGWHandler_REST_S3::postauth_init(optional_yield y) { struct req_init_state *t = &s->init_state; - rgw_parse_url_bucket(t->url_bucket, s->user->get_tenant(), - s->bucket_tenant, s->bucket_name); - + int ret = rgw_parse_url_bucket(t->url_bucket, s->user->get_tenant(), + s->bucket_tenant, s->bucket_name); + if (ret) { + return ret; + } if (s->auth.identity->get_identity_type() == TYPE_ROLE) { s->bucket_tenant = s->auth.identity->get_role_tenant(); } @@ -4883,7 +4885,6 @@ int RGWHandler_REST_S3::postauth_init(optional_yield y) ldpp_dout(s, 10) << "s->object=" << s->object << " s->bucket=" << rgw_make_bucket_entry_name(s->bucket_tenant, s->bucket_name) << dendl; - int ret; ret = rgw_validate_tenant_name(s->bucket_tenant); if (ret) return ret; @@ -4900,8 +4901,11 @@ int RGWHandler_REST_S3::postauth_init(optional_yield y) } else { auth_tenant = s->user->get_tenant(); } - rgw_parse_url_bucket(t->src_bucket, auth_tenant, - s->src_tenant_name, s->src_bucket_name); + ret = rgw_parse_url_bucket(t->src_bucket, auth_tenant, + s->src_tenant_name, s->src_bucket_name); + if (ret) { + return ret; + } ret = rgw_validate_tenant_name(s->src_tenant_name); if (ret) return ret; -- 2.39.5