mirror of
https://github.com/minio/minio.git
synced 2025-04-11 23:12:12 -04:00
Fix check for bucket name: (#3832)
* Do not allow bucket names with adjacent hypen and periods. * Improve performance by eliminating the usage of regular expressions.
This commit is contained in:
parent
6c00a57a7c
commit
6df7bc42b8
@ -21,7 +21,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"path"
|
"path"
|
||||||
"regexp"
|
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
@ -38,12 +37,10 @@ const (
|
|||||||
minioMetaMultipartBucket = minioMetaBucket + "/" + mpartMetaPrefix
|
minioMetaMultipartBucket = minioMetaBucket + "/" + mpartMetaPrefix
|
||||||
// Minio Tmp meta prefix.
|
// Minio Tmp meta prefix.
|
||||||
minioMetaTmpBucket = minioMetaBucket + "/tmp"
|
minioMetaTmpBucket = minioMetaBucket + "/tmp"
|
||||||
|
// DNS separator (period), used for bucket name validation.
|
||||||
|
dnsDelimiter = "."
|
||||||
)
|
)
|
||||||
|
|
||||||
// validBucket regexp.
|
|
||||||
var validBucket = regexp.MustCompile(`^[a-z0-9][a-z0-9\.\-]{1,61}[a-z0-9]$`)
|
|
||||||
var isIPAddress = regexp.MustCompile(`^(\d+\.){3}\d+$`)
|
|
||||||
|
|
||||||
// isMinioBucket returns true if given bucket is a Minio internal
|
// isMinioBucket returns true if given bucket is a Minio internal
|
||||||
// bucket and false otherwise.
|
// bucket and false otherwise.
|
||||||
func isMinioMetaBucketName(bucket string) bool {
|
func isMinioMetaBucketName(bucket string) bool {
|
||||||
@ -52,10 +49,13 @@ func isMinioMetaBucketName(bucket string) bool {
|
|||||||
bucket == minioMetaTmpBucket
|
bucket == minioMetaTmpBucket
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsValidBucketName verifies a bucket name in accordance with Amazon's
|
// IsValidBucketName verifies that a bucket name is in accordance with
|
||||||
// requirements. It must be 3-63 characters long, can contain dashes
|
// Amazon's requirements (i.e. DNS naming conventions). It must be 3-63
|
||||||
// and periods, but must begin and end with a lowercase letter or a number.
|
// characters long, and it must be a sequence of one or more labels
|
||||||
// See: http://docs.aws.amazon.com/AmazonS3/latest/dev/BucketRestrictions.html
|
// separated by periods. Each label can contain lowercase ascii
|
||||||
|
// letters, decimal digits and hyphens, but must not begin or end with
|
||||||
|
// a hyphen. See:
|
||||||
|
// http://docs.aws.amazon.com/AmazonS3/latest/dev/BucketRestrictions.html
|
||||||
func IsValidBucketName(bucket string) bool {
|
func IsValidBucketName(bucket string) bool {
|
||||||
// Special case when bucket is equal to one of the meta buckets.
|
// Special case when bucket is equal to one of the meta buckets.
|
||||||
if isMinioMetaBucketName(bucket) {
|
if isMinioMetaBucketName(bucket) {
|
||||||
@ -64,12 +64,39 @@ func IsValidBucketName(bucket string) bool {
|
|||||||
if len(bucket) < 3 || len(bucket) > 63 {
|
if len(bucket) < 3 || len(bucket) > 63 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if bucket[0] == '.' || bucket[len(bucket)-1] == '.' {
|
|
||||||
return false
|
// Split on dot and check each piece conforms to rules.
|
||||||
|
allNumbers := true
|
||||||
|
pieces := strings.Split(bucket, dnsDelimiter)
|
||||||
|
for _, piece := range pieces {
|
||||||
|
if len(piece) == 0 || piece[0] == '-' ||
|
||||||
|
piece[len(piece)-1] == '-' {
|
||||||
|
// Current piece has 0-length or starts or
|
||||||
|
// ends with a hyphen.
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// Now only need to check if each piece is a valid
|
||||||
|
// 'label' in AWS terminology and if the bucket looks
|
||||||
|
// like an IP address.
|
||||||
|
isNotNumber := false
|
||||||
|
for i := 0; i < len(piece); i++ {
|
||||||
|
switch {
|
||||||
|
case (piece[i] >= 'a' && piece[i] <= 'z' ||
|
||||||
|
piece[i] == '-'):
|
||||||
|
// Found a non-digit character, so
|
||||||
|
// this piece is not a number.
|
||||||
|
isNotNumber = true
|
||||||
|
case piece[i] >= '0' && piece[i] <= '9':
|
||||||
|
// Nothing to do.
|
||||||
|
default:
|
||||||
|
// Found invalid character.
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
allNumbers = allNumbers && !isNotNumber
|
||||||
}
|
}
|
||||||
return (validBucket.MatchString(bucket) &&
|
// Does the bucket name look like an IP address?
|
||||||
!isIPAddress.MatchString(bucket) &&
|
return !(len(pieces) == 4 && allNumbers)
|
||||||
!strings.Contains(bucket, ".."))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsValidObjectName verifies an object name in accordance with Amazon's
|
// IsValidObjectName verifies an object name in accordance with Amazon's
|
||||||
|
@ -41,6 +41,8 @@ func TestIsValidBucketName(t *testing.T) {
|
|||||||
{"testbucket", true},
|
{"testbucket", true},
|
||||||
{"1bucket", true},
|
{"1bucket", true},
|
||||||
{"bucket1", true},
|
{"bucket1", true},
|
||||||
|
{"a.b", true},
|
||||||
|
{"ab.a.bc", true},
|
||||||
// cases for which test should fail.
|
// cases for which test should fail.
|
||||||
// passing invalid bucket names.
|
// passing invalid bucket names.
|
||||||
{"------", false},
|
{"------", false},
|
||||||
@ -59,11 +61,14 @@ func TestIsValidBucketName(t *testing.T) {
|
|||||||
{"ends-with-a-dot.", false},
|
{"ends-with-a-dot.", false},
|
||||||
{"ends-with-a-dash-", false},
|
{"ends-with-a-dash-", false},
|
||||||
{"-starts-with-a-dash", false},
|
{"-starts-with-a-dash", false},
|
||||||
{"THIS-BEINGS-WITH-UPPERCASe", false},
|
{"THIS-BEGINS-WITH-UPPERCASe", false},
|
||||||
{"tHIS-ENDS-WITH-UPPERCASE", false},
|
{"tHIS-ENDS-WITH-UPPERCASE", false},
|
||||||
{"ThisBeginsAndEndsWithUpperCase", false},
|
{"ThisBeginsAndEndsWithUpperCasE", false},
|
||||||
{"una ñina", false},
|
{"una ñina", false},
|
||||||
{"lalalallalallalalalallalallalala-theString-size-is-greater-than-64", false},
|
{"dash-.may-not-appear-next-to-dot", false},
|
||||||
|
{"dash.-may-not-appear-next-to-dot", false},
|
||||||
|
{"dash-.-may-not-appear-next-to-dot", false},
|
||||||
|
{"lalalallalallalalalallalallalala-thestring-size-is-greater-than-63", false},
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, testCase := range testCases {
|
for i, testCase := range testCases {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user