diff --git a/s3api/controllers/base.go b/s3api/controllers/base.go index cfda9724..8804c3a1 100644 --- a/s3api/controllers/base.go +++ b/s3api/controllers/base.go @@ -22,6 +22,7 @@ import ( "io" "log" "net/http" + "net/url" "strconv" "strings" "time" @@ -1733,6 +1734,24 @@ func (c S3ApiController) PutActions(ctx *fiber.Ctx) error { if ctx.Request().URI().QueryArgs().Has("uploadId") && ctx.Request().URI().QueryArgs().Has("partNumber") && copySource != "" { + + cs := copySource + copySource, err := url.QueryUnescape(copySource) + if err != nil { + if c.debug { + log.Printf("error unescaping copy source %q: %v", + cs, err) + } + return SendXMLResponse(ctx, nil, + s3err.GetAPIError(s3err.ErrInvalidCopySource), + &MetaOpts{ + Logger: c.logger, + MetricsMng: c.mm, + Action: metrics.ActionUploadPartCopy, + BucketOwner: parsedAcl.Owner, + }) + } + partNumber := int32(ctx.QueryInt("partNumber", -1)) if partNumber < 1 || partNumber > 10000 { if c.debug { @@ -1748,7 +1767,7 @@ func (c S3ApiController) PutActions(ctx *fiber.Ctx) error { }) } - err := auth.VerifyObjectCopyAccess(ctx.Context(), c.be, copySource, + err = auth.VerifyObjectCopyAccess(ctx.Context(), c.be, copySource, auth.AccessOptions{ Acl: parsedAcl, AclPermission: types.PermissionWrite, @@ -1994,7 +2013,24 @@ func (c S3ApiController) PutActions(ctx *fiber.Ctx) error { } if copySource != "" { - err := auth.VerifyObjectCopyAccess(ctx.Context(), c.be, copySource, + cs := copySource + copySource, err := url.QueryUnescape(copySource) + if err != nil { + if c.debug { + log.Printf("error unescaping copy source %q: %v", + cs, err) + } + return SendXMLResponse(ctx, nil, + s3err.GetAPIError(s3err.ErrInvalidCopySource), + &MetaOpts{ + Logger: c.logger, + MetricsMng: c.mm, + Action: metrics.ActionCopyObject, + BucketOwner: parsedAcl.Owner, + }) + } + + err = auth.VerifyObjectCopyAccess(ctx.Context(), c.be, copySource, auth.AccessOptions{ Acl: parsedAcl, AclPermission: types.PermissionWrite, diff --git a/tests/integration/tests.go b/tests/integration/tests.go index 0f5d7614..7b87b521 100644 --- a/tests/integration/tests.go +++ b/tests/integration/tests.go @@ -4421,7 +4421,7 @@ func CopyObject_non_existing_dir_object(s *S3Conf) error { func CopyObject_success(s *S3Conf) error { testName := "CopyObject_success" return actionHandler(s, testName, func(s3client *s3.Client, bucket string) error { - dataLength, obj := int64(1234567), "my-obj" + dataLength, obj := int64(1234567), "my obj with spaces" dstBucket := getBucketName() err := setup(s, dstBucket) if err != nil {