diff --git a/pkg/donut/signature-v4.go b/pkg/donut/signature-v4.go index 77429cb66..ad2dd5f56 100644 --- a/pkg/donut/signature-v4.go +++ b/pkg/donut/signature-v4.go @@ -226,21 +226,14 @@ func (r *Signature) DoesSignatureMatch(hashedPayload string) (bool, error) { if err != nil { return false, iodine.New(err, nil) } - signedHeaders := r.getSignedHeaders() canonicalRequest := r.getCanonicalRequest() - scope := r.getScope(t) stringToSign := r.getStringToSign(canonicalRequest, t) signingKey := r.getSigningKey(t) - signature := r.getSignature(signingKey, stringToSign) + newSignature := r.getSignature(signingKey, stringToSign) - // final Authorization header - parts := []string{ - authHeaderPrefix + " Credential=" + r.AccessKeyID + "/" + scope, - "SignedHeaders=" + signedHeaders, - "Signature=" + signature, - } - newAuthHeader := strings.Join(parts, ", ") - if newAuthHeader != r.AuthHeader { + authFields := strings.Split(strings.TrimSpace(r.AuthHeader), ",") + signature := strings.Split(strings.TrimSpace(authFields[2]), "=")[1] + if newSignature != signature { return false, nil } return true, nil diff --git a/pkg/server/api/bucket-handlers.go b/pkg/server/api/bucket-handlers.go index 710814619..59cd893c4 100644 --- a/pkg/server/api/bucket-handlers.go +++ b/pkg/server/api/bucket-handlers.go @@ -118,15 +118,13 @@ func (api Minio) ListMultipartUploadsHandler(w http.ResponseWriter, req *http.Re // write body w.Write(encodedSuccessResponse) } + case donut.SignatureDoesNotMatch: + writeErrorResponse(w, req, SignatureDoesNotMatch, acceptsContentType, req.URL.Path) case donut.BucketNotFound: - { - writeErrorResponse(w, req, NoSuchBucket, acceptsContentType, req.URL.Path) - } + writeErrorResponse(w, req, NoSuchBucket, acceptsContentType, req.URL.Path) default: - { - log.Error.Println(iodine.New(err, nil)) - writeErrorResponse(w, req, InternalError, acceptsContentType, req.URL.Path) - } + log.Error.Println(iodine.New(err, nil)) + writeErrorResponse(w, req, InternalError, acceptsContentType, req.URL.Path) } } @@ -185,6 +183,8 @@ func (api Minio) ListObjectsHandler(w http.ResponseWriter, req *http.Request) { setCommonHeaders(w, getContentTypeString(acceptsContentType), len(encodedSuccessResponse)) // write body w.Write(encodedSuccessResponse) + case donut.SignatureDoesNotMatch: + writeErrorResponse(w, req, SignatureDoesNotMatch, acceptsContentType, req.URL.Path) case donut.BucketNameInvalid: writeErrorResponse(w, req, InvalidBucketName, acceptsContentType, req.URL.Path) case donut.BucketNotFound: @@ -242,6 +242,8 @@ func (api Minio) ListBucketsHandler(w http.ResponseWriter, req *http.Request) { setCommonHeaders(w, getContentTypeString(acceptsContentType), len(encodedSuccessResponse)) // write response w.Write(encodedSuccessResponse) + case donut.SignatureDoesNotMatch: + writeErrorResponse(w, req, SignatureDoesNotMatch, acceptsContentType, req.URL.Path) default: log.Error.Println(iodine.New(err, nil)) writeErrorResponse(w, req, InternalError, acceptsContentType, req.URL.Path) @@ -300,6 +302,8 @@ func (api Minio) PutBucketHandler(w http.ResponseWriter, req *http.Request) { // Make sure to add Location information here only for bucket w.Header().Set("Location", "/"+bucket) writeSuccessResponse(w, acceptsContentType) + case donut.SignatureDoesNotMatch: + writeErrorResponse(w, req, SignatureDoesNotMatch, acceptsContentType, req.URL.Path) case donut.TooManyBuckets: writeErrorResponse(w, req, TooManyBuckets, acceptsContentType, req.URL.Path) case donut.BucketNameInvalid: @@ -352,6 +356,8 @@ func (api Minio) PutBucketACLHandler(w http.ResponseWriter, req *http.Request) { switch iodine.ToError(err).(type) { case nil: writeSuccessResponse(w, acceptsContentType) + case donut.SignatureDoesNotMatch: + writeErrorResponse(w, req, SignatureDoesNotMatch, acceptsContentType, req.URL.Path) case donut.BucketNameInvalid: writeErrorResponse(w, req, InvalidBucketName, acceptsContentType, req.URL.Path) case donut.BucketNotFound: @@ -398,6 +404,8 @@ func (api Minio) HeadBucketHandler(w http.ResponseWriter, req *http.Request) { switch iodine.ToError(err).(type) { case nil: writeSuccessResponse(w, acceptsContentType) + case donut.SignatureDoesNotMatch: + writeErrorResponse(w, req, SignatureDoesNotMatch, acceptsContentType, req.URL.Path) case donut.BucketNotFound: error := getErrorCode(NoSuchBucket) w.WriteHeader(error.HTTPStatusCode) diff --git a/pkg/server/api/object-handlers.go b/pkg/server/api/object-handlers.go index 8a7cf46c0..73231c681 100644 --- a/pkg/server/api/object-handlers.go +++ b/pkg/server/api/object-handlers.go @@ -91,6 +91,8 @@ func (api Minio) GetObjectHandler(w http.ResponseWriter, req *http.Request) { } } } + case donut.SignatureDoesNotMatch: + writeErrorResponse(w, req, SignatureDoesNotMatch, acceptsContentType, req.URL.Path) case donut.BucketNameInvalid: writeErrorResponse(w, req, InvalidBucketName, acceptsContentType, req.URL.Path) case donut.BucketNotFound: @@ -144,6 +146,10 @@ func (api Minio) HeadObjectHandler(w http.ResponseWriter, req *http.Request) { case nil: setObjectHeaders(w, metadata) w.WriteHeader(http.StatusOK) + case donut.SignatureDoesNotMatch: + error := getErrorCode(SignatureDoesNotMatch) + w.Header().Set("Server", "Minio") + w.WriteHeader(error.HTTPStatusCode) case donut.BucketNameInvalid: error := getErrorCode(InvalidBucketName) w.Header().Set("Server", "Minio") @@ -314,6 +320,8 @@ func (api Minio) NewMultipartUploadHandler(w http.ResponseWriter, req *http.Requ // write body w.Write(encodedSuccessResponse) } + case donut.SignatureDoesNotMatch: + writeErrorResponse(w, req, SignatureDoesNotMatch, acceptsContentType, req.URL.Path) case donut.ObjectExists: writeErrorResponse(w, req, MethodNotAllowed, acceptsContentType, req.URL.Path) default: @@ -450,6 +458,8 @@ func (api Minio) AbortMultipartUploadHandler(w http.ResponseWriter, req *http.Re case nil: setCommonHeaders(w, getContentTypeString(acceptsContentType), 0) w.WriteHeader(http.StatusNoContent) + case donut.SignatureDoesNotMatch: + writeErrorResponse(w, req, SignatureDoesNotMatch, acceptsContentType, req.URL.Path) case donut.InvalidUploadID: writeErrorResponse(w, req, NoSuchUpload, acceptsContentType, req.URL.Path) default: @@ -505,6 +515,8 @@ func (api Minio) ListObjectPartsHandler(w http.ResponseWriter, req *http.Request // write body w.Write(encodedSuccessResponse) } + case donut.SignatureDoesNotMatch: + writeErrorResponse(w, req, SignatureDoesNotMatch, acceptsContentType, req.URL.Path) case donut.InvalidUploadID: writeErrorResponse(w, req, NoSuchUpload, acceptsContentType, req.URL.Path) default: diff --git a/pkg/server/api/signature.go b/pkg/server/api/signature.go index b6247d476..220e79875 100644 --- a/pkg/server/api/signature.go +++ b/pkg/server/api/signature.go @@ -35,7 +35,7 @@ func StripAccessKeyID(ah string) (string, error) { if ah == "" { return "", errors.New("Missing auth header") } - authFields := strings.Split(ah, ",") + authFields := strings.Split(strings.TrimSpace(ah), ",") if len(authFields) != 3 { return "", errors.New("Missing fields in Auth header") } @@ -46,17 +46,17 @@ func StripAccessKeyID(ah string) (string, error) { if authPrefixFields[0] != authHeaderPrefix { return "", errors.New("Missing fields is Auth header") } - credentials := strings.Split(authPrefixFields[1], "=") + credentials := strings.Split(strings.TrimSpace(authPrefixFields[1]), "=") if len(credentials) != 2 { return "", errors.New("Missing fields in Auth header") } - if len(strings.Split(authFields[1], "=")) != 2 { + if len(strings.Split(strings.TrimSpace(authFields[1]), "=")) != 2 { return "", errors.New("Missing fields in Auth header") } - if len(strings.Split(authFields[2], "=")) != 2 { + if len(strings.Split(strings.TrimSpace(authFields[2]), "=")) != 2 { return "", errors.New("Missing fields in Auth header") } - accessKeyID := strings.Split(credentials[1], "/")[0] + accessKeyID := strings.Split(strings.TrimSpace(credentials[1]), "/")[0] if !auth.IsValidAccessKey(accessKeyID) { return "", errors.New("Invalid access key") }