From d31eaddba3a5d0a3f6a21f15ff8e0b331dab20ab Mon Sep 17 00:00:00 2001 From: Harshavardhana Date: Tue, 19 May 2020 02:01:08 -0700 Subject: [PATCH] fix: avoid double body reads in SelectObject call (#9638) Bonus fix handle encryption headers in response properly for both notification and response to the client. --- cmd/object-handlers.go | 40 ++++++++++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/cmd/object-handlers.go b/cmd/object-handlers.go index c1933ab22..be813eeee 100644 --- a/cmd/object-handlers.go +++ b/cmd/object-handlers.go @@ -173,11 +173,13 @@ func (api objectAPIHandlers) SelectObjectContentHandler(w http.ResponseWriter, r if api.CacheAPI() != nil { getObjectNInfo = api.CacheAPI().GetObjectNInfo } + getObject := func(offset, length int64) (rc io.ReadCloser, err error) { isSuffixLength := false if offset < 0 { isSuffixLength = true } + rs := &HTTPRangeSpec{ IsSuffixLength: isSuffixLength, Start: offset, @@ -193,6 +195,20 @@ func (api objectAPIHandlers) SelectObjectContentHandler(w http.ResponseWriter, r return } + // filter object lock metadata if permission does not permit + getRetPerms := checkRequestAuthType(ctx, r, policy.GetObjectRetentionAction, bucket, object) + legalHoldPerms := checkRequestAuthType(ctx, r, policy.GetObjectLegalHoldAction, bucket, object) + + // filter object lock metadata if permission does not permit + objInfo.UserDefined = objectlock.FilterObjectLockMetadata(objInfo.UserDefined, getRetPerms != ErrNone, legalHoldPerms != ErrNone) + + if objectAPI.IsEncryptionSupported() { + if _, err = DecryptObjectInfo(&objInfo, r.Header); err != nil { + writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL, guessIsBrowserReq(r)) + return + } + } + s3Select, err := s3select.NewS3Select(r.Body) if err != nil { if serr, ok := err.(s3select.SelectError); ok { @@ -212,12 +228,6 @@ func (api objectAPIHandlers) SelectObjectContentHandler(w http.ResponseWriter, r return } - getRetPerms := checkRequestAuthType(ctx, r, policy.GetObjectRetentionAction, bucket, object) - legalHoldPerms := checkRequestAuthType(ctx, r, policy.GetObjectLegalHoldAction, bucket, object) - - // filter object lock metadata if permission does not permit - objInfo.UserDefined = objectlock.FilterObjectLockMetadata(objInfo.UserDefined, getRetPerms != ErrNone, legalHoldPerms != ErrNone) - if err = s3Select.Open(getObject); err != nil { if serr, ok := err.(s3select.SelectError); ok { encodedErrorResponse := encodeResponse(APIErrorResponse{ @@ -236,6 +246,24 @@ func (api objectAPIHandlers) SelectObjectContentHandler(w http.ResponseWriter, r return } + // Set encryption response headers + if objectAPI.IsEncryptionSupported() { + if crypto.IsEncrypted(objInfo.UserDefined) { + switch { + case crypto.S3.IsEncrypted(objInfo.UserDefined): + w.Header().Set(crypto.SSEHeader, crypto.SSEAlgorithmAES256) + case crypto.SSEC.IsEncrypted(objInfo.UserDefined): + // Validate the SSE-C Key set in the header. + if _, err = crypto.SSEC.UnsealObjectKey(r.Header, objInfo.UserDefined, bucket, object); err != nil { + writeErrorResponseHeadersOnly(w, toAPIError(ctx, err)) + return + } + w.Header().Set(crypto.SSECAlgorithm, r.Header.Get(crypto.SSECAlgorithm)) + w.Header().Set(crypto.SSECKeyMD5, r.Header.Get(crypto.SSECKeyMD5)) + } + } + } + s3Select.Evaluate(w) s3Select.Close()