mirror of
https://github.com/minio/minio.git
synced 2024-12-24 22:25:54 -05:00
fix: copyObject key rotation issue (#10085)
- copyObject in-place decryption failed due to incorrect verification of headers - do not decode ETag when object is encrypted with SSE-C, so that pre-conditions don't fail prematurely.
This commit is contained in:
parent
44c8af66ad
commit
d53e560ce0
@ -75,9 +75,6 @@ func getConditionValues(r *http.Request, lc string, username string, claims map[
|
||||
if u, err := url.Parse(r.Header.Get(xhttp.AmzCopySource)); err == nil {
|
||||
vid = u.Query().Get("versionId")
|
||||
}
|
||||
if vid == "" {
|
||||
vid = r.Header.Get(xhttp.AmzCopySourceVersionID)
|
||||
}
|
||||
}
|
||||
|
||||
args := map[string][]string{
|
||||
|
@ -31,6 +31,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/minio/minio/cmd/crypto"
|
||||
xhttp "github.com/minio/minio/cmd/http"
|
||||
"github.com/minio/minio/cmd/logger"
|
||||
sha256 "github.com/minio/sha256-simd"
|
||||
"github.com/minio/sio"
|
||||
@ -809,9 +810,16 @@ func DecryptObjectInfo(info *ObjectInfo, r *http.Request) (encrypted bool, err e
|
||||
}
|
||||
|
||||
if encrypted {
|
||||
if (crypto.SSEC.IsEncrypted(info.UserDefined) && !crypto.SSEC.IsRequested(headers)) ||
|
||||
(crypto.S3.IsEncrypted(info.UserDefined) && crypto.SSEC.IsRequested(headers)) {
|
||||
return encrypted, errEncryptedObject
|
||||
if crypto.SSEC.IsEncrypted(info.UserDefined) {
|
||||
if !(crypto.SSEC.IsRequested(headers) || crypto.SSECopy.IsRequested(headers)) {
|
||||
return encrypted, errEncryptedObject
|
||||
}
|
||||
}
|
||||
|
||||
if crypto.S3.IsEncrypted(info.UserDefined) && r.Header.Get(xhttp.AmzCopySource) == "" {
|
||||
if crypto.SSEC.IsRequested(headers) || crypto.SSECopy.IsRequested(headers) {
|
||||
return encrypted, errEncryptedObject
|
||||
}
|
||||
}
|
||||
|
||||
if _, err = info.DecryptedSize(); err != nil {
|
||||
@ -819,7 +827,7 @@ func DecryptObjectInfo(info *ObjectInfo, r *http.Request) (encrypted bool, err e
|
||||
}
|
||||
|
||||
if crypto.IsEncrypted(info.UserDefined) && !crypto.IsMultiPart(info.UserDefined) {
|
||||
info.ETag = getDecryptedETag(headers, *info, headers.Get(crypto.SSECopyAlgorithm) != "")
|
||||
info.ETag = getDecryptedETag(headers, *info, false)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -612,7 +612,6 @@ func NewGetObjectReader(rs *HTTPRangeSpec, oi ObjectInfo, opts ObjectOptions, cl
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
oi.ETag = getDecryptedETag(h, oi, copySource) // Decrypt the ETag before top layer consumes this value.
|
||||
|
||||
if opts.CheckPrecondFn != nil && opts.CheckPrecondFn(oi) {
|
||||
// Call the cleanup funcs
|
||||
@ -622,6 +621,8 @@ func NewGetObjectReader(rs *HTTPRangeSpec, oi ObjectInfo, opts ObjectOptions, cl
|
||||
return nil, PreConditionFailed{}
|
||||
}
|
||||
|
||||
oi.ETag = getDecryptedETag(h, oi, false)
|
||||
|
||||
// Apply the skipLen and limit on the
|
||||
// decrypted stream
|
||||
decReader = io.LimitReader(ioutil.NewSkipReader(decReader, skipLen), decRangeLength)
|
||||
|
@ -612,10 +612,6 @@ func (api objectAPIHandlers) HeadObjectHandler(w http.ResponseWriter, r *http.Re
|
||||
|
||||
// Set encryption response headers
|
||||
if objectAPI.IsEncryptionSupported() {
|
||||
if _, err = DecryptObjectInfo(&objInfo, r); err != nil {
|
||||
writeErrorResponseHeadersOnly(w, toAPIError(ctx, err))
|
||||
return
|
||||
}
|
||||
if crypto.IsEncrypted(objInfo.UserDefined) {
|
||||
switch {
|
||||
case crypto.S3.IsEncrypted(objInfo.UserDefined):
|
||||
@ -1744,9 +1740,6 @@ func (api objectAPIHandlers) CopyObjectPartHandler(w http.ResponseWriter, r *htt
|
||||
// Note that url.Parse does the unescaping
|
||||
cpSrcPath = u.Path
|
||||
}
|
||||
if vid == "" {
|
||||
vid = strings.TrimSpace(r.Header.Get(xhttp.AmzCopySourceVersionID))
|
||||
}
|
||||
|
||||
srcBucket, srcObject := path2BucketObject(cpSrcPath)
|
||||
// If source object is empty or bucket is empty, reply back invalid copy source.
|
||||
|
Loading…
Reference in New Issue
Block a user