mirror of
https://github.com/minio/minio.git
synced 2024-12-25 14:45: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 {
|
if u, err := url.Parse(r.Header.Get(xhttp.AmzCopySource)); err == nil {
|
||||||
vid = u.Query().Get("versionId")
|
vid = u.Query().Get("versionId")
|
||||||
}
|
}
|
||||||
if vid == "" {
|
|
||||||
vid = r.Header.Get(xhttp.AmzCopySourceVersionID)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
args := map[string][]string{
|
args := map[string][]string{
|
||||||
|
@ -31,6 +31,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/minio/minio/cmd/crypto"
|
"github.com/minio/minio/cmd/crypto"
|
||||||
|
xhttp "github.com/minio/minio/cmd/http"
|
||||||
"github.com/minio/minio/cmd/logger"
|
"github.com/minio/minio/cmd/logger"
|
||||||
sha256 "github.com/minio/sha256-simd"
|
sha256 "github.com/minio/sha256-simd"
|
||||||
"github.com/minio/sio"
|
"github.com/minio/sio"
|
||||||
@ -809,17 +810,24 @@ func DecryptObjectInfo(info *ObjectInfo, r *http.Request) (encrypted bool, err e
|
|||||||
}
|
}
|
||||||
|
|
||||||
if encrypted {
|
if encrypted {
|
||||||
if (crypto.SSEC.IsEncrypted(info.UserDefined) && !crypto.SSEC.IsRequested(headers)) ||
|
if crypto.SSEC.IsEncrypted(info.UserDefined) {
|
||||||
(crypto.S3.IsEncrypted(info.UserDefined) && crypto.SSEC.IsRequested(headers)) {
|
if !(crypto.SSEC.IsRequested(headers) || crypto.SSECopy.IsRequested(headers)) {
|
||||||
return encrypted, errEncryptedObject
|
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 {
|
if _, err = info.DecryptedSize(); err != nil {
|
||||||
return encrypted, err
|
return encrypted, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if crypto.IsEncrypted(info.UserDefined) && !crypto.IsMultiPart(info.UserDefined) {
|
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
|
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) {
|
if opts.CheckPrecondFn != nil && opts.CheckPrecondFn(oi) {
|
||||||
// Call the cleanup funcs
|
// Call the cleanup funcs
|
||||||
@ -622,6 +621,8 @@ func NewGetObjectReader(rs *HTTPRangeSpec, oi ObjectInfo, opts ObjectOptions, cl
|
|||||||
return nil, PreConditionFailed{}
|
return nil, PreConditionFailed{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
oi.ETag = getDecryptedETag(h, oi, false)
|
||||||
|
|
||||||
// Apply the skipLen and limit on the
|
// Apply the skipLen and limit on the
|
||||||
// decrypted stream
|
// decrypted stream
|
||||||
decReader = io.LimitReader(ioutil.NewSkipReader(decReader, skipLen), decRangeLength)
|
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
|
// Set encryption response headers
|
||||||
if objectAPI.IsEncryptionSupported() {
|
if objectAPI.IsEncryptionSupported() {
|
||||||
if _, err = DecryptObjectInfo(&objInfo, r); err != nil {
|
|
||||||
writeErrorResponseHeadersOnly(w, toAPIError(ctx, err))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if crypto.IsEncrypted(objInfo.UserDefined) {
|
if crypto.IsEncrypted(objInfo.UserDefined) {
|
||||||
switch {
|
switch {
|
||||||
case crypto.S3.IsEncrypted(objInfo.UserDefined):
|
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
|
// Note that url.Parse does the unescaping
|
||||||
cpSrcPath = u.Path
|
cpSrcPath = u.Path
|
||||||
}
|
}
|
||||||
if vid == "" {
|
|
||||||
vid = strings.TrimSpace(r.Header.Get(xhttp.AmzCopySourceVersionID))
|
|
||||||
}
|
|
||||||
|
|
||||||
srcBucket, srcObject := path2BucketObject(cpSrcPath)
|
srcBucket, srcObject := path2BucketObject(cpSrcPath)
|
||||||
// If source object is empty or bucket is empty, reply back invalid copy source.
|
// If source object is empty or bucket is empty, reply back invalid copy source.
|
||||||
|
Loading…
Reference in New Issue
Block a user