summaryrefslogtreecommitdiffstats
path: root/src/rgw/rgw_etag_verifier.h
blob: 563b1e8c78f8a0207b690d58a2a170c423393f80 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab ft=cpp

/*
 * RGW Etag Verifier is an RGW filter which enables the objects copied using
 * multisite sync to be verified using their ETag from source i.e. the MD5
 * checksum of the object is computed at the destination and is verified to be
 * identical to the ETag stored in the object HEAD at source cluster.
 * 
 * For MPU objects, a different filter named RGWMultipartEtagFilter is applied
 * which re-computes ETag using RGWObjManifest. This computes the ETag using the
 * same algorithm used at the source cluster i.e. MD5 sum of the individual ETag
 * on the MPU parts.
 */
#ifndef CEPH_RGW_ETAG_VERIFIER_H
#define CEPH_RGW_ETAG_VERIFIER_H

#include "rgw_putobj.h"
#include "rgw_op.h"
#include "common/static_ptr.h"

namespace rgw::putobj {

class ETagVerifier : public rgw::putobj::Pipe
{
protected:
  CephContext* cct;
  MD5 hash;
  string calculated_etag;

public:
  ETagVerifier(CephContext* cct_, rgw::putobj::DataProcessor *next)
    : Pipe(next), cct(cct_) {
      // Allow use of MD5 digest in FIPS mode for non-cryptographic purposes
      hash.SetFlags(EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
    }

  virtual void calculate_etag() = 0;
  string get_calculated_etag() { return calculated_etag;}

}; /* ETagVerifier */

class ETagVerifier_Atomic : public ETagVerifier
{
public:
  ETagVerifier_Atomic(CephContext* cct_, rgw::putobj::DataProcessor *next)
    : ETagVerifier(cct_, next) {}

  int process(bufferlist&& data, uint64_t logical_offset) override;
  void calculate_etag() override;

}; /* ETagVerifier_Atomic */

class ETagVerifier_MPU : public ETagVerifier
{
  std::vector<uint64_t> part_ofs;
  uint64_t cur_part_index{0}, next_part_index{1};
  MD5 mpu_etag_hash;
 
  void process_end_of_MPU_part();

public:
  ETagVerifier_MPU(CephContext* cct,
                             std::vector<uint64_t> part_ofs,
                             rgw::putobj::DataProcessor *next)
    : ETagVerifier(cct, next),
      part_ofs(std::move(part_ofs))
  {
    // Allow use of MD5 digest in FIPS mode for non-cryptographic purposes
    hash.SetFlags(EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
  }

  int process(bufferlist&& data, uint64_t logical_offset) override;
  void calculate_etag() override;

}; /* ETagVerifier_MPU */

constexpr auto max_etag_verifier_size = std::max(
    sizeof(ETagVerifier_Atomic),
    sizeof(ETagVerifier_MPU)
  );
using etag_verifier_ptr = ceph::static_ptr<ETagVerifier, max_etag_verifier_size>;

int create_etag_verifier(const DoutPrefixProvider *dpp, 
                         CephContext* cct, DataProcessor* next,
                         const bufferlist& manifest_bl,
                         const std::optional<RGWCompressionInfo>& compression,
                         etag_verifier_ptr& verifier);

} // namespace rgw::putobj

#endif /* CEPH_RGW_ETAG_VERIFIER_H */