storj.io/minio@v0.0.0-20230509071714-0cbc90f649b1/cmd/object-api-input-checks.go (about)

     1  /*
     2   * MinIO Cloud Storage, (C) 2016 MinIO, Inc.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package cmd
    18  
    19  import (
    20  	"context"
    21  	"runtime"
    22  	"strings"
    23  
    24  	"github.com/google/uuid"
    25  	"github.com/minio/minio-go/v7/pkg/s3utils"
    26  
    27  	"storj.io/minio/cmd/logger"
    28  )
    29  
    30  // Checks on GetObject arguments, bucket and object.
    31  func checkGetObjArgs(ctx context.Context, bucket, object string) error {
    32  	return checkBucketAndObjectNames(ctx, bucket, object)
    33  }
    34  
    35  // Checks on DeleteObject arguments, bucket and object.
    36  func checkDelObjArgs(ctx context.Context, bucket, object string) error {
    37  	return checkBucketAndObjectNames(ctx, bucket, object)
    38  }
    39  
    40  // Checks bucket and object name validity, returns nil if both are valid.
    41  func checkBucketAndObjectNames(ctx context.Context, bucket, object string) error {
    42  	// Verify if bucket is valid.
    43  	if !isMinioMetaBucketName(bucket) && s3utils.CheckValidBucketName(bucket) != nil {
    44  		logger.LogIf(ctx, BucketNameInvalid{Bucket: bucket})
    45  		return BucketNameInvalid{Bucket: bucket}
    46  	}
    47  	// Verify if object is valid.
    48  	if len(object) == 0 {
    49  		logger.LogIf(ctx, ObjectNameInvalid{Bucket: bucket, Object: object})
    50  		return ObjectNameInvalid{Bucket: bucket, Object: object}
    51  	}
    52  	if !IsValidObjectPrefix(object) {
    53  		logger.LogIf(ctx, ObjectNameInvalid{Bucket: bucket, Object: object})
    54  		return ObjectNameInvalid{Bucket: bucket, Object: object}
    55  	}
    56  	if runtime.GOOS == globalWindowsOSName && strings.Contains(object, "\\") {
    57  		// Objects cannot be contain \ in Windows and is listed as `Characters to Avoid`.
    58  		return ObjectNameInvalid{Bucket: bucket, Object: object}
    59  	}
    60  	return nil
    61  }
    62  
    63  // Checks for all ListObjects arguments validity.
    64  func checkListObjsArgs(ctx context.Context, bucket, prefix, marker string, obj getBucketInfoI) error {
    65  	// Verify if bucket exists before validating object name.
    66  	// This is done on purpose since the order of errors is
    67  	// important here bucket does not exist error should
    68  	// happen before we return an error for invalid object name.
    69  	// FIXME: should be moved to handler layer.
    70  	if err := checkBucketExist(ctx, bucket, obj); err != nil {
    71  		return err
    72  	}
    73  	// Validates object prefix validity after bucket exists.
    74  	if !IsValidObjectPrefix(prefix) {
    75  		logger.LogIf(ctx, ObjectNameInvalid{
    76  			Bucket: bucket,
    77  			Object: prefix,
    78  		})
    79  		return ObjectNameInvalid{
    80  			Bucket: bucket,
    81  			Object: prefix,
    82  		}
    83  	}
    84  	// Verify if marker has prefix.
    85  	if marker != "" && !HasPrefix(marker, prefix) {
    86  		logger.LogIf(ctx, InvalidMarkerPrefixCombination{
    87  			Marker: marker,
    88  			Prefix: prefix,
    89  		})
    90  		return InvalidMarkerPrefixCombination{
    91  			Marker: marker,
    92  			Prefix: prefix,
    93  		}
    94  	}
    95  	return nil
    96  }
    97  
    98  // Checks for all ListMultipartUploads arguments validity.
    99  func checkListMultipartArgs(ctx context.Context, bucket, prefix, keyMarker, uploadIDMarker, delimiter string, obj ObjectLayer) error {
   100  	if err := checkListObjsArgs(ctx, bucket, prefix, keyMarker, obj); err != nil {
   101  		return err
   102  	}
   103  	if uploadIDMarker != "" {
   104  		if HasSuffix(keyMarker, SlashSeparator) {
   105  
   106  			logger.LogIf(ctx, InvalidUploadIDKeyCombination{
   107  				UploadIDMarker: uploadIDMarker,
   108  				KeyMarker:      keyMarker,
   109  			})
   110  			return InvalidUploadIDKeyCombination{
   111  				UploadIDMarker: uploadIDMarker,
   112  				KeyMarker:      keyMarker,
   113  			}
   114  		}
   115  		if _, err := uuid.Parse(uploadIDMarker); err != nil {
   116  			logger.LogIf(ctx, err)
   117  			return MalformedUploadID{
   118  				UploadID: uploadIDMarker,
   119  			}
   120  		}
   121  	}
   122  	return nil
   123  }
   124  
   125  // Checks for NewMultipartUpload arguments validity, also validates if bucket exists.
   126  func checkNewMultipartArgs(ctx context.Context, bucket, object string, obj ObjectLayer) error {
   127  	return checkObjectArgs(ctx, bucket, object, obj)
   128  }
   129  
   130  // Checks for PutObjectPart arguments validity, also validates if bucket exists.
   131  func checkPutObjectPartArgs(ctx context.Context, bucket, object string, obj ObjectLayer) error {
   132  	return checkObjectArgs(ctx, bucket, object, obj)
   133  }
   134  
   135  // Checks for ListParts arguments validity, also validates if bucket exists.
   136  func checkListPartsArgs(ctx context.Context, bucket, object string, obj ObjectLayer) error {
   137  	return checkObjectArgs(ctx, bucket, object, obj)
   138  }
   139  
   140  // Checks for CompleteMultipartUpload arguments validity, also validates if bucket exists.
   141  func checkCompleteMultipartArgs(ctx context.Context, bucket, object string, obj ObjectLayer) error {
   142  	return checkObjectArgs(ctx, bucket, object, obj)
   143  }
   144  
   145  // Checks for AbortMultipartUpload arguments validity, also validates if bucket exists.
   146  func checkAbortMultipartArgs(ctx context.Context, bucket, object string, obj ObjectLayer) error {
   147  	return checkObjectArgs(ctx, bucket, object, obj)
   148  }
   149  
   150  // Checks Object arguments validity, also validates if bucket exists.
   151  func checkObjectArgs(ctx context.Context, bucket, object string, obj ObjectLayer) error {
   152  	// Verify if bucket exists before validating object name.
   153  	// This is done on purpose since the order of errors is
   154  	// important here bucket does not exist error should
   155  	// happen before we return an error for invalid object name.
   156  	// FIXME: should be moved to handler layer.
   157  	if err := checkBucketExist(ctx, bucket, obj); err != nil {
   158  		return err
   159  	}
   160  
   161  	if err := checkObjectNameForLengthAndSlash(bucket, object); err != nil {
   162  		return err
   163  	}
   164  
   165  	// Validates object name validity after bucket exists.
   166  	if !IsValidObjectName(object) {
   167  		return ObjectNameInvalid{
   168  			Bucket: bucket,
   169  			Object: object,
   170  		}
   171  	}
   172  
   173  	return nil
   174  }
   175  
   176  // Checks for PutObject arguments validity, also validates if bucket exists.
   177  func checkPutObjectArgs(ctx context.Context, bucket, object string, obj getBucketInfoI) error {
   178  	// Verify if bucket exists before validating object name.
   179  	// This is done on purpose since the order of errors is
   180  	// important here bucket does not exist error should
   181  	// happen before we return an error for invalid object name.
   182  	// FIXME: should be moved to handler layer.
   183  	if err := checkBucketExist(ctx, bucket, obj); err != nil {
   184  		return err
   185  	}
   186  
   187  	if err := checkObjectNameForLengthAndSlash(bucket, object); err != nil {
   188  		return err
   189  	}
   190  	if len(object) == 0 ||
   191  		!IsValidObjectPrefix(object) {
   192  		return ObjectNameInvalid{
   193  			Bucket: bucket,
   194  			Object: object,
   195  		}
   196  	}
   197  	return nil
   198  }
   199  
   200  type getBucketInfoI interface {
   201  	GetBucketInfo(ctx context.Context, bucket string) (bucketInfo BucketInfo, err error)
   202  }
   203  
   204  // Checks whether bucket exists and returns appropriate error if not.
   205  func checkBucketExist(ctx context.Context, bucket string, obj getBucketInfoI) error {
   206  	_, err := obj.GetBucketInfo(ctx, bucket)
   207  	if err != nil {
   208  		return err
   209  	}
   210  	return nil
   211  }