From 9629180e594f74233731f863d515b4ee9c8e84fd 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 (cherry picked from commit 8f8bb1d2b743a2681d40cd8f25dedd0f221b49c7) Conflicts: src/rgw/rgw_bucket.cc: renamed to driver/rados/rgw_bucket.cc src/rgw/rgw_bucket.h: using namespace std --- src/rgw/rgw_bucket.cc | 8 ++++++-- src/rgw/rgw_bucket.h | 7 ++++--- src/rgw/rgw_rest_s3.cc | 16 ++++++++++------ 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/src/rgw/rgw_bucket.cc b/src/rgw/rgw_bucket.cc index 89cc597730cb8..3d680514af112 100644 --- a/src/rgw/rgw_bucket.cc +++ b/src/rgw/rgw_bucket.cc @@ -130,8 +130,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) { @@ -142,10 +142,14 @@ 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_bucket.h b/src/rgw/rgw_bucket.h index 7ab2dfc81bdcd..f9c6aa1945a4e 100644 --- a/src/rgw/rgw_bucket.h +++ b/src/rgw/rgw_bucket.h @@ -49,9 +49,10 @@ extern int rgw_bucket_parse_bucket_key(CephContext *cct, const 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 string& bucket, - const string& auth_tenant, - string &tenant_name, 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 declaration of RGWRados::check_filter_t. diff --git a/src/rgw/rgw_rest_s3.cc b/src/rgw/rgw_rest_s3.cc index 1ed672fa6f993..bf4b91002f108 100644 --- a/src/rgw/rgw_rest_s3.cc +++ b/src/rgw/rgw_rest_s3.cc @@ -4694,9 +4694,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(); } @@ -4704,7 +4706,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; @@ -4721,8 +4722,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