mirror of
https://github.com/minio/minio.git
synced 2024-12-24 22:25:54 -05:00
parent
bba562235b
commit
97f2bc26b9
@ -139,6 +139,7 @@ const (
|
|||||||
ErrSlowDown
|
ErrSlowDown
|
||||||
ErrInvalidPrefixMarker
|
ErrInvalidPrefixMarker
|
||||||
ErrBadRequest
|
ErrBadRequest
|
||||||
|
ErrKeyTooLongError
|
||||||
// Add new error codes here.
|
// Add new error codes here.
|
||||||
|
|
||||||
// SSE-S3 related API errors
|
// SSE-S3 related API errors
|
||||||
@ -187,6 +188,7 @@ const (
|
|||||||
ErrRequestBodyParse
|
ErrRequestBodyParse
|
||||||
ErrObjectExistsAsDirectory
|
ErrObjectExistsAsDirectory
|
||||||
ErrInvalidObjectName
|
ErrInvalidObjectName
|
||||||
|
ErrInvalidObjectNamePrefixSlash
|
||||||
ErrInvalidResourceName
|
ErrInvalidResourceName
|
||||||
ErrServerNotInitialized
|
ErrServerNotInitialized
|
||||||
ErrOperationTimedOut
|
ErrOperationTimedOut
|
||||||
@ -682,6 +684,11 @@ var errorCodes = errorCodeMap{
|
|||||||
Description: "400 BadRequest",
|
Description: "400 BadRequest",
|
||||||
HTTPStatusCode: http.StatusBadRequest,
|
HTTPStatusCode: http.StatusBadRequest,
|
||||||
},
|
},
|
||||||
|
ErrKeyTooLongError: {
|
||||||
|
Code: "KeyTooLongError",
|
||||||
|
Description: "Your key is too long",
|
||||||
|
HTTPStatusCode: http.StatusBadRequest,
|
||||||
|
},
|
||||||
|
|
||||||
// FIXME: Actual XML error response also contains the header which missed in list of signed header parameters.
|
// FIXME: Actual XML error response also contains the header which missed in list of signed header parameters.
|
||||||
ErrUnsignedHeaders: {
|
ErrUnsignedHeaders: {
|
||||||
@ -885,6 +892,11 @@ var errorCodes = errorCodeMap{
|
|||||||
Description: "Object name contains unsupported characters.",
|
Description: "Object name contains unsupported characters.",
|
||||||
HTTPStatusCode: http.StatusBadRequest,
|
HTTPStatusCode: http.StatusBadRequest,
|
||||||
},
|
},
|
||||||
|
ErrInvalidObjectNamePrefixSlash: {
|
||||||
|
Code: "XMinioInvalidObjectName",
|
||||||
|
Description: "Object name contains a leading slash.",
|
||||||
|
HTTPStatusCode: http.StatusBadRequest,
|
||||||
|
},
|
||||||
ErrInvalidResourceName: {
|
ErrInvalidResourceName: {
|
||||||
Code: "XMinioInvalidResourceName",
|
Code: "XMinioInvalidResourceName",
|
||||||
Description: "Resource name contains bad components such as \"..\" or \".\".",
|
Description: "Resource name contains bad components such as \"..\" or \".\".",
|
||||||
@ -1579,6 +1591,8 @@ func toAPIErrorCode(ctx context.Context, err error) (apiErr APIErrorCode) {
|
|||||||
apiErr = ErrMethodNotAllowed
|
apiErr = ErrMethodNotAllowed
|
||||||
case ObjectNameInvalid:
|
case ObjectNameInvalid:
|
||||||
apiErr = ErrInvalidObjectName
|
apiErr = ErrInvalidObjectName
|
||||||
|
case ObjectNamePrefixAsSlash:
|
||||||
|
apiErr = ErrInvalidObjectNamePrefixSlash
|
||||||
case InvalidUploadID:
|
case InvalidUploadID:
|
||||||
apiErr = ErrNoSuchUpload
|
apiErr = ErrNoSuchUpload
|
||||||
case InvalidPart:
|
case InvalidPart:
|
||||||
@ -1639,6 +1653,8 @@ func toAPIErrorCode(ctx context.Context, err error) (apiErr APIErrorCode) {
|
|||||||
apiErr = ErrBackendDown
|
apiErr = ErrBackendDown
|
||||||
case crypto.Error:
|
case crypto.Error:
|
||||||
apiErr = ErrObjectTampered
|
apiErr = ErrObjectTampered
|
||||||
|
case ObjectNameTooLong:
|
||||||
|
apiErr = ErrKeyTooLongError
|
||||||
default:
|
default:
|
||||||
var ie, iw int
|
var ie, iw int
|
||||||
// This work-around is to handle the issue golang/go#30648
|
// This work-around is to handle the issue golang/go#30648
|
||||||
|
@ -269,11 +269,27 @@ func (e BucketNameInvalid) Error() string {
|
|||||||
// ObjectNameInvalid - object name provided is invalid.
|
// ObjectNameInvalid - object name provided is invalid.
|
||||||
type ObjectNameInvalid GenericError
|
type ObjectNameInvalid GenericError
|
||||||
|
|
||||||
|
// ObjectNameTooLong - object name too long.
|
||||||
|
type ObjectNameTooLong GenericError
|
||||||
|
|
||||||
|
// ObjectNamePrefixAsSlash - object name has a slash as prefix.
|
||||||
|
type ObjectNamePrefixAsSlash GenericError
|
||||||
|
|
||||||
// Return string an error formatted as the given text.
|
// Return string an error formatted as the given text.
|
||||||
func (e ObjectNameInvalid) Error() string {
|
func (e ObjectNameInvalid) Error() string {
|
||||||
return "Object name invalid: " + e.Bucket + "#" + e.Object
|
return "Object name invalid: " + e.Bucket + "#" + e.Object
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return string an error formatted as the given text.
|
||||||
|
func (e ObjectNameTooLong) Error() string {
|
||||||
|
return "Object name too long: " + e.Bucket + "#" + e.Object
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return string an error formatted as the given text.
|
||||||
|
func (e ObjectNamePrefixAsSlash) Error() string {
|
||||||
|
return "Object name contains forward slash as pefix: " + e.Bucket + "#" + e.Object
|
||||||
|
}
|
||||||
|
|
||||||
// AllAccessDisabled All access to this object has been disabled
|
// AllAccessDisabled All access to this object has been disabled
|
||||||
type AllAccessDisabled GenericError
|
type AllAccessDisabled GenericError
|
||||||
|
|
||||||
|
@ -166,18 +166,18 @@ func checkObjectArgs(ctx context.Context, bucket, object string, obj ObjectLayer
|
|||||||
if err := checkBucketExist(ctx, bucket, obj); err != nil {
|
if err := checkBucketExist(ctx, bucket, obj); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := checkObjectNameForLengthAndSlash(bucket, object); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
// Validates object name validity after bucket exists.
|
// Validates object name validity after bucket exists.
|
||||||
if !IsValidObjectName(object) {
|
if !IsValidObjectName(object) {
|
||||||
logger.LogIf(ctx, ObjectNameInvalid{
|
|
||||||
Bucket: bucket,
|
|
||||||
Object: object,
|
|
||||||
})
|
|
||||||
|
|
||||||
return ObjectNameInvalid{
|
return ObjectNameInvalid{
|
||||||
Bucket: bucket,
|
Bucket: bucket,
|
||||||
Object: object,
|
Object: object,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,8 +192,10 @@ func checkPutObjectArgs(ctx context.Context, bucket, object string, obj ObjectLa
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := checkObjectNameForLengthAndSlash(bucket, object); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
if len(object) == 0 ||
|
if len(object) == 0 ||
|
||||||
hasPrefix(object, slashSeparator) ||
|
|
||||||
(hasSuffix(object, slashSeparator) && size != 0) ||
|
(hasSuffix(object, slashSeparator) && size != 0) ||
|
||||||
!IsValidObjectPrefix(object) {
|
!IsValidObjectPrefix(object) {
|
||||||
return ObjectNameInvalid{
|
return ObjectNameInvalid{
|
||||||
|
@ -136,7 +136,7 @@ func IsValidObjectName(object string) bool {
|
|||||||
if len(object) == 0 {
|
if len(object) == 0 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if hasSuffix(object, slashSeparator) || hasPrefix(object, slashSeparator) {
|
if hasSuffix(object, slashSeparator) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return IsValidObjectPrefix(object)
|
return IsValidObjectPrefix(object)
|
||||||
@ -148,9 +148,6 @@ func IsValidObjectPrefix(object string) bool {
|
|||||||
if hasBadPathComponent(object) {
|
if hasBadPathComponent(object) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if len(object) > 1024 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if !utf8.ValidString(object) {
|
if !utf8.ValidString(object) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -161,6 +158,25 @@ func IsValidObjectPrefix(object string) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// checkObjectNameForLengthAndSlash -check for the validity of object name length and prefis as slash
|
||||||
|
func checkObjectNameForLengthAndSlash(bucket, object string) error {
|
||||||
|
// Check for the length of object name
|
||||||
|
if len(object) > 1024 {
|
||||||
|
return ObjectNameTooLong{
|
||||||
|
Bucket: bucket,
|
||||||
|
Object: object,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Check for slash as prefix in object name
|
||||||
|
if hasPrefix(object, slashSeparator) {
|
||||||
|
return ObjectNamePrefixAsSlash{
|
||||||
|
Bucket: bucket,
|
||||||
|
Object: object,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Slash separator.
|
// Slash separator.
|
||||||
const slashSeparator = "/"
|
const slashSeparator = "/"
|
||||||
|
|
||||||
|
@ -113,7 +113,6 @@ func TestIsValidObjectName(t *testing.T) {
|
|||||||
// passing invalid object names.
|
// passing invalid object names.
|
||||||
{"", false},
|
{"", false},
|
||||||
{"a/b/c/", false},
|
{"a/b/c/", false},
|
||||||
{"/a/b/c", false},
|
|
||||||
{"../../etc", false},
|
{"../../etc", false},
|
||||||
{"../../", false},
|
{"../../", false},
|
||||||
{"/../../etc", false},
|
{"/../../etc", false},
|
||||||
|
@ -1354,7 +1354,37 @@ func (s *TestSuiteCommon) TestPutObjectLongName(c *check) {
|
|||||||
response, err = client.Do(request)
|
response, err = client.Do(request)
|
||||||
c.Assert(err, nil)
|
c.Assert(err, nil)
|
||||||
c.Assert(response.StatusCode, http.StatusOK)
|
c.Assert(response.StatusCode, http.StatusOK)
|
||||||
// make long object name.
|
|
||||||
|
//make long object name.
|
||||||
|
longObjName = fmt.Sprintf("%0255d/%0255d/%0255d/%0255d/%0255d", 1, 1, 1, 1, 1)
|
||||||
|
if IsDocker() || IsKubernetes() {
|
||||||
|
longObjName = fmt.Sprintf("%0242d/%0242d/%0242d/%0242d/%0242d", 1, 1, 1, 1, 1)
|
||||||
|
}
|
||||||
|
// create new HTTP request to insert the object.
|
||||||
|
buffer = bytes.NewReader([]byte("hello world"))
|
||||||
|
request, err = newTestSignedRequest("PUT", getPutObjectURL(s.endPoint, bucketName, longObjName),
|
||||||
|
int64(buffer.Len()), buffer, s.accessKey, s.secretKey, s.signer)
|
||||||
|
c.Assert(err, nil)
|
||||||
|
// execute the HTTP request.
|
||||||
|
response, err = client.Do(request)
|
||||||
|
c.Assert(err, nil)
|
||||||
|
c.Assert(response.StatusCode, http.StatusBadRequest)
|
||||||
|
verifyError(c, response, "KeyTooLongError", "Your key is too long", http.StatusBadRequest)
|
||||||
|
|
||||||
|
// make object name with prefix as slash
|
||||||
|
longObjName = fmt.Sprintf("/%0255d/%0255d", 1, 1)
|
||||||
|
buffer = bytes.NewReader([]byte("hello world"))
|
||||||
|
// create new HTTP request to insert the object.
|
||||||
|
request, err = newTestSignedRequest("PUT", getPutObjectURL(s.endPoint, bucketName, longObjName),
|
||||||
|
int64(buffer.Len()), buffer, s.accessKey, s.secretKey, s.signer)
|
||||||
|
c.Assert(err, nil)
|
||||||
|
// execute the HTTP request.
|
||||||
|
response, err = client.Do(request)
|
||||||
|
c.Assert(err, nil)
|
||||||
|
c.Assert(response.StatusCode, http.StatusBadRequest)
|
||||||
|
verifyError(c, response, "XMinioInvalidObjectName", "Object name contains a leading slash.", http.StatusBadRequest)
|
||||||
|
|
||||||
|
//make object name as unsuported
|
||||||
longObjName = fmt.Sprintf("%0256d", 1)
|
longObjName = fmt.Sprintf("%0256d", 1)
|
||||||
buffer = bytes.NewReader([]byte("hello world"))
|
buffer = bytes.NewReader([]byte("hello world"))
|
||||||
request, err = newTestSignedRequest("PUT", getPutObjectURL(s.endPoint, bucketName, longObjName),
|
request, err = newTestSignedRequest("PUT", getPutObjectURL(s.endPoint, bucketName, longObjName),
|
||||||
|
Loading…
Reference in New Issue
Block a user