fix: relax enforcing filename on PostPolicy (#18336)

The filename is not required to be on the form data.
This commit is contained in:
Daniel López Guimaraes 2023-10-31 04:06:32 +00:00 committed by GitHub
parent ac8c43fe9c
commit a1792ca0d1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 34 additions and 8 deletions

View File

@ -983,7 +983,7 @@ func (api objectAPIHandlers) PostPolicyBucketHandler(w http.ResponseWriter, r *h
}
var b bytes.Buffer
if fileName == "" {
if name != "file" {
if http.CanonicalHeaderKey(name) == http.CanonicalHeaderKey("x-minio-fanout-list") {
dec := json.NewDecoder(part)

View File

@ -314,6 +314,7 @@ func testPostPolicyBucketHandler(obj ObjectLayer, instanceType string, t TestErr
secretKey string
dates []interface{}
policy string
noFilename bool
corruptedBase64 bool
corruptedMultipart bool
}{
@ -327,6 +328,17 @@ func testPostPolicyBucketHandler(obj ObjectLayer, instanceType string, t TestErr
dates: []interface{}{curTimePlus5Min.Format(iso8601TimeFormat), curTime.Format(iso8601DateFormat), curTime.Format(yyyymmdd)},
policy: `{"expiration": "%s","conditions":[["eq", "$bucket", "` + bucketName + `"], ["starts-with", "$key", "test/"], ["eq", "$x-amz-algorithm", "AWS4-HMAC-SHA256"], ["eq", "$x-amz-date", "%s"], ["eq", "$x-amz-credential", "` + credentials.AccessKey + `/%s/us-east-1/s3/aws4_request"],["eq", "$x-amz-meta-uuid", "1234"]]}`,
},
// Success case, no multipart filename.
{
objectName: "test",
data: []byte("Hello, World"),
expectedRespStatus: http.StatusNoContent,
accessKey: credentials.AccessKey,
secretKey: credentials.SecretKey,
dates: []interface{}{curTimePlus5Min.Format(iso8601TimeFormat), curTime.Format(iso8601DateFormat), curTime.Format(yyyymmdd)},
policy: `{"expiration": "%s","conditions":[["eq", "$bucket", "` + bucketName + `"], ["starts-with", "$key", "test/"], ["eq", "$x-amz-algorithm", "AWS4-HMAC-SHA256"], ["eq", "$x-amz-date", "%s"], ["eq", "$x-amz-credential", "` + credentials.AccessKey + `/%s/us-east-1/s3/aws4_request"],["eq", "$x-amz-meta-uuid", "1234"]]}`,
noFilename: true,
},
// Success case, big body.
{
objectName: "test",
@ -399,7 +411,7 @@ func testPostPolicyBucketHandler(obj ObjectLayer, instanceType string, t TestErr
testCase.policy = fmt.Sprintf(testCase.policy, testCase.dates...)
req, perr := newPostRequestV4Generic("", bucketName, testCase.objectName, testCase.data, testCase.accessKey,
testCase.secretKey, region, curTime, []byte(testCase.policy), nil, testCase.corruptedBase64, testCase.corruptedMultipart)
testCase.secretKey, region, curTime, []byte(testCase.policy), nil, testCase.noFilename, testCase.corruptedBase64, testCase.corruptedMultipart)
if perr != nil {
t.Fatalf("Test %d: %s: Failed to create HTTP request for PostPolicyHandler: <ERROR> %v", i+1, instanceType, perr)
}
@ -539,7 +551,7 @@ func testPostPolicyBucketHandlerRedirect(obj ObjectLayer, instanceType string, t
// Create a new POST request with success_action_redirect field specified
req, perr := newPostRequestV4Generic("", bucketName, keyName, []byte("objData"),
credentials.AccessKey, credentials.SecretKey, region, curTime,
[]byte(policy), map[string]string{"success_action_redirect": redirectURL.String()}, false, false)
[]byte(policy), map[string]string{"success_action_redirect": redirectURL.String()}, false, false, false)
if perr != nil {
t.Fatalf("%s: Failed to create HTTP request for PostPolicyHandler: <ERROR> %v", instanceType, perr)
@ -647,7 +659,7 @@ func buildGenericPolicy(t time.Time, accessKey, region, bucketName, objectName s
}
func newPostRequestV4Generic(endPoint, bucketName, objectName string, objData []byte, accessKey, secretKey string, region string,
t time.Time, policy []byte, addFormData map[string]string, corruptedB64 bool, corruptedMultipart bool,
t time.Time, policy []byte, addFormData map[string]string, noFilename bool, corruptedB64 bool, corruptedMultipart bool,
) (*http.Request, error) {
// Get the user credential.
credStr := getCredentialString(accessKey, region, t)
@ -662,9 +674,17 @@ func newPostRequestV4Generic(endPoint, bucketName, objectName string, objData []
// Presign with V4 signature based on the policy.
signature := postPresignSignatureV4(encodedPolicy, t, secretKey, region)
// If there is no filename on multipart, get the filename from the key.
key := objectName
if noFilename {
key += "/upload.txt"
} else {
key += "/${filename}"
}
formData := map[string]string{
"bucket": bucketName,
"key": objectName + "/${filename}",
"key": key,
"x-amz-credential": credStr,
"policy": encodedPolicy,
"x-amz-signature": signature,
@ -689,7 +709,13 @@ func newPostRequestV4Generic(endPoint, bucketName, objectName string, objData []
}
// Set the File formData but don't if we want send an incomplete multipart request
if !corruptedMultipart {
writer, err := w.CreateFormFile("file", "upload.txt")
var writer io.Writer
var err error
if noFilename {
writer, err = w.CreateFormField("file")
} else {
writer, err = w.CreateFormFile("file", "upload.txt")
}
if err != nil {
// return nil, err
return nil, err
@ -716,12 +742,12 @@ func newPostRequestV4WithContentLength(endPoint, bucketName, objectName string,
t := UTCNow()
region := "us-east-1"
policy := buildGenericPolicy(t, accessKey, region, bucketName, objectName, true)
return newPostRequestV4Generic(endPoint, bucketName, objectName, objData, accessKey, secretKey, region, t, policy, nil, false, false)
return newPostRequestV4Generic(endPoint, bucketName, objectName, objData, accessKey, secretKey, region, t, policy, nil, false, false, false)
}
func newPostRequestV4(endPoint, bucketName, objectName string, objData []byte, accessKey, secretKey string) (*http.Request, error) {
t := UTCNow()
region := "us-east-1"
policy := buildGenericPolicy(t, accessKey, region, bucketName, objectName, false)
return newPostRequestV4Generic(endPoint, bucketName, objectName, objData, accessKey, secretKey, region, t, policy, nil, false, false)
return newPostRequestV4Generic(endPoint, bucketName, objectName, objData, accessKey, secretKey, region, t, policy, nil, false, false, false)
}