Handle both space and non-space characters, in signature v4 - add errors for all API's

master
Harshavardhana 10 years ago
parent eac92d4647
commit e5006c738d
  1. 15
      pkg/donut/signature-v4.go
  2. 16
      pkg/server/api/bucket-handlers.go
  3. 12
      pkg/server/api/object-handlers.go
  4. 10
      pkg/server/api/signature.go

@ -226,21 +226,14 @@ func (r *Signature) DoesSignatureMatch(hashedPayload string) (bool, error) {
if err != nil { if err != nil {
return false, iodine.New(err, nil) return false, iodine.New(err, nil)
} }
signedHeaders := r.getSignedHeaders()
canonicalRequest := r.getCanonicalRequest() canonicalRequest := r.getCanonicalRequest()
scope := r.getScope(t)
stringToSign := r.getStringToSign(canonicalRequest, t) stringToSign := r.getStringToSign(canonicalRequest, t)
signingKey := r.getSigningKey(t) signingKey := r.getSigningKey(t)
signature := r.getSignature(signingKey, stringToSign) newSignature := r.getSignature(signingKey, stringToSign)
// final Authorization header authFields := strings.Split(strings.TrimSpace(r.AuthHeader), ",")
parts := []string{ signature := strings.Split(strings.TrimSpace(authFields[2]), "=")[1]
authHeaderPrefix + " Credential=" + r.AccessKeyID + "/" + scope, if newSignature != signature {
"SignedHeaders=" + signedHeaders,
"Signature=" + signature,
}
newAuthHeader := strings.Join(parts, ", ")
if newAuthHeader != r.AuthHeader {
return false, nil return false, nil
} }
return true, nil return true, nil

@ -118,17 +118,15 @@ func (api Minio) ListMultipartUploadsHandler(w http.ResponseWriter, req *http.Re
// write body // write body
w.Write(encodedSuccessResponse) w.Write(encodedSuccessResponse)
} }
case donut.SignatureDoesNotMatch:
writeErrorResponse(w, req, SignatureDoesNotMatch, acceptsContentType, req.URL.Path)
case donut.BucketNotFound: case donut.BucketNotFound:
{
writeErrorResponse(w, req, NoSuchBucket, acceptsContentType, req.URL.Path) writeErrorResponse(w, req, NoSuchBucket, acceptsContentType, req.URL.Path)
}
default: default:
{
log.Error.Println(iodine.New(err, nil)) log.Error.Println(iodine.New(err, nil))
writeErrorResponse(w, req, InternalError, acceptsContentType, req.URL.Path) writeErrorResponse(w, req, InternalError, acceptsContentType, req.URL.Path)
} }
} }
}
// ListObjectsHandler - GET Bucket (List Objects) // ListObjectsHandler - GET Bucket (List Objects)
// ------------------------- // -------------------------
@ -185,6 +183,8 @@ func (api Minio) ListObjectsHandler(w http.ResponseWriter, req *http.Request) {
setCommonHeaders(w, getContentTypeString(acceptsContentType), len(encodedSuccessResponse)) setCommonHeaders(w, getContentTypeString(acceptsContentType), len(encodedSuccessResponse))
// write body // write body
w.Write(encodedSuccessResponse) w.Write(encodedSuccessResponse)
case donut.SignatureDoesNotMatch:
writeErrorResponse(w, req, SignatureDoesNotMatch, acceptsContentType, req.URL.Path)
case donut.BucketNameInvalid: case donut.BucketNameInvalid:
writeErrorResponse(w, req, InvalidBucketName, acceptsContentType, req.URL.Path) writeErrorResponse(w, req, InvalidBucketName, acceptsContentType, req.URL.Path)
case donut.BucketNotFound: case donut.BucketNotFound:
@ -242,6 +242,8 @@ func (api Minio) ListBucketsHandler(w http.ResponseWriter, req *http.Request) {
setCommonHeaders(w, getContentTypeString(acceptsContentType), len(encodedSuccessResponse)) setCommonHeaders(w, getContentTypeString(acceptsContentType), len(encodedSuccessResponse))
// write response // write response
w.Write(encodedSuccessResponse) w.Write(encodedSuccessResponse)
case donut.SignatureDoesNotMatch:
writeErrorResponse(w, req, SignatureDoesNotMatch, acceptsContentType, req.URL.Path)
default: default:
log.Error.Println(iodine.New(err, nil)) log.Error.Println(iodine.New(err, nil))
writeErrorResponse(w, req, InternalError, acceptsContentType, req.URL.Path) 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 // Make sure to add Location information here only for bucket
w.Header().Set("Location", "/"+bucket) w.Header().Set("Location", "/"+bucket)
writeSuccessResponse(w, acceptsContentType) writeSuccessResponse(w, acceptsContentType)
case donut.SignatureDoesNotMatch:
writeErrorResponse(w, req, SignatureDoesNotMatch, acceptsContentType, req.URL.Path)
case donut.TooManyBuckets: case donut.TooManyBuckets:
writeErrorResponse(w, req, TooManyBuckets, acceptsContentType, req.URL.Path) writeErrorResponse(w, req, TooManyBuckets, acceptsContentType, req.URL.Path)
case donut.BucketNameInvalid: case donut.BucketNameInvalid:
@ -352,6 +356,8 @@ func (api Minio) PutBucketACLHandler(w http.ResponseWriter, req *http.Request) {
switch iodine.ToError(err).(type) { switch iodine.ToError(err).(type) {
case nil: case nil:
writeSuccessResponse(w, acceptsContentType) writeSuccessResponse(w, acceptsContentType)
case donut.SignatureDoesNotMatch:
writeErrorResponse(w, req, SignatureDoesNotMatch, acceptsContentType, req.URL.Path)
case donut.BucketNameInvalid: case donut.BucketNameInvalid:
writeErrorResponse(w, req, InvalidBucketName, acceptsContentType, req.URL.Path) writeErrorResponse(w, req, InvalidBucketName, acceptsContentType, req.URL.Path)
case donut.BucketNotFound: case donut.BucketNotFound:
@ -398,6 +404,8 @@ func (api Minio) HeadBucketHandler(w http.ResponseWriter, req *http.Request) {
switch iodine.ToError(err).(type) { switch iodine.ToError(err).(type) {
case nil: case nil:
writeSuccessResponse(w, acceptsContentType) writeSuccessResponse(w, acceptsContentType)
case donut.SignatureDoesNotMatch:
writeErrorResponse(w, req, SignatureDoesNotMatch, acceptsContentType, req.URL.Path)
case donut.BucketNotFound: case donut.BucketNotFound:
error := getErrorCode(NoSuchBucket) error := getErrorCode(NoSuchBucket)
w.WriteHeader(error.HTTPStatusCode) w.WriteHeader(error.HTTPStatusCode)

@ -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: case donut.BucketNameInvalid:
writeErrorResponse(w, req, InvalidBucketName, acceptsContentType, req.URL.Path) writeErrorResponse(w, req, InvalidBucketName, acceptsContentType, req.URL.Path)
case donut.BucketNotFound: case donut.BucketNotFound:
@ -144,6 +146,10 @@ func (api Minio) HeadObjectHandler(w http.ResponseWriter, req *http.Request) {
case nil: case nil:
setObjectHeaders(w, metadata) setObjectHeaders(w, metadata)
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
case donut.SignatureDoesNotMatch:
error := getErrorCode(SignatureDoesNotMatch)
w.Header().Set("Server", "Minio")
w.WriteHeader(error.HTTPStatusCode)
case donut.BucketNameInvalid: case donut.BucketNameInvalid:
error := getErrorCode(InvalidBucketName) error := getErrorCode(InvalidBucketName)
w.Header().Set("Server", "Minio") w.Header().Set("Server", "Minio")
@ -314,6 +320,8 @@ func (api Minio) NewMultipartUploadHandler(w http.ResponseWriter, req *http.Requ
// write body // write body
w.Write(encodedSuccessResponse) w.Write(encodedSuccessResponse)
} }
case donut.SignatureDoesNotMatch:
writeErrorResponse(w, req, SignatureDoesNotMatch, acceptsContentType, req.URL.Path)
case donut.ObjectExists: case donut.ObjectExists:
writeErrorResponse(w, req, MethodNotAllowed, acceptsContentType, req.URL.Path) writeErrorResponse(w, req, MethodNotAllowed, acceptsContentType, req.URL.Path)
default: default:
@ -450,6 +458,8 @@ func (api Minio) AbortMultipartUploadHandler(w http.ResponseWriter, req *http.Re
case nil: case nil:
setCommonHeaders(w, getContentTypeString(acceptsContentType), 0) setCommonHeaders(w, getContentTypeString(acceptsContentType), 0)
w.WriteHeader(http.StatusNoContent) w.WriteHeader(http.StatusNoContent)
case donut.SignatureDoesNotMatch:
writeErrorResponse(w, req, SignatureDoesNotMatch, acceptsContentType, req.URL.Path)
case donut.InvalidUploadID: case donut.InvalidUploadID:
writeErrorResponse(w, req, NoSuchUpload, acceptsContentType, req.URL.Path) writeErrorResponse(w, req, NoSuchUpload, acceptsContentType, req.URL.Path)
default: default:
@ -505,6 +515,8 @@ func (api Minio) ListObjectPartsHandler(w http.ResponseWriter, req *http.Request
// write body // write body
w.Write(encodedSuccessResponse) w.Write(encodedSuccessResponse)
} }
case donut.SignatureDoesNotMatch:
writeErrorResponse(w, req, SignatureDoesNotMatch, acceptsContentType, req.URL.Path)
case donut.InvalidUploadID: case donut.InvalidUploadID:
writeErrorResponse(w, req, NoSuchUpload, acceptsContentType, req.URL.Path) writeErrorResponse(w, req, NoSuchUpload, acceptsContentType, req.URL.Path)
default: default:

@ -35,7 +35,7 @@ func StripAccessKeyID(ah string) (string, error) {
if ah == "" { if ah == "" {
return "", errors.New("Missing auth header") return "", errors.New("Missing auth header")
} }
authFields := strings.Split(ah, ",") authFields := strings.Split(strings.TrimSpace(ah), ",")
if len(authFields) != 3 { if len(authFields) != 3 {
return "", errors.New("Missing fields in Auth header") return "", errors.New("Missing fields in Auth header")
} }
@ -46,17 +46,17 @@ func StripAccessKeyID(ah string) (string, error) {
if authPrefixFields[0] != authHeaderPrefix { if authPrefixFields[0] != authHeaderPrefix {
return "", errors.New("Missing fields is Auth header") return "", errors.New("Missing fields is Auth header")
} }
credentials := strings.Split(authPrefixFields[1], "=") credentials := strings.Split(strings.TrimSpace(authPrefixFields[1]), "=")
if len(credentials) != 2 { if len(credentials) != 2 {
return "", errors.New("Missing fields in Auth header") 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") 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") 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) { if !auth.IsValidAccessKey(accessKeyID) {
return "", errors.New("Invalid access key") return "", errors.New("Invalid access key")
} }

Loading…
Cancel
Save