Skip to content

Commit

Permalink
add s3 checksum crc32 and sha1
Browse files Browse the repository at this point in the history
packaged in RGWChecksum class

Signed-off-by: tongzhiwei <tongzhiwei_yewu.cmss.chinamobile.com>
  • Loading branch information
imtzw committed Feb 15, 2023
1 parent 2d15020 commit 4949261
Show file tree
Hide file tree
Showing 12 changed files with 462 additions and 4 deletions.
1 change: 1 addition & 0 deletions src/rgw/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ set(librgw_common_srcs
rgw_bucket_encryption.cc
rgw_tracer.cc
rgw_lua_background.cc
rgw_checksum.cc
driver/rados/cls_fifo_legacy.cc
driver/rados/rgw_bucket.cc
driver/rados/rgw_bucket_sync.cc
Expand Down
6 changes: 6 additions & 0 deletions src/rgw/driver/rados/rgw_putobj_processor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,12 @@ int MultipartObjectProcessor::complete(size_t accounted_size,
info.modified = real_clock::now();
info.manifest = manifest;

if (attrs.find(RGW_ATTR_PREFIX RGW_ATTR_CHECKSUM_CRC32) != attrs.end()){
info.checksum_crc32_str = attrs[RGW_ATTR_PREFIX RGW_ATTR_CHECKSUM_CRC32].to_str();
}
if (attrs.find(RGW_ATTR_PREFIX RGW_ATTR_CHECKSUM_SHA1) != attrs.end()){
info.checksum_sha1_str = attrs[RGW_ATTR_PREFIX RGW_ATTR_CHECKSUM_SHA1].to_str();
}
bool compressed;
r = rgw_compression_info_from_attrset(attrs, compressed, info.cs_info);
if (r < 0) {
Expand Down
10 changes: 10 additions & 0 deletions src/rgw/driver/rados/rgw_sal_rados.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <sstream>
#include <boost/algorithm/string.hpp>
#include <boost/process.hpp>
#include <boost/crc.hpp>

#include "common/Clock.h"
#include "common/errno.h"
Expand Down Expand Up @@ -2545,6 +2546,13 @@ int RadosMultipartUpload::complete(const DoutPrefixProvider *dpp,
uint64_t min_part_size = cct->_conf->rgw_multipart_min_part_size;
auto etags_iter = part_etags.begin();
rgw::sal::Attrs attrs = target_obj->get_attrs();
RGWChecksum checksum;
string target_checksum_algorithm;
if (attrs.find(RGW_ATTR_PREFIX RGW_ATTR_CHECKSUM_ALGORITHM) != attrs.end()) {
target_checksum_algorithm = attrs[RGW_ATTR_PREFIX RGW_ATTR_CHECKSUM_ALGORITHM].to_str();
}
checksum.enable_by_name(target_checksum_algorithm);
checksum.reset();

do {
ret = list_parts(dpp, cct, max_parts, marker, &marker, &truncated);
Expand Down Expand Up @@ -2658,6 +2666,8 @@ int RadosMultipartUpload::complete(const DoutPrefixProvider *dpp,
etag_bl.append(etag);

attrs[RGW_ATTR_ETAG] = etag_bl;
checksum.final();
checksum.add_checksum_attr(attrs, parts.size());

if (compressed) {
// write compression attribute to full object
Expand Down
15 changes: 13 additions & 2 deletions src/rgw/rgw_basic_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -245,25 +245,29 @@ struct RGWUploadPartInfo {
uint64_t size;
uint64_t accounted_size{0};
std::string etag;
std::string checksum_crc32_str;
std::string checksum_sha1_str;
ceph::real_time modified;
RGWObjManifest manifest;
RGWCompressionInfo cs_info;

RGWUploadPartInfo() : num(0), size(0) {}

void encode(bufferlist& bl) const {
ENCODE_START(4, 2, bl);
ENCODE_START(5, 2, bl);
encode(num, bl);
encode(size, bl);
encode(etag, bl);
encode(modified, bl);
encode(manifest, bl);
encode(cs_info, bl);
encode(accounted_size, bl);
encode(checksum_crc32_str, bl);
encode(checksum_sha1_str, bl);
ENCODE_FINISH(bl);
}
void decode(bufferlist::const_iterator& bl) {
DECODE_START_LEGACY_COMPAT_LEN(4, 2, 2, bl);
DECODE_START_LEGACY_COMPAT_LEN(5, 2, 2, bl);
decode(num, bl);
decode(size, bl);
decode(etag, bl);
Expand All @@ -276,6 +280,13 @@ struct RGWUploadPartInfo {
} else {
accounted_size = size;
}
if (struct_v >= 5) {
decode(checksum_crc32_str, bl);
decode(checksum_sha1_str, bl);
}else{
checksum_crc32_str = "";
checksum_sha1_str = "";
}
DECODE_FINISH(bl);
}
void dump(Formatter *f) const;
Expand Down
216 changes: 216 additions & 0 deletions src/rgw/rgw_checksum.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
#include "rgw_common.h"
using namespace std;

bool RGWChecksum::is_supplied_checksum(const string &s) {
if (s == RGW_ATTR_CHECKSUM_CRC32)
return true;
if (s == RGW_ATTR_CHECKSUM_SHA1)
return true;
return false;
}

int RGWChecksum::enable_supplied() {
int enabled_num = 0;
if (supplied_crc32_b64 != nullptr) {
set_enable_crc32();
enabled_num += 1;
}
if (supplied_sha1_b64 != nullptr) {
set_enable_sha1();
enabled_num += 1;
}
if (enabled_num > 1) {
return -EINVAL;
}
return 0;
}

int RGWChecksum::check_specified_algorithm() {
if (specified_algorithm == nullptr) {
return 0;
}
bool valid_algorithm = false;
if (strcmp(specified_algorithm, "CRC32") == 0) {
if (!need_calc_crc32)
return -EINVAL;
valid_algorithm = true;
}
if (strcmp(specified_algorithm, "SHA1") == 0) {
if (!need_calc_sha1)
return -EINVAL;
valid_algorithm = true;
}
if (!valid_algorithm)
return -EINVAL;
return 0;
}

void RGWChecksum::disable_all() {
disable_crc32 = true;
disable_sha1 = true;
need_calc_crc32 = false;
need_calc_sha1 = false;
}

int RGWChecksum::supplied_unarmor() {
if (need_calc_crc32) {
if (strlen(supplied_crc32_b64) > RGW_CHECKSUM_CRC32_ARMORED_SIZE)
return -ERR_INVALID_DIGEST;
int ret = ceph_unarmor(
supplied_crc32_bin,
&supplied_crc32_bin[RGW_CHECKSUM_CRC32_DIGESTSIZE + 1],
supplied_crc32_b64, supplied_crc32_b64 + strlen(supplied_crc32_b64));
if (ret != RGW_CHECKSUM_CRC32_DIGESTSIZE) {
return -ERR_INVALID_DIGEST;
}
}
if (need_calc_sha1) {
if (strlen(supplied_sha1_b64) > RGW_CHECKSUM_SHA1_ARMORED_SIZE)
return -ERR_INVALID_DIGEST;
int ret = ceph_unarmor(
supplied_sha1_bin, &supplied_sha1_bin[RGW_CHECKSUM_SHA1_DIGESTSIZE + 1],
supplied_sha1_b64, supplied_sha1_b64 + strlen(supplied_sha1_b64));
if (ret != RGW_CHECKSUM_SHA1_DIGESTSIZE) {
return -ERR_INVALID_DIGEST;
}
}
return 0;
}

void RGWChecksum::reset() {
hash_crc32.reset();
hash_sha1.Restart();
}

void RGWChecksum::update(bufferlist &data) {
if (need_calc_crc32) {
hash_crc32.process_bytes((const unsigned char *)data.c_str(),
data.length());
}
if (need_calc_sha1) {
hash_sha1.Update((const unsigned char *)data.c_str(), data.length());
}
}

void RGWChecksum::update(string &str) {
char buf[400];
if (need_calc_crc32) {
hex_to_buf(str.c_str(), buf, RGW_CHECKSUM_CRC32_DIGESTSIZE);
hash_crc32.process_bytes((const unsigned char *)&buf,
RGW_CHECKSUM_CRC32_DIGESTSIZE);
}
if (need_calc_sha1) {
hex_to_buf(str.c_str(), buf, RGW_CHECKSUM_SHA1_DIGESTSIZE);
hash_sha1.Update((const unsigned char *)&buf, RGW_CHECKSUM_SHA1_DIGESTSIZE);
}
}

void RGWChecksum::final() {
if (need_calc_crc32) {
u_int32_t final_crc32 = hash_crc32();
snprintf(final_crc32_str, RGW_CHECKSUM_CRC32_DIGESTSIZE * 2 + 1, "%08x",
final_crc32);
hex_to_buf(final_crc32_str, final_crc32_bin, RGW_CHECKSUM_CRC32_DIGESTSIZE);
}
if (need_calc_sha1) {
hash_sha1.Final((unsigned char *)final_sha1_bin);
buf_to_hex((unsigned char *)final_sha1_bin, RGW_CHECKSUM_SHA1_DIGESTSIZE,
final_sha1_str);
}
}

int RGWChecksum::check() {
if (need_calc_crc32) {
return strncmp(final_crc32_bin, supplied_crc32_bin,
RGW_CHECKSUM_CRC32_DIGESTSIZE);
}
if (need_calc_sha1) {
return strncmp(final_sha1_bin, supplied_sha1_bin,
RGW_CHECKSUM_SHA1_DIGESTSIZE);
}
return 0;
}

void RGWChecksum::add_checksum_attr(map<string, bufferlist> &out_attrs) {
if (need_calc_crc32) {
bufferlist &bl = out_attrs[RGW_ATTR_PREFIX RGW_ATTR_CHECKSUM_CRC32];
bl.clear();
bl.append(final_crc32_str, RGW_CHECKSUM_CRC32_DIGESTSIZE * 2);
}
if (need_calc_sha1) {
bufferlist &bl = out_attrs[RGW_ATTR_PREFIX RGW_ATTR_CHECKSUM_SHA1];
bl.clear();
bl.append(final_sha1_str, RGW_CHECKSUM_SHA1_DIGESTSIZE * 2);
}
}

void RGWChecksum::add_checksum_attr(map<string, bufferlist> &out_attrs,
long long partNumber) {
char buf[20];
snprintf(buf, sizeof(buf), "-%lld", partNumber);
if (need_calc_crc32) {
bufferlist &bl = out_attrs[RGW_ATTR_PREFIX RGW_ATTR_CHECKSUM_CRC32];
bl.clear();
bl.append(final_crc32_str, RGW_CHECKSUM_CRC32_DIGESTSIZE * 2);
bl.append(buf, strlen(buf));
}
if (need_calc_sha1) {
bufferlist &bl = out_attrs[RGW_ATTR_PREFIX RGW_ATTR_CHECKSUM_SHA1];
bl.clear();
bl.append(final_sha1_str, RGW_CHECKSUM_SHA1_DIGESTSIZE * 2);
bl.append(buf, strlen(buf));
}
}

void RGWChecksum::resp_armor(bufferlist &data, string &outstr) {
if (need_calc_crc32) {
hex_to_buf(data.c_str(), resp_crc32_bin, RGW_CHECKSUM_CRC32_DIGESTSIZE);
const char *mult_sign = strchr(data.c_str(), '-');
ceph_armor(resp_crc32_b64,
resp_crc32_b64 + RGW_CHECKSUM_CRC32_ARMORED_SIZE + 1,
resp_crc32_bin, resp_crc32_bin + RGW_CHECKSUM_CRC32_DIGESTSIZE);
char *p_crc32_b64 = resp_crc32_b64 + RGW_CHECKSUM_CRC32_ARMORED_SIZE;
if (mult_sign) {
while (mult_sign - data.c_str() < data.length()) {
*p_crc32_b64 = *mult_sign;
p_crc32_b64++, mult_sign++;
}
}
*p_crc32_b64 = '\0';
outstr = string(resp_crc32_b64);
}
if (need_calc_sha1) {
hex_to_buf(data.c_str(), resp_sha1_bin, RGW_CHECKSUM_SHA1_DIGESTSIZE);
const char *mult_sign = strchr(data.c_str(), '-');
ceph_armor(resp_sha1_b64,
resp_sha1_b64 + RGW_CHECKSUM_SHA1_ARMORED_SIZE + 1,
resp_sha1_bin, resp_sha1_bin + RGW_CHECKSUM_SHA1_DIGESTSIZE);
char *p_sha1_b64 = resp_sha1_b64 + RGW_CHECKSUM_SHA1_ARMORED_SIZE;
if (mult_sign) {
while (mult_sign - data.c_str() < data.length()) {
*p_sha1_b64 = *mult_sign;
p_sha1_b64++, mult_sign++;
}
}
*p_sha1_b64 = '\0';
outstr = string(resp_sha1_b64);
}
}

int RGWChecksum::check_upload_header(std::map<std::string, bufferlist> *attrs) {
if (attrs && attrs->find(RGW_ATTR_CHECKSUM_ALGORITHM) != attrs->end()) {
std::string target_checksum_algorithm =
(*attrs)[RGW_ATTR_CHECKSUM_ALGORITHM].to_str();
if (std::strcmp(target_checksum_algorithm.c_str(), "CRC32") == 0) {
if (!supplied_crc32_b64) {
return -1;
}
}
if (std::strcmp(target_checksum_algorithm.c_str(), "SHA1") == 0) {
if (!supplied_sha1_b64) {
return -1;
}
}
}
return 0;
}

0 comments on commit 4949261

Please sign in to comment.