| 
									
										
										
										
											2016-12-02 15:15:17 +08:00
										 |  |  | /* | 
					
						
							| 
									
										
										
										
											2019-04-10 02:39:42 +08:00
										 |  |  |  * MinIO Cloud Storage, (C) 2016 MinIO, Inc. | 
					
						
							| 
									
										
										
										
											2016-12-02 15:15:17 +08:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
					
						
							|  |  |  |  * you may not use this file except in compliance with the License. | 
					
						
							|  |  |  |  * You may obtain a copy of the License at | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *     http://www.apache.org/licenses/LICENSE-2.0
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Unless required by applicable law or agreed to in writing, software | 
					
						
							|  |  |  |  * distributed under the License is distributed on an "AS IS" BASIS, | 
					
						
							|  |  |  |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
					
						
							|  |  |  |  * See the License for the specific language governing permissions and | 
					
						
							|  |  |  |  * limitations under the License. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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" | 
					
						
							| 
									
										
										
										
											2018-04-06 06:04:40 +08:00
										 |  |  | 	"github.com/minio/minio/cmd/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-02-25 23:52:28 +08:00
										 |  |  | func checkListObjsArgs(ctx context.Context, bucket, prefix, marker 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
										 |  |  | 	} | 
					
						
							|  |  |  | 	// 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.
 | 
					
						
							| 
									
										
										
										
											2018-04-06 06:04:40 +08:00
										 |  |  | func checkPutObjectArgs(ctx context.Context, bucket, object string, obj ObjectLayer, size int64) 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 || | 
					
						
							| 
									
										
										
										
											2019-12-06 15:16:06 +08:00
										 |  |  | 		(HasSuffix(object, SlashSeparator) && size != 0) || | 
					
						
							| 
									
										
										
										
											2018-02-10 07:19:30 +08:00
										 |  |  | 		!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 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-02 15:15:17 +08:00
										 |  |  | // Checks whether bucket exists and returns appropriate error if not.
 | 
					
						
							| 
									
										
										
										
											2018-04-06 06:04:40 +08:00
										 |  |  | func checkBucketExist(ctx context.Context, bucket string, obj ObjectLayer) error { | 
					
						
							|  |  |  | 	_, err := obj.GetBucketInfo(ctx, bucket) | 
					
						
							| 
									
										
										
										
											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 | 
					
						
							|  |  |  | } |