#include "rgw_tools.h"
#include "rgw_coroutine.h"
#include "rgw_compression.h"
+#include "rgw_crypt.h"
#include "rgw_etag_verifier.h"
#include "rgw_worker.h"
#include "rgw_notify.h"
}
}
}
+
/* We need the manifest to recompute the ETag for verification */
iter = src_attrs.find(RGW_ATTR_MANIFEST);
if (iter != src_attrs.end()) {
manifest_bl = std::move(iter->second);
src_attrs.erase(iter);
+
+ // if the source object was encrypted, preserve the original object's
+ // part lengths
+ if (src_attrs.count(RGW_ATTR_CRYPT_MODE)) {
+ std::vector<size_t> parts_len;
+ int r = RGWGetObj_BlockDecrypt::read_manifest_parts(dpp, manifest_bl,
+ parts_len);
+ if (r < 0) {
+ ldpp_dout(dpp, 4) << "failed to read part lengths from the manifest" << dendl;
+ } else {
+ // store the encoded part lenghts in RGW_ATTR_CRYPT_PARTS
+ bufferlist parts_bl;
+ encode(parts_len, parts_bl);
+ src_attrs[RGW_ATTR_CRYPT_PARTS] = std::move(parts_bl);
+ }
+ }
}
// filter out olh attributes
#define RGW_ATTR_CRYPT_KEYSEL RGW_ATTR_CRYPT_PREFIX "keysel"
#define RGW_ATTR_CRYPT_CONTEXT RGW_ATTR_CRYPT_PREFIX "context"
#define RGW_ATTR_CRYPT_DATAKEY RGW_ATTR_CRYPT_PREFIX "datakey"
+#define RGW_ATTR_CRYPT_PARTS RGW_ATTR_CRYPT_PREFIX "part-lengths"
/* SSE-S3 Encryption Attributes */
#define RGW_ATTR_BUCKET_ENCRYPTION_PREFIX RGW_ATTR_PREFIX "sse-s3."
// in case of a multipart upload, we need to know the part lengths to
// correctly decrypt across part boundaries
std::vector<size_t> parts_len;
- res = RGWGetObj_BlockDecrypt::read_manifest_parts(this, *manifest_bl,
- parts_len);
- if (res < 0) {
- return res;
+
+ // for replicated objects, the original part lengths are preserved in an xattr
+ if (auto i = attrs.find(RGW_ATTR_CRYPT_PARTS); i != attrs.end()) {
+ try {
+ auto p = i->second.cbegin();
+ using ceph::decode;
+ decode(parts_len, p);
+ } catch (const buffer::error&) {
+ ldpp_dout(this, 1) << "failed to decode RGW_ATTR_CRYPT_PARTS" << dendl;
+ return -EIO;
+ }
+ } else {
+ // otherwise, we read the part lengths from the manifest
+ res = RGWGetObj_BlockDecrypt::read_manifest_parts(this, *manifest_bl,
+ parts_len);
+ if (res < 0) {
+ return res;
+ }
}
*filter = std::make_unique<RGWGetObj_BlockDecrypt>(
// in case of a multipart upload, we need to know the part lengths to
// correctly decrypt across part boundaries
std::vector<size_t> parts_len;
- res = RGWGetObj_BlockDecrypt::read_manifest_parts(this, *manifest_bl,
- parts_len);
- if (res < 0) {
- return res;
+
+ // for replicated objects, the original part lengths are preserved in an xattr
+ if (auto i = attrs.find(RGW_ATTR_CRYPT_PARTS); i != attrs.end()) {
+ try {
+ auto p = i->second.cbegin();
+ using ceph::decode;
+ decode(parts_len, p);
+ } catch (const buffer::error&) {
+ ldpp_dout(this, 1) << "failed to decode RGW_ATTR_CRYPT_PARTS" << dendl;
+ return -EIO;
+ }
+ } else {
+ // otherwise, we read the part lengths from the manifest
+ res = RGWGetObj_BlockDecrypt::read_manifest_parts(this, *manifest_bl,
+ parts_len);
+ if (res < 0) {
+ return res;
+ }
}
*filter = std::make_unique<RGWGetObj_BlockDecrypt>(