From 23a545673de93162532a9933576fa00c89bef3e7 Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Fri, 8 May 2015 03:31:43 -0700 Subject: [PATCH] Verify incoming md5sum for invidual parts in complete multipart request and some simplification of the code Add two new functions for session cleanup --- pkg/api/api_object_handlers.go | 4 +- pkg/storage/drivers/memory/memory.go | 69 ++++++++++++++++++---------- 2 files changed, 45 insertions(+), 28 deletions(-) diff --git a/pkg/api/api_object_handlers.go b/pkg/api/api_object_handlers.go index 85a7f0bfe..2f2d240de 100644 --- a/pkg/api/api_object_handlers.go +++ b/pkg/api/api_object_handlers.go @@ -365,17 +365,15 @@ func (server *minioAPI) completeMultipartUploadHandler(w http.ResponseWriter, re return } - partMap := make(map[int]string) - vars := mux.Vars(req) bucket := vars["bucket"] object := vars["object"] uploadID := vars["uploadId"] + partMap := make(map[int]string) for _, part := range parts.Part { partMap[part.PartNumber] = part.ETag } - etag, err := server.driver.CompleteMultipartUpload(bucket, object, uploadID, partMap) switch err := iodine.ToError(err).(type) { case nil: diff --git a/pkg/storage/drivers/memory/memory.go b/pkg/storage/drivers/memory/memory.go index 1e2fd7501..76d7a757e 100644 --- a/pkg/storage/drivers/memory/memory.go +++ b/pkg/storage/drivers/memory/memory.go @@ -561,6 +561,21 @@ func (memory *memoryDriver) CreateObjectPart(bucket, key, uploadID string, partI return memory.CreateObject(bucket, getMultipartKey(key, uploadID, partID), "", expectedMD5Sum, size, data) } +func (memory *memoryDriver) cleanupMultipartSession(bucket, key, uploadID string) { + memory.lock.Lock() + defer memory.lock.Unlock() + memory.objects.Delete(bucket + "/" + key + "?uploadId=" + uploadID) +} + +func (memory *memoryDriver) cleanupMultiparts(bucket, key, uploadID string, parts map[int]string) { + memory.lock.Lock() + defer memory.lock.Unlock() + for i := range parts { + objectKey := bucket + "/" + getMultipartKey(key, uploadID, i) + memory.objects.Delete(objectKey) + } +} + func (memory *memoryDriver) CompleteMultipartUpload(bucket, key, uploadID string, parts map[int]string) (string, error) { // Verify upload id _, ok := memory.objects.Get(bucket + "/" + key + "?uploadId=" + uploadID) @@ -582,45 +597,49 @@ func (memory *memoryDriver) CompleteMultipartUpload(bucket, key, uploadID string memory.lock.Lock() var size int64 - for i := 1; i <= len(parts); i++ { - if _, ok := parts[i]; ok { - if object, ok := memory.storedBuckets[bucket].objectMetadata[bucket+"/"+getMultipartKey(key, uploadID, i)]; ok == true { - size += object.Size - } - } else { + for i := range parts { + object, ok := memory.storedBuckets[bucket].objectMetadata[bucket+"/"+getMultipartKey(key, uploadID, i)] + if !ok { memory.lock.Unlock() return "", iodine.New(errors.New("missing part: "+strconv.Itoa(i)), nil) } + size += object.Size } var fullObject bytes.Buffer for i := 1; i <= len(parts); i++ { - if _, ok := parts[i]; ok { - if object, ok := memory.objects.Get(bucket + "/" + getMultipartKey(key, uploadID, i)); ok == true { - obj := object.([]byte) - _, err := io.Copy(&fullObject, bytes.NewBuffer(obj)) - if err != nil { - return "", iodine.New(err, nil) - } - } else { - log.Println("Cannot fetch: ", getMultipartKey(key, uploadID, i)) - } - } else { + recvMD5 := parts[i] + object, ok := memory.objects.Get(bucket + "/" + getMultipartKey(key, uploadID, i)) + if ok == false { memory.lock.Unlock() return "", iodine.New(errors.New("missing part: "+strconv.Itoa(i)), nil) } - } - - for i := 1; i <= len(parts); i++ { - if _, ok := parts[i]; ok { - objectKey := bucket + "/" + getMultipartKey(key, uploadID, i) - memory.objects.Delete(objectKey) + obj := object.([]byte) + calcMD5Bytes := md5.Sum(obj) + // complete multi part request header md5sum per part is hex encoded + recvMD5Bytes, err := hex.DecodeString(strings.Trim(recvMD5, "\"")) + if err != nil { + return "", iodine.New(drivers.InvalidDigest{Md5: recvMD5}, nil) + } + if !bytes.Equal(recvMD5Bytes, calcMD5Bytes[:]) { + return "", iodine.New(drivers.BadDigest{Md5: recvMD5, Bucket: bucket, Key: getMultipartKey(key, uploadID, i)}, nil) + } + _, err = io.Copy(&fullObject, bytes.NewBuffer(obj)) + if err != nil { + return "", iodine.New(err, nil) } } - memory.lock.Unlock() md5sumSlice := md5.Sum(fullObject.Bytes()) md5sum := base64.StdEncoding.EncodeToString(md5sumSlice[:]) - return memory.CreateObject(bucket, key, "", md5sum, size, &fullObject) + etag, err := memory.CreateObject(bucket, key, "", md5sum, size, &fullObject) + if err != nil { + memory.cleanupMultiparts(bucket, key, uploadID, parts) + memory.cleanupMultipartSession(bucket, key, uploadID) + return "", iodine.New(err, nil) + } + memory.cleanupMultiparts(bucket, key, uploadID, parts) + memory.cleanupMultipartSession(bucket, key, uploadID) + return etag, nil }