[#619] Fix content-length invalid check

Signed-off-by: Roman Loginov <r.loginov@yadro.com>
This commit is contained in:
Roman Loginov 2025-02-10 01:33:51 +03:00 committed by Alexey Vanin
parent 711d6b2c71
commit bfec3e0a5e
2 changed files with 117 additions and 7 deletions

View file

@ -54,17 +54,29 @@ func (p *postPolicy) condition(key string) *policyCondition {
return nil
}
func (p *postPolicy) CheckContentLength(size uint64) bool {
func (p *postPolicy) CheckContentLength(size uint64) error {
if p.empty {
return true
return nil
}
for _, condition := range p.Conditions {
if condition.Matching == "content-length-range" {
length := strconv.FormatUint(size, 10)
return condition.Key <= length && length <= condition.Value
start, err := strconv.ParseUint(condition.Key, 10, 64)
if err != nil {
return errInvalidCondition
}
end, err := strconv.ParseUint(condition.Value, 10, 64)
if err != nil {
return errInvalidCondition
}
if start <= size && size <= end {
return nil
}
return fmt.Errorf("length of the content did not fall within the range specified in the condition")
}
}
return true
return nil
}
func (p *policyCondition) match(value string) bool {
@ -560,8 +572,8 @@ func (h *handler) PostObject(w http.ResponseWriter, r *http.Request) {
return
}
if !policy.CheckContentLength(size) {
h.logAndSendError(ctx, w, "invalid content-length", reqInfo, apierr.GetAPIError(apierr.ErrInvalidArgument))
if err := policy.CheckContentLength(size); err != nil {
h.logAndSendError(ctx, w, err.Error(), reqInfo, apierr.GetAPIError(apierr.ErrPostPolicyConditionInvalidFormat))
return
}

View file

@ -1206,6 +1206,104 @@ func TestFormEncryptionParamsBase(t *testing.T) {
}
}
func TestCheckContentLength(t *testing.T) {
contentLength := "content-length-range"
notFallError := "length of the content did not fall within the range specified in the condition"
parseError := "invalid condition"
for _, tc := range []struct {
name string
matching string
key string
value string
size uint64
errMsg string
emptyPolicy bool
}{
{
name: "valid",
matching: contentLength,
key: "0",
value: "1000",
size: 50,
},
{
name: "valid lower limit",
matching: contentLength,
key: "5",
value: "100",
size: 5,
},
{
name: "valid upper limit",
matching: contentLength,
key: "5",
value: "100",
size: 100,
},
{
name: "invalid size value (too small)",
matching: contentLength,
key: "5",
value: "100",
size: 2,
errMsg: notFallError,
},
{
name: "invalid size value (to high)",
matching: contentLength,
key: "5",
value: "100",
size: 200,
errMsg: notFallError,
},
{
name: "no matching",
},
{
name: "invalid key type",
matching: contentLength,
key: "invalid",
value: "100",
size: 10,
errMsg: parseError,
},
{
name: "invalid value type",
matching: contentLength,
key: "5",
value: "invalid",
size: 10,
errMsg: parseError,
},
{
name: "empty policy",
emptyPolicy: true,
},
} {
t.Run(tc.name, func(t *testing.T) {
policy := &postPolicy{
Conditions: []*policyCondition{
{
Matching: tc.matching,
Key: tc.key,
Value: tc.value,
},
},
empty: tc.emptyPolicy,
}
err := policy.CheckContentLength(tc.size)
if tc.errMsg != "" {
require.Error(t, err)
require.Contains(t, err.Error(), tc.errMsg)
return
}
require.NoError(t, err)
})
}
}
func prepareRequestForEncryption(hc *handlerContext, algo, key, md5, tlsTermination string, reqWithoutTLS, reqWithoutSSE, isCopySource bool) *http.Request {
r := httptest.NewRequest(http.MethodPost, "/", nil)