forked from TrueCloudLab/frostfs-s3-gw
[#619] Fix content-length invalid check
Signed-off-by: Roman Loginov <r.loginov@yadro.com>
This commit is contained in:
parent
711d6b2c71
commit
bfec3e0a5e
2 changed files with 117 additions and 7 deletions
|
@ -54,17 +54,29 @@ func (p *postPolicy) condition(key string) *policyCondition {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *postPolicy) CheckContentLength(size uint64) bool {
|
func (p *postPolicy) CheckContentLength(size uint64) error {
|
||||||
if p.empty {
|
if p.empty {
|
||||||
return true
|
return nil
|
||||||
}
|
}
|
||||||
for _, condition := range p.Conditions {
|
for _, condition := range p.Conditions {
|
||||||
if condition.Matching == "content-length-range" {
|
if condition.Matching == "content-length-range" {
|
||||||
length := strconv.FormatUint(size, 10)
|
start, err := strconv.ParseUint(condition.Key, 10, 64)
|
||||||
return condition.Key <= length && length <= condition.Value
|
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 {
|
func (p *policyCondition) match(value string) bool {
|
||||||
|
@ -560,8 +572,8 @@ func (h *handler) PostObject(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !policy.CheckContentLength(size) {
|
if err := policy.CheckContentLength(size); err != nil {
|
||||||
h.logAndSendError(ctx, w, "invalid content-length", reqInfo, apierr.GetAPIError(apierr.ErrInvalidArgument))
|
h.logAndSendError(ctx, w, err.Error(), reqInfo, apierr.GetAPIError(apierr.ErrPostPolicyConditionInvalidFormat))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
func prepareRequestForEncryption(hc *handlerContext, algo, key, md5, tlsTermination string, reqWithoutTLS, reqWithoutSSE, isCopySource bool) *http.Request {
|
||||||
r := httptest.NewRequest(http.MethodPost, "/", nil)
|
r := httptest.NewRequest(http.MethodPost, "/", nil)
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue