diff --git a/cmd/encryption-v1.go b/cmd/encryption-v1.go index 8cc5d0842..401efd2b9 100644 --- a/cmd/encryption-v1.go +++ b/cmd/encryption-v1.go @@ -332,7 +332,7 @@ func DecryptRequestWithSequenceNumberR(client io.Reader, h http.Header, bucket, // DecryptCopyRequestR - same as DecryptCopyRequest, but with a // Reader -func DecryptCopyRequestR(client io.Reader, h http.Header, bucket, object string, metadata map[string]string) (io.Reader, error) { +func DecryptCopyRequestR(client io.Reader, h http.Header, bucket, object string, seqNumber uint32, metadata map[string]string) (io.Reader, error) { var ( key []byte err error @@ -343,7 +343,7 @@ func DecryptCopyRequestR(client io.Reader, h http.Header, bucket, object string, return nil, err } } - return newDecryptReader(client, key, bucket, object, 0, metadata) + return newDecryptReader(client, key, bucket, object, seqNumber, metadata) } func newDecryptReader(client io.Reader, key []byte, bucket, object string, seqNumber uint32, metadata map[string]string) (io.Reader, error) { @@ -365,17 +365,6 @@ func newDecryptReaderWithObjectKey(client io.Reader, objectEncryptionKey []byte, return reader, nil } -// GetEncryptedOffsetLength - returns encrypted offset and length -// along with sequence number -func GetEncryptedOffsetLength(startOffset, length int64, objInfo ObjectInfo) (seqNumber uint32, encStartOffset, encLength int64) { - if !isEncryptedMultipart(objInfo) { - seqNumber, encStartOffset, encLength = getEncryptedSinglePartOffsetLength(startOffset, length, objInfo) - return - } - seqNumber, encStartOffset, encLength = getEncryptedMultipartsOffsetLength(startOffset, length, objInfo) - return -} - // DecryptBlocksRequestR - same as DecryptBlocksRequest but with a // reader func DecryptBlocksRequestR(inputReader io.Reader, h http.Header, offset, @@ -389,7 +378,7 @@ func DecryptBlocksRequestR(inputReader io.Reader, h http.Header, offset, var reader io.Reader var err error if copySource { - reader, err = DecryptCopyRequestR(inputReader, h, bucket, object, oi.UserDefined) + reader, err = DecryptCopyRequestR(inputReader, h, bucket, object, seqNumber, oi.UserDefined) } else { reader, err = DecryptRequestWithSequenceNumberR(inputReader, h, bucket, object, seqNumber, oi.UserDefined) } diff --git a/cmd/object-handlers.go b/cmd/object-handlers.go index cb36b6610..4b5807ddf 100644 --- a/cmd/object-handlers.go +++ b/cmd/object-handlers.go @@ -701,30 +701,12 @@ func (api objectAPIHandlers) CopyObjectHandler(w http.ResponseWriter, r *http.Re getObjectNInfo = api.CacheAPI().GetObjectNInfo } - // Get request range. - var rs *HTTPRangeSpec - rangeHeader := r.Header.Get("x-amz-copy-source-range") - if rangeHeader != "" { - var parseRangeErr error - if rs, parseRangeErr = parseRequestRangeSpec(rangeHeader); parseRangeErr != nil { - // Handle only errInvalidRange. Ignore other - // parse error and treat it as regular Get - // request like Amazon S3. - if parseRangeErr == errInvalidRange { - writeErrorResponse(w, ErrInvalidRange, r.URL) - return - } - - // log the error. - logger.LogIf(ctx, parseRangeErr) - } - } - var lock = noLock if !cpSrcDstSame { lock = readLock } + var rs *HTTPRangeSpec gr, err := getObjectNInfo(ctx, srcBucket, srcObject, rs, r.Header, lock, srcOpts) if err != nil { writeErrorResponse(w, toAPIErrorCode(err), r.URL) @@ -1485,8 +1467,11 @@ func (api objectAPIHandlers) CopyObjectPartHandler(w http.ResponseWriter, r *htt } // Get the object offset & length - startOffset, length, _ := rs.GetOffsetLength(actualPartSize) - actualPartSize = length + startOffset, length, err := rs.GetOffsetLength(actualPartSize) + if err != nil { + writeErrorResponse(w, toAPIErrorCode(err), r.URL) + return + } /// maximum copy size for multipart objects in a single operation if isMaxAllowedPartSize(length) { @@ -1494,8 +1479,8 @@ func (api objectAPIHandlers) CopyObjectPartHandler(w http.ResponseWriter, r *htt return } + actualPartSize = length var reader io.Reader - var getLength = length var li ListPartsInfo li, err = objectAPI.ListObjectParts(ctx, dstBucket, dstObject, uploadID, 0, 1) @@ -1503,6 +1488,7 @@ func (api objectAPIHandlers) CopyObjectPartHandler(w http.ResponseWriter, r *htt writeErrorResponse(w, toAPIErrorCode(err), r.URL) return } + // Read compression metadata preserved in the init multipart for the decision. _, compressPart := li.UserDefined[ReservedMetadataPrefix+"compression"] isCompressed := compressPart @@ -1535,7 +1521,7 @@ func (api objectAPIHandlers) CopyObjectPartHandler(w http.ResponseWriter, r *htt if objectAPI.IsEncryptionSupported() && !isCompressed { if crypto.IsEncrypted(li.UserDefined) { - if !hasServerSideEncryptionHeader(r.Header) { + if !crypto.SSEC.IsRequested(r.Header) && crypto.SSEC.IsEncrypted(li.UserDefined) { writeErrorResponse(w, ErrSSEMultipartEncrypted, r.URL) return } @@ -1567,18 +1553,18 @@ func (api objectAPIHandlers) CopyObjectPartHandler(w http.ResponseWriter, r *htt } info := ObjectInfo{Size: length} - size := info.EncryptedSize() - srcInfo.Reader, err = hash.NewReader(reader, size, "", "", actualPartSize) + srcInfo.Reader, err = hash.NewReader(reader, info.EncryptedSize(), "", "", length) if err != nil { writeErrorResponse(w, toAPIErrorCode(err), r.URL) return } } } + // Copy source object to destination, if source and destination // object is same then only metadata is updated. - partInfo, err := objectAPI.CopyObjectPart(ctx, srcBucket, srcObject, dstBucket, - dstObject, uploadID, partID, startOffset, getLength, srcInfo, srcOpts, dstOpts) + partInfo, err := objectAPI.CopyObjectPart(ctx, srcBucket, srcObject, dstBucket, dstObject, uploadID, partID, + startOffset, length, srcInfo, srcOpts, dstOpts) if err != nil { writeErrorResponse(w, toAPIErrorCode(err), r.URL) return