web: Validate if bucket names are reserved (#3841)

Both '.minio.sys' and 'minio' should be never allowed
to be created from web-ui and then fail to list it
by filtering them out.

Fixes #3840
master
Harshavardhana 8 years ago committed by GitHub
parent cddc684559
commit e5d4e7aa9d
  1. 11
      cmd/generic-handlers.go
  2. 12
      cmd/object-api-utils.go
  3. 4
      cmd/typed-errors.go
  4. 22
      cmd/web-handlers.go
  5. 2
      cmd/web-handlers_test.go

@ -20,7 +20,6 @@ import (
"bufio" "bufio"
"net" "net"
"net/http" "net/http"
"path"
"strings" "strings"
"time" "time"
@ -161,17 +160,17 @@ func (h cacheControlHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// Adds verification for incoming paths. // Adds verification for incoming paths.
type minioPrivateBucketHandler struct { type minioPrivateBucketHandler struct {
handler http.Handler handler http.Handler
reservedBucketPath string
} }
func setPrivateBucketHandler(h http.Handler) http.Handler { func setPrivateBucketHandler(h http.Handler) http.Handler {
return minioPrivateBucketHandler{h, minioReservedBucketPath} return minioPrivateBucketHandler{h}
} }
func (h minioPrivateBucketHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { func (h minioPrivateBucketHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// For all non browser requests, reject access to 'reservedBucketPath'. // For all non browser requests, reject access to 'minioReservedBucketPath'.
if !guessIsBrowserReq(r) && path.Clean(r.URL.Path) == h.reservedBucketPath { bucketName, _ := urlPath2BucketObjectName(r.URL)
if !guessIsBrowserReq(r) && isMinioReservedBucket(bucketName) && isMinioMetaBucket(bucketName) {
writeErrorResponse(w, ErrAllAccessDisabled, r.URL) writeErrorResponse(w, ErrAllAccessDisabled, r.URL)
return return
} }

@ -194,7 +194,17 @@ func isReservedOrInvalidBucket(bucketEntry string) bool {
if !IsValidBucketName(bucketEntry) { if !IsValidBucketName(bucketEntry) {
return true return true
} }
return bucketEntry == minioMetaBucket || bucketEntry == minioReservedBucket return isMinioMetaBucket(bucketEntry) || isMinioReservedBucket(bucketEntry)
}
// Returns true if input bucket is a reserved minio meta bucket '.minio.sys'.
func isMinioMetaBucket(bucketName string) bool {
return bucketName == minioMetaBucket
}
// Returns true if input bucket is a reserved minio bucket 'minio'.
func isMinioReservedBucket(bucketName string) bool {
return bucketName == minioReservedBucket
} }
// byBucketName is a collection satisfying sort.Interface. // byBucketName is a collection satisfying sort.Interface.

@ -50,3 +50,7 @@ var errServerVersionMismatch = errors.New("Server versions do not match")
// errServerTimeMismatch - server times are too far apart. // errServerTimeMismatch - server times are too far apart.
var errServerTimeMismatch = errors.New("Server times are too far apart") var errServerTimeMismatch = errors.New("Server times are too far apart")
// errReservedBucket - bucket name is reserved for Minio, usually
// returned for 'minio', '.minio.sys'
var errReservedBucket = errors.New("All access to this bucket is disabled")

@ -113,7 +113,7 @@ type MakeBucketArgs struct {
BucketName string `json:"bucketName"` BucketName string `json:"bucketName"`
} }
// MakeBucket - make a bucket. // MakeBucket - creates a new bucket.
func (web *webAPIHandlers) MakeBucket(r *http.Request, args *MakeBucketArgs, reply *WebGenericRep) error { func (web *webAPIHandlers) MakeBucket(r *http.Request, args *MakeBucketArgs, reply *WebGenericRep) error {
objectAPI := web.ObjectAPI() objectAPI := web.ObjectAPI()
if objectAPI == nil { if objectAPI == nil {
@ -122,12 +122,19 @@ func (web *webAPIHandlers) MakeBucket(r *http.Request, args *MakeBucketArgs, rep
if !isHTTPRequestValid(r) { if !isHTTPRequestValid(r) {
return toJSONError(errAuthentication) return toJSONError(errAuthentication)
} }
// Check if bucket is a reserved bucket name.
if isMinioMetaBucket(args.BucketName) || isMinioReservedBucket(args.BucketName) {
return toJSONError(errReservedBucket)
}
bucketLock := globalNSMutex.NewNSLock(args.BucketName, "") bucketLock := globalNSMutex.NewNSLock(args.BucketName, "")
bucketLock.Lock() bucketLock.Lock()
defer bucketLock.Unlock() defer bucketLock.Unlock()
if err := objectAPI.MakeBucket(args.BucketName); err != nil { if err := objectAPI.MakeBucket(args.BucketName); err != nil {
return toJSONError(err, args.BucketName) return toJSONError(err, args.BucketName)
} }
reply.UIVersion = browser.UIVersion reply.UIVersion = browser.UIVersion
return nil return nil
} }
@ -890,6 +897,13 @@ func toJSONError(err error, params ...string) (jerr *json2.Error) {
Message: apiErr.Description, Message: apiErr.Description,
} }
switch apiErr.Code { switch apiErr.Code {
// Reserved bucket name provided.
case "AllAccessDisabled":
if len(params) > 0 {
jerr = &json2.Error{
Message: fmt.Sprintf("All access to this bucket %s has been disabled.", params[0]),
}
}
// Bucket name invalid with custom error message. // Bucket name invalid with custom error message.
case "InvalidBucketName": case "InvalidBucketName":
if len(params) > 0 { if len(params) > 0 {
@ -961,6 +975,12 @@ func toWebAPIError(err error) APIError {
HTTPStatusCode: http.StatusMethodNotAllowed, HTTPStatusCode: http.StatusMethodNotAllowed,
Description: err.Error(), Description: err.Error(),
} }
} else if err == errReservedBucket {
return APIError{
Code: "AllAccessDisabled",
HTTPStatusCode: http.StatusForbidden,
Description: err.Error(),
}
} }
// Convert error type to api error code. // Convert error type to api error code.
var apiErrCode APIErrorCode var apiErrCode APIErrorCode

@ -265,6 +265,8 @@ func testMakeBucketWebHandler(obj ObjectLayer, instanceType string, t TestErrHan
{"", false}, {"", false},
{".", false}, {".", false},
{"ab", false}, {"ab", false},
{"minio", false},
{".minio.sys", false},
{bucketName, true}, {bucketName, true},
} }

Loading…
Cancel
Save