| 
									
										
										
										
											2021-04-19 03:41:13 +08:00
										 |  |  | // Copyright (c) 2015-2021 MinIO, Inc.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // This file is part of MinIO Object Storage stack
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // This program is free software: you can redistribute it and/or modify
 | 
					
						
							|  |  |  | // it under the terms of the GNU Affero General Public License as published by
 | 
					
						
							|  |  |  | // the Free Software Foundation, either version 3 of the License, or
 | 
					
						
							|  |  |  | // (at your option) any later version.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // This program is distributed in the hope that it will be useful
 | 
					
						
							|  |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
					
						
							|  |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
					
						
							|  |  |  | // GNU Affero General Public License for more details.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // You should have received a copy of the GNU Affero General Public License
 | 
					
						
							|  |  |  | // along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
					
						
							| 
									
										
										
										
											2016-12-02 15:15:17 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | package cmd | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-26 03:58:29 +08:00
										 |  |  | import ( | 
					
						
							| 
									
										
										
										
											2018-03-16 04:27:16 +08:00
										 |  |  | 	"context" | 
					
						
							| 
									
										
										
										
											2020-05-14 14:55:38 +08:00
										 |  |  | 	"runtime" | 
					
						
							|  |  |  | 	"strings" | 
					
						
							| 
									
										
										
										
											2018-03-16 04:27:16 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-14 17:40:05 +08:00
										 |  |  | 	"github.com/google/uuid" | 
					
						
							| 
									
										
										
										
											2020-07-15 00:38:05 +08:00
										 |  |  | 	"github.com/minio/minio-go/v7/pkg/s3utils" | 
					
						
							| 
									
										
										
										
											2021-06-02 05:59:40 +08:00
										 |  |  | 	"github.com/minio/minio/internal/logger" | 
					
						
							| 
									
										
										
										
											2017-11-26 03:58:29 +08:00
										 |  |  | ) | 
					
						
							| 
									
										
										
										
											2016-12-02 15:15:17 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | // Checks on GetObject arguments, bucket and object.
 | 
					
						
							| 
									
										
										
										
											2018-04-06 06:04:40 +08:00
										 |  |  | func checkGetObjArgs(ctx context.Context, bucket, object string) error { | 
					
						
							|  |  |  | 	return checkBucketAndObjectNames(ctx, bucket, object) | 
					
						
							| 
									
										
										
										
											2016-12-02 15:15:17 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Checks on DeleteObject arguments, bucket and object.
 | 
					
						
							| 
									
										
										
										
											2018-04-06 06:04:40 +08:00
										 |  |  | func checkDelObjArgs(ctx context.Context, bucket, object string) error { | 
					
						
							|  |  |  | 	return checkBucketAndObjectNames(ctx, bucket, object) | 
					
						
							| 
									
										
										
										
											2016-12-02 15:15:17 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Checks bucket and object name validity, returns nil if both are valid.
 | 
					
						
							| 
									
										
										
										
											2018-04-06 06:04:40 +08:00
										 |  |  | func checkBucketAndObjectNames(ctx context.Context, bucket, object string) error { | 
					
						
							| 
									
										
										
										
											2016-12-02 15:15:17 +08:00
										 |  |  | 	// Verify if bucket is valid.
 | 
					
						
							| 
									
										
										
										
											2019-08-21 11:40:52 +08:00
										 |  |  | 	if !isMinioMetaBucketName(bucket) && s3utils.CheckValidBucketName(bucket) != nil { | 
					
						
							| 
									
										
										
										
											2018-04-06 06:04:40 +08:00
										 |  |  | 		logger.LogIf(ctx, BucketNameInvalid{Bucket: bucket}) | 
					
						
							|  |  |  | 		return BucketNameInvalid{Bucket: bucket} | 
					
						
							| 
									
										
										
										
											2016-12-02 15:15:17 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	// Verify if object is valid.
 | 
					
						
							| 
									
										
										
										
											2018-01-30 10:43:13 +08:00
										 |  |  | 	if len(object) == 0 { | 
					
						
							| 
									
										
										
										
											2018-04-06 06:04:40 +08:00
										 |  |  | 		logger.LogIf(ctx, ObjectNameInvalid{Bucket: bucket, Object: object}) | 
					
						
							|  |  |  | 		return ObjectNameInvalid{Bucket: bucket, Object: object} | 
					
						
							| 
									
										
										
										
											2018-01-30 10:43:13 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	if !IsValidObjectPrefix(object) { | 
					
						
							| 
									
										
										
										
											2018-04-06 06:04:40 +08:00
										 |  |  | 		logger.LogIf(ctx, ObjectNameInvalid{Bucket: bucket, Object: object}) | 
					
						
							|  |  |  | 		return ObjectNameInvalid{Bucket: bucket, Object: object} | 
					
						
							| 
									
										
										
										
											2016-12-02 15:15:17 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-05-14 14:55:38 +08:00
										 |  |  | 	if runtime.GOOS == globalWindowsOSName && strings.Contains(object, "\\") { | 
					
						
							|  |  |  | 		// Objects cannot be contain \ in Windows and is listed as `Characters to Avoid`.
 | 
					
						
							|  |  |  | 		return ObjectNameInvalid{Bucket: bucket, Object: object} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-12-02 15:15:17 +08:00
										 |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Checks for all ListObjects arguments validity.
 | 
					
						
							| 
									
										
										
										
											2020-09-11 00:18:19 +08:00
										 |  |  | func checkListObjsArgs(ctx context.Context, bucket, prefix, marker string, obj getBucketInfoI) error { | 
					
						
							| 
									
										
										
										
											2016-12-02 15:15:17 +08:00
										 |  |  | 	// Verify if bucket exists before validating object name.
 | 
					
						
							|  |  |  | 	// This is done on purpose since the order of errors is
 | 
					
						
							|  |  |  | 	// important here bucket does not exist error should
 | 
					
						
							|  |  |  | 	// happen before we return an error for invalid object name.
 | 
					
						
							|  |  |  | 	// FIXME: should be moved to handler layer.
 | 
					
						
							| 
									
										
										
										
											2018-04-06 06:04:40 +08:00
										 |  |  | 	if err := checkBucketExist(ctx, bucket, obj); err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							| 
									
										
										
										
											2016-12-02 15:15:17 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	// Validates object prefix validity after bucket exists.
 | 
					
						
							|  |  |  | 	if !IsValidObjectPrefix(prefix) { | 
					
						
							| 
									
										
										
										
											2018-04-06 06:04:40 +08:00
										 |  |  | 		logger.LogIf(ctx, ObjectNameInvalid{ | 
					
						
							| 
									
										
										
										
											2016-12-02 15:15:17 +08:00
										 |  |  | 			Bucket: bucket, | 
					
						
							|  |  |  | 			Object: prefix, | 
					
						
							|  |  |  | 		}) | 
					
						
							| 
									
										
										
										
											2018-04-06 06:04:40 +08:00
										 |  |  | 		return ObjectNameInvalid{ | 
					
						
							|  |  |  | 			Bucket: bucket, | 
					
						
							|  |  |  | 			Object: prefix, | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-12-02 15:15:17 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	// Verify if marker has prefix.
 | 
					
						
							| 
									
										
										
										
											2019-12-06 15:16:06 +08:00
										 |  |  | 	if marker != "" && !HasPrefix(marker, prefix) { | 
					
						
							| 
									
										
										
										
											2018-04-06 06:04:40 +08:00
										 |  |  | 		logger.LogIf(ctx, InvalidMarkerPrefixCombination{ | 
					
						
							| 
									
										
										
										
											2016-12-02 15:15:17 +08:00
										 |  |  | 			Marker: marker, | 
					
						
							|  |  |  | 			Prefix: prefix, | 
					
						
							|  |  |  | 		}) | 
					
						
							| 
									
										
										
										
											2018-04-06 06:04:40 +08:00
										 |  |  | 		return InvalidMarkerPrefixCombination{ | 
					
						
							|  |  |  | 			Marker: marker, | 
					
						
							|  |  |  | 			Prefix: prefix, | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-12-02 15:15:17 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Checks for all ListMultipartUploads arguments validity.
 | 
					
						
							| 
									
										
										
										
											2018-04-06 06:04:40 +08:00
										 |  |  | func checkListMultipartArgs(ctx context.Context, bucket, prefix, keyMarker, uploadIDMarker, delimiter string, obj ObjectLayer) error { | 
					
						
							| 
									
										
										
										
											2020-02-25 23:52:28 +08:00
										 |  |  | 	if err := checkListObjsArgs(ctx, bucket, prefix, keyMarker, obj); err != nil { | 
					
						
							| 
									
										
										
										
											2016-12-02 15:15:17 +08:00
										 |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if uploadIDMarker != "" { | 
					
						
							| 
									
										
										
										
											2019-12-06 15:16:06 +08:00
										 |  |  | 		if HasSuffix(keyMarker, SlashSeparator) { | 
					
						
							| 
									
										
										
										
											2018-04-06 06:04:40 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			logger.LogIf(ctx, InvalidUploadIDKeyCombination{ | 
					
						
							| 
									
										
										
										
											2016-12-02 15:15:17 +08:00
										 |  |  | 				UploadIDMarker: uploadIDMarker, | 
					
						
							|  |  |  | 				KeyMarker:      keyMarker, | 
					
						
							|  |  |  | 			}) | 
					
						
							| 
									
										
										
										
											2018-04-06 06:04:40 +08:00
										 |  |  | 			return InvalidUploadIDKeyCombination{ | 
					
						
							|  |  |  | 				UploadIDMarker: uploadIDMarker, | 
					
						
							|  |  |  | 				KeyMarker:      keyMarker, | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2016-12-02 15:15:17 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-04-14 17:40:05 +08:00
										 |  |  | 		if _, err := uuid.Parse(uploadIDMarker); err != nil { | 
					
						
							| 
									
										
										
										
											2018-04-06 06:04:40 +08:00
										 |  |  | 			logger.LogIf(ctx, err) | 
					
						
							|  |  |  | 			return MalformedUploadID{ | 
					
						
							|  |  |  | 				UploadID: uploadIDMarker, | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2016-12-02 15:15:17 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Checks for NewMultipartUpload arguments validity, also validates if bucket exists.
 | 
					
						
							| 
									
										
										
										
											2018-04-06 06:04:40 +08:00
										 |  |  | func checkNewMultipartArgs(ctx context.Context, bucket, object string, obj ObjectLayer) error { | 
					
						
							|  |  |  | 	return checkObjectArgs(ctx, bucket, object, obj) | 
					
						
							| 
									
										
										
										
											2016-12-02 15:15:17 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Checks for PutObjectPart arguments validity, also validates if bucket exists.
 | 
					
						
							| 
									
										
										
										
											2018-04-06 06:04:40 +08:00
										 |  |  | func checkPutObjectPartArgs(ctx context.Context, bucket, object string, obj ObjectLayer) error { | 
					
						
							|  |  |  | 	return checkObjectArgs(ctx, bucket, object, obj) | 
					
						
							| 
									
										
										
										
											2016-12-02 15:15:17 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Checks for ListParts arguments validity, also validates if bucket exists.
 | 
					
						
							| 
									
										
										
										
											2018-04-06 06:04:40 +08:00
										 |  |  | func checkListPartsArgs(ctx context.Context, bucket, object string, obj ObjectLayer) error { | 
					
						
							|  |  |  | 	return checkObjectArgs(ctx, bucket, object, obj) | 
					
						
							| 
									
										
										
										
											2016-12-02 15:15:17 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Checks for CompleteMultipartUpload arguments validity, also validates if bucket exists.
 | 
					
						
							| 
									
										
										
										
											2018-04-06 06:04:40 +08:00
										 |  |  | func checkCompleteMultipartArgs(ctx context.Context, bucket, object string, obj ObjectLayer) error { | 
					
						
							|  |  |  | 	return checkObjectArgs(ctx, bucket, object, obj) | 
					
						
							| 
									
										
										
										
											2016-12-02 15:15:17 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Checks for AbortMultipartUpload arguments validity, also validates if bucket exists.
 | 
					
						
							| 
									
										
										
										
											2018-04-06 06:04:40 +08:00
										 |  |  | func checkAbortMultipartArgs(ctx context.Context, bucket, object string, obj ObjectLayer) error { | 
					
						
							|  |  |  | 	return checkObjectArgs(ctx, bucket, object, obj) | 
					
						
							| 
									
										
										
										
											2016-12-02 15:15:17 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-10 07:19:30 +08:00
										 |  |  | // Checks Object arguments validity, also validates if bucket exists.
 | 
					
						
							| 
									
										
										
										
											2018-04-06 06:04:40 +08:00
										 |  |  | func checkObjectArgs(ctx context.Context, bucket, object string, obj ObjectLayer) error { | 
					
						
							| 
									
										
										
										
											2016-12-02 15:15:17 +08:00
										 |  |  | 	// Verify if bucket exists before validating object name.
 | 
					
						
							|  |  |  | 	// This is done on purpose since the order of errors is
 | 
					
						
							|  |  |  | 	// important here bucket does not exist error should
 | 
					
						
							|  |  |  | 	// happen before we return an error for invalid object name.
 | 
					
						
							|  |  |  | 	// FIXME: should be moved to handler layer.
 | 
					
						
							| 
									
										
										
										
											2018-04-06 06:04:40 +08:00
										 |  |  | 	if err := checkBucketExist(ctx, bucket, obj); err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							| 
									
										
										
										
											2016-12-02 15:15:17 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-07-12 12:38:12 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if err := checkObjectNameForLengthAndSlash(bucket, object); err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-02-06 10:59:38 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-02 15:15:17 +08:00
										 |  |  | 	// Validates object name validity after bucket exists.
 | 
					
						
							|  |  |  | 	if !IsValidObjectName(object) { | 
					
						
							| 
									
										
										
										
											2018-04-06 06:04:40 +08:00
										 |  |  | 		return ObjectNameInvalid{ | 
					
						
							|  |  |  | 			Bucket: bucket, | 
					
						
							|  |  |  | 			Object: object, | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-12-02 15:15:17 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-07-12 12:38:12 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-02 15:15:17 +08:00
										 |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-10 07:19:30 +08:00
										 |  |  | // Checks for PutObject arguments validity, also validates if bucket exists.
 | 
					
						
							| 
									
										
										
										
											2020-10-07 03:03:57 +08:00
										 |  |  | func checkPutObjectArgs(ctx context.Context, bucket, object string, obj getBucketInfoI) error { | 
					
						
							| 
									
										
										
										
											2018-02-10 07:19:30 +08:00
										 |  |  | 	// Verify if bucket exists before validating object name.
 | 
					
						
							|  |  |  | 	// This is done on purpose since the order of errors is
 | 
					
						
							|  |  |  | 	// important here bucket does not exist error should
 | 
					
						
							|  |  |  | 	// happen before we return an error for invalid object name.
 | 
					
						
							|  |  |  | 	// FIXME: should be moved to handler layer.
 | 
					
						
							| 
									
										
										
										
											2018-04-06 06:04:40 +08:00
										 |  |  | 	if err := checkBucketExist(ctx, bucket, obj); err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							| 
									
										
										
										
											2018-02-10 07:19:30 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-12 12:38:12 +08:00
										 |  |  | 	if err := checkObjectNameForLengthAndSlash(bucket, object); err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-02-10 07:19:30 +08:00
										 |  |  | 	if len(object) == 0 || | 
					
						
							|  |  |  | 		!IsValidObjectPrefix(object) { | 
					
						
							| 
									
										
										
										
											2018-04-06 06:04:40 +08:00
										 |  |  | 		return ObjectNameInvalid{ | 
					
						
							|  |  |  | 			Bucket: bucket, | 
					
						
							|  |  |  | 			Object: object, | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-02-10 07:19:30 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-11 00:18:19 +08:00
										 |  |  | type getBucketInfoI interface { | 
					
						
							| 
									
										
										
										
											2022-07-26 08:51:32 +08:00
										 |  |  | 	GetBucketInfo(ctx context.Context, bucket string, opts BucketOptions) (bucketInfo BucketInfo, err error) | 
					
						
							| 
									
										
										
										
											2020-09-11 00:18:19 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-02 15:15:17 +08:00
										 |  |  | // Checks whether bucket exists and returns appropriate error if not.
 | 
					
						
							| 
									
										
										
										
											2020-09-11 00:18:19 +08:00
										 |  |  | func checkBucketExist(ctx context.Context, bucket string, obj getBucketInfoI) error { | 
					
						
							| 
									
										
										
										
											2022-07-26 08:51:32 +08:00
										 |  |  | 	_, err := obj.GetBucketInfo(ctx, bucket, BucketOptions{}) | 
					
						
							| 
									
										
										
										
											2016-12-02 15:15:17 +08:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2018-04-11 00:36:37 +08:00
										 |  |  | 		return err | 
					
						
							| 
									
										
										
										
											2016-12-02 15:15:17 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } |