mirror of
https://github.com/minio/minio.git
synced 2025-04-18 17:55:28 -04:00
POST Policy, multiple fixes: AccessDenied with unmet conditions, ${filename} in Key, missing filename in multipart (#2304)
* Unsatisfied conditions will return AccessDenied instead of MissingFields * Require form-field `file` in POST policy and make `filename` an optional attribute * S3 feature: Replace in Key by filename attribute passed in multipart
This commit is contained in:
parent
2f7358a8a6
commit
8b3cb3a0de
@ -347,7 +347,7 @@ func (api objectAPIHandlers) PostPolicyBucketHandler(w http.ResponseWriter, r *h
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
fileBody, formValues, err := extractHTTPFormValues(reader)
|
fileBody, fileName, formValues, err := extractHTTPFormValues(reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errorIf(err, "Unable to parse form values.")
|
errorIf(err, "Unable to parse form values.")
|
||||||
writeErrorResponse(w, r, ErrMalformedPOSTRequest, r.URL.Path)
|
writeErrorResponse(w, r, ErrMalformedPOSTRequest, r.URL.Path)
|
||||||
@ -357,6 +357,12 @@ func (api objectAPIHandlers) PostPolicyBucketHandler(w http.ResponseWriter, r *h
|
|||||||
formValues["Bucket"] = bucket
|
formValues["Bucket"] = bucket
|
||||||
object := formValues["Key"]
|
object := formValues["Key"]
|
||||||
|
|
||||||
|
if fileName != "" && strings.Contains(object, "${filename}") {
|
||||||
|
// S3 feature to replace ${filename} found in Key form field
|
||||||
|
// by the filename attribute passed in multipart
|
||||||
|
object = strings.Replace(object, "${filename}", fileName, -1)
|
||||||
|
}
|
||||||
|
|
||||||
// Verify policy signature.
|
// Verify policy signature.
|
||||||
apiErr := doesPolicySignatureMatch(formValues)
|
apiErr := doesPolicySignatureMatch(formValues)
|
||||||
if apiErr != ErrNone {
|
if apiErr != ErrNone {
|
||||||
|
@ -99,29 +99,32 @@ func extractMetadataFromHeader(header http.Header) map[string]string {
|
|||||||
return metadata
|
return metadata
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractHTTPFormValues(reader *multipart.Reader) (io.Reader, map[string]string, error) {
|
func extractHTTPFormValues(reader *multipart.Reader) (io.Reader, string, map[string]string, error) {
|
||||||
/// HTML Form values
|
/// HTML Form values
|
||||||
formValues := make(map[string]string)
|
formValues := make(map[string]string)
|
||||||
filePart := new(bytes.Buffer)
|
filePart := new(bytes.Buffer)
|
||||||
|
fileName := ""
|
||||||
var err error
|
var err error
|
||||||
for err == nil {
|
for err == nil {
|
||||||
var part *multipart.Part
|
var part *multipart.Part
|
||||||
part, err = reader.NextPart()
|
part, err = reader.NextPart()
|
||||||
if part != nil {
|
if part != nil {
|
||||||
if part.FileName() == "" {
|
canonicalFormName := http.CanonicalHeaderKey(part.FormName())
|
||||||
|
if canonicalFormName != "File" {
|
||||||
var buffer []byte
|
var buffer []byte
|
||||||
buffer, err = ioutil.ReadAll(part)
|
buffer, err = ioutil.ReadAll(part)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, "", nil, err
|
||||||
}
|
}
|
||||||
formValues[http.CanonicalHeaderKey(part.FormName())] = string(buffer)
|
formValues[canonicalFormName] = string(buffer)
|
||||||
} else {
|
} else {
|
||||||
if _, err = io.Copy(filePart, part); err != nil {
|
if _, err = io.Copy(filePart, part); err != nil {
|
||||||
return nil, nil, err
|
return nil, "", nil, err
|
||||||
}
|
}
|
||||||
|
fileName = part.FileName()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return filePart, formValues, nil
|
return filePart, fileName, formValues, nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -170,32 +170,32 @@ func checkPostPolicy(formValues map[string]string) APIErrorCode {
|
|||||||
}
|
}
|
||||||
if postPolicyForm.Conditions.Policies["$bucket"].Operator == "eq" {
|
if postPolicyForm.Conditions.Policies["$bucket"].Operator == "eq" {
|
||||||
if formValues["Bucket"] != postPolicyForm.Conditions.Policies["$bucket"].Value {
|
if formValues["Bucket"] != postPolicyForm.Conditions.Policies["$bucket"].Value {
|
||||||
return ErrMissingFields
|
return ErrAccessDenied
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if postPolicyForm.Conditions.Policies["$x-amz-date"].Operator == "eq" {
|
if postPolicyForm.Conditions.Policies["$x-amz-date"].Operator == "eq" {
|
||||||
if formValues["X-Amz-Date"] != postPolicyForm.Conditions.Policies["$x-amz-date"].Value {
|
if formValues["X-Amz-Date"] != postPolicyForm.Conditions.Policies["$x-amz-date"].Value {
|
||||||
return ErrMissingFields
|
return ErrAccessDenied
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if postPolicyForm.Conditions.Policies["$Content-Type"].Operator == "starts-with" {
|
if postPolicyForm.Conditions.Policies["$Content-Type"].Operator == "starts-with" {
|
||||||
if !strings.HasPrefix(formValues["Content-Type"], postPolicyForm.Conditions.Policies["$Content-Type"].Value) {
|
if !strings.HasPrefix(formValues["Content-Type"], postPolicyForm.Conditions.Policies["$Content-Type"].Value) {
|
||||||
return ErrMissingFields
|
return ErrAccessDenied
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if postPolicyForm.Conditions.Policies["$Content-Type"].Operator == "eq" {
|
if postPolicyForm.Conditions.Policies["$Content-Type"].Operator == "eq" {
|
||||||
if formValues["Content-Type"] != postPolicyForm.Conditions.Policies["$Content-Type"].Value {
|
if formValues["Content-Type"] != postPolicyForm.Conditions.Policies["$Content-Type"].Value {
|
||||||
return ErrMissingFields
|
return ErrAccessDenied
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if postPolicyForm.Conditions.Policies["$key"].Operator == "starts-with" {
|
if postPolicyForm.Conditions.Policies["$key"].Operator == "starts-with" {
|
||||||
if !strings.HasPrefix(formValues["Key"], postPolicyForm.Conditions.Policies["$key"].Value) {
|
if !strings.HasPrefix(formValues["Key"], postPolicyForm.Conditions.Policies["$key"].Value) {
|
||||||
return ErrMissingFields
|
return ErrAccessDenied
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if postPolicyForm.Conditions.Policies["$key"].Operator == "eq" {
|
if postPolicyForm.Conditions.Policies["$key"].Operator == "eq" {
|
||||||
if formValues["Key"] != postPolicyForm.Conditions.Policies["$key"].Value {
|
if formValues["Key"] != postPolicyForm.Conditions.Policies["$key"].Value {
|
||||||
return ErrMissingFields
|
return ErrAccessDenied
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ErrNone
|
return ErrNone
|
||||||
|
Loading…
x
Reference in New Issue
Block a user