For non-ASCII object keys, raw UTF-8 bytes end up in the signed
x-amz-meta-rgwx-source-key header. Strict S3-compatible backends
normalize non-ASCII bytes when verifying SigV4, producing a signature
mismatch -> HTTP 403, surfaced in LC as -EACCES (-13).
url_encode() the value before signing. The header is write-only,
so no decode is needed.
Signed-off-by: Matthew N. Heler <matthew.heler@hotmail.com>
attrs["x-amz-meta-rgwx-source-mtime"] = buf;
attrs["x-amz-meta-rgwx-source-etag"] = obj_properties.etag;
- attrs["x-amz-meta-rgwx-source-key"] = rest_obj.key.name;
+ // url-encoded; decode the fields for restore if required
+ attrs["x-amz-meta-rgwx-source-key"] = url_encode(rest_obj.key.name);
if (!rest_obj.key.instance.empty()) {
- attrs["x-amz-meta-rgwx-source-version-id"] = rest_obj.key.instance;
+ attrs["x-amz-meta-rgwx-source-version-id"] = url_encode(rest_obj.key.instance);
}
for (const auto& a : attrs) {
ldpp_dout(dpp, 30) << "init_send_attrs attr[" << a.first << "] = " << a.second <<dendl;
new_attrs["x-amz-meta-rgwx-source-mtime"] = buf;
new_attrs["x-amz-meta-rgwx-source-etag"] = src_properties.etag;
- new_attrs["x-amz-meta-rgwx-source-key"] = rest_obj.key.name;
+ new_attrs["x-amz-meta-rgwx-source-key"] = url_encode(rest_obj.key.name);
if (!rest_obj.key.instance.empty()) {
- new_attrs["x-amz-meta-rgwx-source-version-id"] = rest_obj.key.instance;
+ new_attrs["x-amz-meta-rgwx-source-version-id"] = url_encode(rest_obj.key.instance);
}
}