From d531080b7ecd56305df1b79affa8cadf2fb526c4 Mon Sep 17 00:00:00 2001 From: Andreas Auernhammer Date: Sat, 18 Aug 2018 06:07:19 +0200 Subject: [PATCH] add SSE-KMS not-implemented error handling (#6234) This commit adds error handling for SSE-KMS requests to HEAD, GET, PUT and COPY operations. The server responds with `not implemented` if a client sends a SSE-KMS request. --- cmd/api-errors.go | 6 +++ cmd/object-handlers.go | 86 +++++++++++++++++++++++++++--------------- 2 files changed, 62 insertions(+), 30 deletions(-) diff --git a/cmd/api-errors.go b/cmd/api-errors.go index 231213aaf..fab4497d5 100644 --- a/cmd/api-errors.go +++ b/cmd/api-errors.go @@ -129,6 +129,7 @@ const ( ErrMaximumExpires ErrSlowDown ErrInvalidPrefixMarker + ErrBadRequest // Add new error codes here. // SSE-S3 related API errors @@ -636,6 +637,11 @@ var errorCodeResponse = map[APIErrorCode]APIError{ Description: "Invalid marker prefix combination", HTTPStatusCode: http.StatusBadRequest, }, + ErrBadRequest: { + Code: "BadRequest", + Description: "400 BadRequest", + HTTPStatusCode: http.StatusBadRequest, + }, // FIXME: Actual XML error response also contains the header which missed in list of signed header parameters. ErrUnsignedHeaders: { diff --git a/cmd/object-handlers.go b/cmd/object-handlers.go index 7e4bd8b5a..e22dcde0b 100644 --- a/cmd/object-handlers.go +++ b/cmd/object-handlers.go @@ -258,17 +258,19 @@ func (api objectAPIHandlers) SelectObjectContentHandler(w http.ResponseWriter, r func (api objectAPIHandlers) GetObjectHandler(w http.ResponseWriter, r *http.Request) { ctx := newContext(r, w, "GetObject") - var object, bucket string - vars := mux.Vars(r) - bucket = vars["bucket"] - object = vars["object"] - - // Fetch object stat info. objectAPI := api.ObjectAPI() if objectAPI == nil { writeErrorResponse(w, ErrServerNotInitialized, r.URL) return } + if crypto.S3.IsRequested(r.Header) || crypto.S3KMS.IsRequested(r.Header) { // If SSE-S3 or SSE-KMS present -> AWS fails with undefined error + writeErrorResponse(w, ErrBadRequest, r.URL) + return + } + + vars := mux.Vars(r) + bucket := vars["bucket"] + object := vars["object"] getObjectInfo := objectAPI.GetObjectInfo if api.CacheAPI() != nil { @@ -419,16 +421,19 @@ func (api objectAPIHandlers) GetObjectHandler(w http.ResponseWriter, r *http.Req func (api objectAPIHandlers) HeadObjectHandler(w http.ResponseWriter, r *http.Request) { ctx := newContext(r, w, "HeadObject") - var object, bucket string - vars := mux.Vars(r) - bucket = vars["bucket"] - object = vars["object"] - objectAPI := api.ObjectAPI() if objectAPI == nil { writeErrorResponseHeadersOnly(w, ErrServerNotInitialized) return } + if crypto.S3.IsRequested(r.Header) || crypto.S3KMS.IsRequested(r.Header) { // If SSE-S3 or SSE-KMS present -> AWS fails with undefined error + writeErrorResponse(w, ErrBadRequest, r.URL) + return + } + + vars := mux.Vars(r) + bucket := vars["bucket"] + object := vars["object"] getObjectInfo := objectAPI.GetObjectInfo if api.CacheAPI() != nil { @@ -547,14 +552,19 @@ func getCpObjMetadataFromHeader(ctx context.Context, r *http.Request, userMeta m func (api objectAPIHandlers) CopyObjectHandler(w http.ResponseWriter, r *http.Request) { ctx := newContext(r, w, "CopyObject") - vars := mux.Vars(r) - dstBucket := vars["bucket"] - dstObject := vars["object"] objectAPI := api.ObjectAPI() if objectAPI == nil { writeErrorResponse(w, ErrServerNotInitialized, r.URL) return } + if !objectAPI.IsEncryptionSupported() && crypto.S3KMS.IsRequested(r.Header) { + writeErrorResponse(w, ErrNotImplemented, r.URL) // SSE-KMS is not supported + return + } + + vars := mux.Vars(r) + dstBucket := vars["bucket"] + dstObject := vars["object"] if s3Error := checkRequestAuthType(ctx, r, policy.PutObjectAction, dstBucket, dstObject); s3Error != ErrNone { writeErrorResponse(w, s3Error, r.URL) @@ -853,10 +863,8 @@ func (api objectAPIHandlers) PutObjectHandler(w http.ResponseWriter, r *http.Req writeErrorResponse(w, ErrServerNotInitialized, r.URL) return } - - // X-Amz-Copy-Source shouldn't be set for this call. - if _, ok := r.Header["X-Amz-Copy-Source"]; ok { - writeErrorResponse(w, ErrInvalidCopySource, r.URL) + if !objectAPI.IsEncryptionSupported() && crypto.S3KMS.IsRequested(r.Header) { + writeErrorResponse(w, ErrNotImplemented, r.URL) // SSE-KMS is not supported return } @@ -864,6 +872,12 @@ func (api objectAPIHandlers) PutObjectHandler(w http.ResponseWriter, r *http.Req bucket := vars["bucket"] object := vars["object"] + // X-Amz-Copy-Source shouldn't be set for this call. + if _, ok := r.Header["X-Amz-Copy-Source"]; ok { + writeErrorResponse(w, ErrInvalidCopySource, r.URL) + return + } + // Validate storage class metadata if present if _, ok := r.Header[amzStorageClassCanonical]; ok { if !isValidStorageClassMeta(r.Header.Get(amzStorageClassCanonical)) { @@ -1058,16 +1072,19 @@ func (api objectAPIHandlers) PutObjectHandler(w http.ResponseWriter, r *http.Req func (api objectAPIHandlers) NewMultipartUploadHandler(w http.ResponseWriter, r *http.Request) { ctx := newContext(r, w, "NewMultipartUpload") - var object, bucket string - vars := mux.Vars(r) - bucket = vars["bucket"] - object = vars["object"] - objectAPI := api.ObjectAPI() if objectAPI == nil { writeErrorResponse(w, ErrServerNotInitialized, r.URL) return } + if !objectAPI.IsEncryptionSupported() && crypto.S3KMS.IsRequested(r.Header) { + writeErrorResponse(w, ErrNotImplemented, r.URL) // SSE-KMS is not supported + return + } + + vars := mux.Vars(r) + bucket := vars["bucket"] + object := vars["object"] if s3Error := checkRequestAuthType(ctx, r, policy.PutObjectAction, bucket, object); s3Error != ErrNone { writeErrorResponse(w, s3Error, r.URL) @@ -1138,15 +1155,19 @@ func (api objectAPIHandlers) NewMultipartUploadHandler(w http.ResponseWriter, r func (api objectAPIHandlers) CopyObjectPartHandler(w http.ResponseWriter, r *http.Request) { ctx := newContext(r, w, "CopyObjectPart") - vars := mux.Vars(r) - dstBucket := vars["bucket"] - dstObject := vars["object"] - objectAPI := api.ObjectAPI() if objectAPI == nil { writeErrorResponse(w, ErrServerNotInitialized, r.URL) return } + if !objectAPI.IsEncryptionSupported() && crypto.S3KMS.IsRequested(r.Header) { + writeErrorResponse(w, ErrNotImplemented, r.URL) // SSE-KMS is not supported + return + } + + vars := mux.Vars(r) + dstBucket := vars["bucket"] + dstObject := vars["object"] if s3Error := checkRequestAuthType(ctx, r, policy.PutObjectAction, dstBucket, dstObject); s3Error != ErrNone { writeErrorResponse(w, s3Error, r.URL) @@ -1339,14 +1360,19 @@ func (api objectAPIHandlers) CopyObjectPartHandler(w http.ResponseWriter, r *htt func (api objectAPIHandlers) PutObjectPartHandler(w http.ResponseWriter, r *http.Request) { ctx := newContext(r, w, "PutObjectPart") - vars := mux.Vars(r) - bucket := vars["bucket"] - object := vars["object"] objectAPI := api.ObjectAPI() if objectAPI == nil { writeErrorResponse(w, ErrServerNotInitialized, r.URL) return } + if !objectAPI.IsEncryptionSupported() && crypto.S3KMS.IsRequested(r.Header) { + writeErrorResponse(w, ErrNotImplemented, r.URL) // SSE-KMS is not supported + return + } + + vars := mux.Vars(r) + bucket := vars["bucket"] + object := vars["object"] // X-Amz-Copy-Source shouldn't be set for this call. if _, ok := r.Header["X-Amz-Copy-Source"]; ok {