forked from TrueCloudLab/frostfs-s3-gw
1025 lines
26 KiB
Go
1025 lines
26 KiB
Go
//go:build gofuzz
|
|
// +build gofuzz
|
|
|
|
package handler
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/md5"
|
|
"encoding/base64"
|
|
"encoding/hex"
|
|
"encoding/xml"
|
|
"errors"
|
|
"mime/multipart"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
tt "testing" // read https://github.com/AdamKorcz/go-118-fuzz-build?tab=readme-ov-file#workflow
|
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/data"
|
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/layer"
|
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/middleware"
|
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/creds/accessbox"
|
|
engineiam "git.frostfs.info/TrueCloudLab/policy-engine/iam"
|
|
utils "github.com/trailofbits/go-fuzz-utils"
|
|
"go.uber.org/zap/zaptest"
|
|
)
|
|
|
|
var (
|
|
fuzzBktName string
|
|
fuzzBox *accessbox.Box
|
|
fuzzHc *handlerContextBase
|
|
fuzzt *tt.T
|
|
)
|
|
|
|
const (
|
|
fuzzSuccessExitCode = 0
|
|
fuzzFailExitCode = -1
|
|
)
|
|
|
|
func createTestBucketAndInitContext() {
|
|
fuzzt = new(tt.T)
|
|
|
|
log := zaptest.NewLogger(fuzzt)
|
|
var err error
|
|
fuzzHc, err = prepareHandlerContextBase(layer.DefaultCachesConfigs(log))
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
fuzzBktName = "bucket"
|
|
fuzzBox, _ = createAccessBox(fuzzt)
|
|
|
|
w := httptest.NewRecorder()
|
|
r := httptest.NewRequest(http.MethodPut, defaultURL, nil)
|
|
reqInfo := middleware.NewReqInfo(w, r, middleware.ObjectRequest{Bucket: fuzzBktName, Object: ""}, "")
|
|
r = r.WithContext(middleware.SetReqInfo(fuzzHc.Context(), reqInfo))
|
|
r = r.WithContext(middleware.SetBox(r.Context(), &middleware.Box{AccessBox: fuzzBox}))
|
|
|
|
fuzzHc.Handler().CreateBucketHandler(w, r)
|
|
}
|
|
|
|
func prepareStrings(tp *utils.TypeProvider, count int) ([]string, error) {
|
|
array := make([]string, count)
|
|
var err error
|
|
|
|
for i := 0; i < count; i++ {
|
|
err = tp.Reset()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
array[i], err = tp.GetString()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
return array, nil
|
|
}
|
|
|
|
func addMD5Header(tp *utils.TypeProvider, r *http.Request, rawBody []byte) error {
|
|
if len(rawBody) == 0 {
|
|
return nil
|
|
}
|
|
|
|
rand, err := tp.GetBool()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if rand == true {
|
|
defer func() {
|
|
if recover() != nil {
|
|
err = errors.New("panic in base64")
|
|
}
|
|
}()
|
|
|
|
var dst []byte
|
|
base64.StdEncoding.Encode(dst, rawBody)
|
|
hash := md5.Sum(dst)
|
|
r.Header.Set("Content-Md5", hex.EncodeToString(hash[:]))
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func generateParams(tp *utils.TypeProvider, input string, params []string) (string, error) {
|
|
input += "?"
|
|
|
|
count, err := tp.GetInt()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
count = count % len(params)
|
|
if count < 0 {
|
|
count += len(params)
|
|
}
|
|
|
|
for i := 0; i < count; i++ {
|
|
position, err := tp.GetInt()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
position = position % len(params)
|
|
if position < 0 {
|
|
position += len(params)
|
|
}
|
|
|
|
v, err := tp.GetString()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
input += params[position] + "=" + v + "&"
|
|
}
|
|
|
|
return input, nil
|
|
}
|
|
|
|
func generateHeaders(tp *utils.TypeProvider, r *http.Request, params []string) error {
|
|
count, err := tp.GetInt()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
count = count % len(params)
|
|
if count < 0 {
|
|
count += len(params)
|
|
}
|
|
|
|
for i := 0; i < count; i++ {
|
|
position, err := tp.GetInt()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
position = position % len(params)
|
|
if position < 0 {
|
|
position += len(params)
|
|
}
|
|
|
|
v, err := tp.GetString()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
r.Header.Set(params[position], v)
|
|
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func InitFuzzCreateBucketHandler() {
|
|
fuzzt = new(tt.T)
|
|
|
|
log := zaptest.NewLogger(fuzzt)
|
|
var err error
|
|
fuzzHc, err = prepareHandlerContextBase(layer.DefaultCachesConfigs(log))
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
fuzzBox, _ = createAccessBox(fuzzt)
|
|
}
|
|
|
|
func DoFuzzCreateBucketHandler(input []byte) int {
|
|
// FUZZER INIT
|
|
if len(input) < 100 {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
tp, err := utils.NewTypeProvider(input)
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
strings, err := prepareStrings(tp, 4)
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
bktName := strings[0]
|
|
body := strings[1]
|
|
|
|
bodyXml, err := xml.Marshal(body)
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
w := httptest.NewRecorder()
|
|
r := httptest.NewRequest(http.MethodPut, defaultURL, bytes.NewReader(bodyXml))
|
|
reqInfo := middleware.NewReqInfo(w, r, middleware.ObjectRequest{Bucket: bktName, Object: ""}, "")
|
|
r = r.WithContext(middleware.SetReqInfo(fuzzHc.Context(), reqInfo))
|
|
r = r.WithContext(middleware.SetBox(r.Context(), &middleware.Box{AccessBox: fuzzBox}))
|
|
|
|
err = generateHeaders(tp, r, []string{"x-amz-acl", "x-amz-bucket-object-lock-enabled", "x-amz-grant-full-control", "x-amz-grant-read", "x-amz-grant-read-acp", "x-amz-grant-write", "x-amz-grant-write-acp", "x-amz-object-ownership"})
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
fuzzHc.Handler().CreateBucketHandler(w, r)
|
|
|
|
return fuzzSuccessExitCode
|
|
}
|
|
|
|
func FuzzCreateBucketHandler(f *testing.F) {
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
|
DoFuzzCreateBucketHandler(data)
|
|
})
|
|
}
|
|
|
|
func InitFuzzPutBucketCorsHandler() {
|
|
createTestBucketAndInitContext()
|
|
}
|
|
|
|
func DoFuzzPutBucketCorsHandler(input []byte) int {
|
|
// FUZZER INIT
|
|
if len(input) < 100 {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
tp, err := utils.NewTypeProvider(input)
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
var cors data.CORSConfiguration
|
|
err = tp.Fill(&cors)
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
bodyXml, err := xml.Marshal(cors)
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
w := httptest.NewRecorder()
|
|
r := httptest.NewRequest(http.MethodPut, defaultURL+"?cors", bytes.NewReader(bodyXml))
|
|
reqInfo := middleware.NewReqInfo(w, r, middleware.ObjectRequest{Bucket: fuzzBktName, Object: ""}, "")
|
|
r = r.WithContext(middleware.SetReqInfo(fuzzHc.Context(), reqInfo))
|
|
r = r.WithContext(middleware.SetBox(r.Context(), &middleware.Box{AccessBox: fuzzBox}))
|
|
|
|
err = generateHeaders(tp, r, []string{"x-amz-expected-bucket-owner"})
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
fuzzHc.Handler().PutBucketCorsHandler(w, r)
|
|
|
|
return fuzzSuccessExitCode
|
|
}
|
|
|
|
func FuzzPutBucketCorsHandler(f *testing.F) {
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
|
DoFuzzPutBucketCorsHandler(data)
|
|
})
|
|
}
|
|
|
|
func InitFuzzPutBucketPolicyHandler() {
|
|
createTestBucketAndInitContext()
|
|
}
|
|
|
|
func FuzzPutBucketPolicyHandler(f *testing.F) {
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
|
DoFuzzPutBucketPolicyHandler(data)
|
|
})
|
|
}
|
|
|
|
func DoFuzzPutBucketPolicyHandler(input []byte) int {
|
|
// FUZZER INIT
|
|
if len(input) < 100 {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
tp, err := utils.NewTypeProvider(input)
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
var policy engineiam.Policy
|
|
err = tp.Fill(&policy)
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
bodyXml, err := xml.Marshal(policy)
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
w := httptest.NewRecorder()
|
|
r := httptest.NewRequest(http.MethodPut, defaultURL+"?policy", bytes.NewReader(bodyXml))
|
|
reqInfo := middleware.NewReqInfo(w, r, middleware.ObjectRequest{Bucket: fuzzBktName, Object: ""}, "")
|
|
r = r.WithContext(middleware.SetReqInfo(fuzzHc.Context(), reqInfo))
|
|
r = r.WithContext(middleware.SetBox(r.Context(), &middleware.Box{AccessBox: fuzzBox}))
|
|
|
|
err = generateHeaders(tp, r, []string{"x-amz-expected-bucket-owner", "x-amz-confirm-remove-self-bucket-access"})
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
err = addMD5Header(tp, r, bodyXml)
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
fuzzHc.Handler().PutBucketPolicyHandler(w, r)
|
|
|
|
return fuzzSuccessExitCode
|
|
}
|
|
|
|
func InitFuzzDeleteMultipleObjectsHandler() {
|
|
createTestBucketAndInitContext()
|
|
}
|
|
|
|
func FuzzDeleteMultipleObjectsHandler(f *testing.F) {
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
|
DoFuzzDeleteMultipleObjectsHandler(data)
|
|
})
|
|
}
|
|
|
|
func DoFuzzDeleteMultipleObjectsHandler(input []byte) int {
|
|
// FUZZER INIT
|
|
if len(input) < 100 {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
tp, err := utils.NewTypeProvider(input)
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
var body DeleteObjectsRequest
|
|
err = tp.Fill(&body)
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
bodyXml, err := xml.Marshal(body)
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
w := httptest.NewRecorder()
|
|
r := httptest.NewRequest(http.MethodPost, defaultURL+"?delete", bytes.NewReader(bodyXml))
|
|
reqInfo := middleware.NewReqInfo(w, r, middleware.ObjectRequest{Bucket: fuzzBktName, Object: ""}, "")
|
|
r = r.WithContext(middleware.SetReqInfo(fuzzHc.Context(), reqInfo))
|
|
r = r.WithContext(middleware.SetBox(r.Context(), &middleware.Box{AccessBox: fuzzBox}))
|
|
|
|
err = generateHeaders(tp, r, []string{"x-amz-expected-bucket-owner", "x-amz-bypass-governance-retention", "x-amz-mfa"})
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
err = addMD5Header(tp, r, bodyXml)
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
fuzzHc.Handler().DeleteMultipleObjectsHandler(w, r)
|
|
|
|
return fuzzSuccessExitCode
|
|
}
|
|
|
|
func InitFuzzPostObject() {
|
|
createTestBucketAndInitContext()
|
|
}
|
|
|
|
func FuzzPostObject(f *testing.F) {
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
|
DoFuzzPostObject(data)
|
|
})
|
|
}
|
|
|
|
func postObject(tp *utils.TypeProvider) ([]byte, string, error) {
|
|
strings, err := prepareStrings(tp, 2)
|
|
if err != nil {
|
|
return nil, "", err
|
|
}
|
|
|
|
bodyXml, err := xml.Marshal(strings[0])
|
|
if err != nil {
|
|
return nil, "", err
|
|
}
|
|
objName := strings[1]
|
|
|
|
w := httptest.NewRecorder()
|
|
r := httptest.NewRequest(http.MethodPost, defaultURL, bytes.NewReader(bodyXml))
|
|
reqInfo := middleware.NewReqInfo(w, r, middleware.ObjectRequest{Bucket: fuzzBktName, Object: objName}, "")
|
|
r = r.WithContext(middleware.SetReqInfo(fuzzHc.Context(), reqInfo))
|
|
r = r.WithContext(middleware.SetBox(r.Context(), &middleware.Box{AccessBox: fuzzBox}))
|
|
|
|
err = generateHeaders(tp, r, []string{"X-Amz-Grant-Read", "X-Amz-Grant-Full-Control", "X-Amz-Grant-Write", "X-Amz-Acl", "x-amz-expected-bucket-owner"})
|
|
if err != nil {
|
|
return nil, "", err
|
|
}
|
|
|
|
var file multipart.Form
|
|
err = tp.Fill(&file)
|
|
if err != nil {
|
|
return nil, "", err
|
|
}
|
|
|
|
r.MultipartForm = &file
|
|
|
|
fuzzHc.Handler().PostObject(w, r)
|
|
|
|
return bodyXml, objName, nil
|
|
}
|
|
|
|
func DoFuzzPostObject(input []byte) int {
|
|
// FUZZER INIT
|
|
if len(input) < 100 {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
tp, err := utils.NewTypeProvider(input)
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
_, _, err = postObject(tp)
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
return fuzzSuccessExitCode
|
|
}
|
|
|
|
func InitFuzzDeleteBucketHandler() {
|
|
createTestBucketAndInitContext()
|
|
}
|
|
|
|
func FuzzDeleteBucketHandler(f *testing.F) {
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
|
DoFuzzDeleteBucketHandler(data)
|
|
})
|
|
}
|
|
|
|
func DoFuzzDeleteBucketHandler(input []byte) int {
|
|
// FUZZER INIT
|
|
if len(input) < 100 {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
tp, err := utils.NewTypeProvider(input)
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
w := httptest.NewRecorder()
|
|
r := httptest.NewRequest(http.MethodDelete, defaultURL, nil)
|
|
reqInfo := middleware.NewReqInfo(w, r, middleware.ObjectRequest{Bucket: fuzzBktName, Object: ""}, "")
|
|
r = r.WithContext(middleware.SetReqInfo(fuzzHc.Context(), reqInfo))
|
|
r = r.WithContext(middleware.SetBox(r.Context(), &middleware.Box{AccessBox: fuzzBox}))
|
|
|
|
err = generateHeaders(tp, r, []string{"x-amz-expected-bucket-owner"})
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
fuzzHc.Handler().DeleteBucketHandler(w, r)
|
|
|
|
return fuzzSuccessExitCode
|
|
}
|
|
|
|
func InitFuzzDeleteBucketCorsHandler() {
|
|
createTestBucketAndInitContext()
|
|
}
|
|
|
|
func FuzzDeleteBucketCorsHandler(f *testing.F) {
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
|
DoFuzzDeleteBucketCorsHandler(data)
|
|
})
|
|
}
|
|
|
|
func DoFuzzDeleteBucketCorsHandler(input []byte) int {
|
|
// FUZZER INIT
|
|
if len(input) < 100 {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
tp, err := utils.NewTypeProvider(input)
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
w := httptest.NewRecorder()
|
|
r := httptest.NewRequest(http.MethodDelete, defaultURL+"?cors", nil)
|
|
reqInfo := middleware.NewReqInfo(w, r, middleware.ObjectRequest{Bucket: fuzzBktName, Object: ""}, "")
|
|
r = r.WithContext(middleware.SetReqInfo(fuzzHc.Context(), reqInfo))
|
|
r = r.WithContext(middleware.SetBox(r.Context(), &middleware.Box{AccessBox: fuzzBox}))
|
|
|
|
err = generateHeaders(tp, r, []string{"x-amz-expected-bucket-owner"})
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
fuzzHc.Handler().DeleteBucketCorsHandler(w, r)
|
|
|
|
return fuzzSuccessExitCode
|
|
}
|
|
|
|
func InitFuzzDeleteBucketPolicyHandler() {
|
|
createTestBucketAndInitContext()
|
|
}
|
|
|
|
func FuzzDeleteBucketPolicyHandler(f *testing.F) {
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
|
DoFuzzDeleteBucketPolicyHandler(data)
|
|
})
|
|
}
|
|
|
|
func DoFuzzDeleteBucketPolicyHandler(input []byte) int {
|
|
// FUZZER INIT
|
|
if len(input) < 100 {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
tp, err := utils.NewTypeProvider(input)
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
w := httptest.NewRecorder()
|
|
r := httptest.NewRequest(http.MethodDelete, defaultURL+"?policy", nil)
|
|
reqInfo := middleware.NewReqInfo(w, r, middleware.ObjectRequest{Bucket: fuzzBktName, Object: ""}, "")
|
|
r = r.WithContext(middleware.SetReqInfo(fuzzHc.Context(), reqInfo))
|
|
r = r.WithContext(middleware.SetBox(r.Context(), &middleware.Box{AccessBox: fuzzBox}))
|
|
|
|
err = generateHeaders(tp, r, []string{"x-amz-expected-bucket-owner"})
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
fuzzHc.Handler().DeleteBucketPolicyHandler(w, r)
|
|
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
func InitFuzzCopyObjectHandler() {
|
|
createTestBucketAndInitContext()
|
|
}
|
|
|
|
func FuzzCopyObjectHandler(f *testing.F) {
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
|
DoFuzzCopyObjectHandler(data)
|
|
})
|
|
}
|
|
|
|
func DoFuzzCopyObjectHandler(input []byte) int {
|
|
// FUZZER INIT
|
|
if len(input) < 100 {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
tp, err := utils.NewTypeProvider(input)
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
w := httptest.NewRecorder()
|
|
var r *http.Request
|
|
|
|
key, err := tp.GetString()
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
params, err := generateParams(tp, key, []string{"versionId"})
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
defer func() {
|
|
if recover() != nil {
|
|
err = errors.New("panic in httptest.NewRequest")
|
|
}
|
|
}()
|
|
r = httptest.NewRequest(http.MethodPut, defaultURL+params, nil)
|
|
if r != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
reqInfo := middleware.NewReqInfo(w, r, middleware.ObjectRequest{Bucket: fuzzBktName, Object: ""}, "")
|
|
r = r.WithContext(middleware.SetReqInfo(fuzzHc.Context(), reqInfo))
|
|
r = r.WithContext(middleware.SetBox(r.Context(), &middleware.Box{AccessBox: fuzzBox}))
|
|
|
|
err = generateHeaders(tp, r, []string{"x-amz-acl", "x-amz-checksum-algorithm", "x-amz-copy-source", "x-amz-copy-source-if-match", "x-amz-copy-source-if-match", "x-amz-copy-source-if-unmodified-since", "x-amz-copy-source-if-modified-since", "x-amz-copy-source-if-none-match", "x-amz-copy-source-if-modified-since", "x-amz-copy-source-if-none-match", "x-amz-copy-source-if-none-match", "x-amz-copy-source-if-modified-since", "x-amz-copy-source-if-unmodified-since", "x-amz-copy-source-if-match", "x-amz-copy-source-if-unmodified-since", "x-amz-copy-source-server-side-encryption-customer-algorithm", "x-amz-copy-source-server-side-encryption-customer-key", "x-amz-copy-source-server-side-encryption-customer-key-MD5", "x-amz-expected-bucket-owner", "x-amz-grant-full-control", "x-amz-grant-read", "x-amz-grant-read-acp", "x-amz-grant-write-acp", "x-amz-metadata-directive", "x-amz-website-redirect-location", "x-amz-object-lock-legal-hold", "x-amz-object-lock-mode", "x-amz-object-lock-retain-until-date", "x-amz-request-payer", "x-amz-server-side-encryption", "x-amz-server-side-encryption-aws-kms-key-id", "x-amz-server-side-encryption-bucket-key-enabled", "x-amz-server-side-encryption-context", "x-amz-server-side-encryption-customer-algorithm", "x-amz-server-side-encryption-customer-key", "x-amz-server-side-encryption-customer-key-MD5", "x-amz-source-expected-bucket-owner", "x-amz-storage-class", "x-amz-tagging", "x-amz-tagging-directive", "x-amz-website-redirect-location"})
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
fuzzHc.Handler().CopyObjectHandler(w, r)
|
|
|
|
return fuzzSuccessExitCode
|
|
}
|
|
|
|
func InitFuzzDeleteObjectHandler() {
|
|
createTestBucketAndInitContext()
|
|
}
|
|
|
|
func FuzzDeleteObjectHandler(f *testing.F) {
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
|
DoFuzzDeleteObjectHandler(data)
|
|
})
|
|
}
|
|
|
|
func DoFuzzDeleteObjectHandler(input []byte) int {
|
|
// FUZZER INIT
|
|
if len(input) < 100 {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
tp, err := utils.NewTypeProvider(input)
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
_, objName, err := postObject(tp)
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
w := httptest.NewRecorder()
|
|
var r *http.Request
|
|
|
|
params, err := generateParams(tp, objName, []string{"versionId"})
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
defer func() {
|
|
if recover() != nil {
|
|
err = errors.New("panic in httptest.NewRequest")
|
|
}
|
|
}()
|
|
r = httptest.NewRequest(http.MethodDelete, defaultURL+params, nil)
|
|
if r != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
reqInfo := middleware.NewReqInfo(w, r, middleware.ObjectRequest{Bucket: fuzzBktName, Object: objName}, "")
|
|
r = r.WithContext(middleware.SetReqInfo(fuzzHc.Context(), reqInfo))
|
|
r = r.WithContext(middleware.SetBox(r.Context(), &middleware.Box{AccessBox: fuzzBox}))
|
|
|
|
err = generateHeaders(tp, r, []string{"x-amz-expected-bucket-owner", "x-amz-bypass-governance-retention", "x-amz-mfa"})
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
fuzzHc.Handler().DeleteObjectHandler(w, r)
|
|
|
|
return fuzzSuccessExitCode
|
|
}
|
|
|
|
func InitFuzzGetObjectHandler() {
|
|
createTestBucketAndInitContext()
|
|
}
|
|
|
|
func FuzzGetObjectHandler(f *testing.F) {
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
|
DoFuzzGetObjectHandler(data)
|
|
})
|
|
}
|
|
|
|
func DoFuzzGetObjectHandler(input []byte) int {
|
|
// FUZZER INIT
|
|
if len(input) < 100 {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
tp, err := utils.NewTypeProvider(input)
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
_, objName, err := postObject(tp)
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
params, err := generateParams(tp, objName, []string{"versionId", "partNumber", "Range", "response-content-type", "response-content-language", "response-expires", "response-cache-control", "response-content-disposition", "response-content-encoding"})
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
w := httptest.NewRecorder()
|
|
|
|
defer func() {
|
|
if recover() != nil {
|
|
err = errors.New("panic in httptest.NewRequest")
|
|
}
|
|
}()
|
|
r := httptest.NewRequest(http.MethodGet, defaultURL+params, nil)
|
|
if r != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
reqInfo := middleware.NewReqInfo(w, r, middleware.ObjectRequest{Bucket: fuzzBktName, Object: objName}, "")
|
|
r = r.WithContext(middleware.SetReqInfo(fuzzHc.Context(), reqInfo))
|
|
r = r.WithContext(middleware.SetBox(r.Context(), &middleware.Box{AccessBox: fuzzBox}))
|
|
|
|
err = generateHeaders(tp, r, []string{"x-amz-expected-bucket-owner", "If-Match", "If-None-Match", "If-Modified-Since", "If-Unmodified-Since", "x-amz-server-side-encryption-customer-algorithm", "x-amz-server-side-encryption-customer-key", "x-amz-server-side-encryption-customer-key-MD5", "Range"})
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
fuzzHc.Handler().GetObjectHandler(w, r)
|
|
|
|
return fuzzSuccessExitCode
|
|
}
|
|
|
|
func InitFuzzPutObjectHandler() {
|
|
createTestBucketAndInitContext()
|
|
}
|
|
|
|
func DoFuzzPutObjectHandler(input []byte) int {
|
|
// FUZZER INIT
|
|
if len(input) < 100 {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
tp, err := utils.NewTypeProvider(input)
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
objName, err := tp.GetString()
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
body, err := tp.GetBytes()
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
w := httptest.NewRecorder()
|
|
|
|
r := httptest.NewRequest(http.MethodPut, defaultURL+objName, bytes.NewReader(body))
|
|
if r != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
reqInfo := middleware.NewReqInfo(w, r, middleware.ObjectRequest{Bucket: fuzzBktName, Object: objName}, "")
|
|
r = r.WithContext(middleware.SetReqInfo(fuzzHc.Context(), reqInfo))
|
|
r = r.WithContext(middleware.SetBox(r.Context(), &middleware.Box{AccessBox: fuzzBox}))
|
|
|
|
err = generateHeaders(tp, r, []string{"x-amz-expected-bucket-owner", "X-Amz-Grant-Read", "X-Amz-Grant-Full-Control", "X-Amz-Grant-Write", "X-Amz-Acl", "X-Amz-Tagging", "Content-Type", "Cache-Control", "Expires", "Content-Language", "Content-Encoding", "x-amz-server-side-encryption-customer-algorithm", "x-amz-server-side-encryption-customer-key", "x-amz-server-side-encryption-customer-key-MD5", "X-Amz-Content-Sha256", "X-Amz-Object-Lock-Legal-Hold", "X-Amz-Object-Lock-Mode", "X-Amz-Object-Lock-Retain-Until-Date", "X-Amz-Bypass-Governance-Retention", "X-Amz-Meta-*"})
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
err = addMD5Header(tp, r, body)
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
fuzzHc.Handler().PutObjectHandler(w, r)
|
|
|
|
return fuzzSuccessExitCode
|
|
}
|
|
|
|
func FuzzPutObjectHandler(f *testing.F) {
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
|
DoFuzzPutObjectHandler(data)
|
|
})
|
|
}
|
|
|
|
func InitFuzzPutObjectLegalHoldHandler() {
|
|
createTestBucketAndInitContext()
|
|
}
|
|
|
|
func DoFuzzPutObjectLegalHoldHandler(input []byte) int {
|
|
// FUZZER INIT
|
|
if len(input) < 100 {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
tp, err := utils.NewTypeProvider(input)
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
_, objName, err := postObject(tp)
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
var hold data.LegalHold
|
|
err = tp.Fill(&hold)
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
rawBody, err := xml.Marshal(hold)
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
w := httptest.NewRecorder()
|
|
|
|
r := httptest.NewRequest(http.MethodPut, defaultURL+objName+"?legal-hold", bytes.NewReader(rawBody))
|
|
if r != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
reqInfo := middleware.NewReqInfo(w, r, middleware.ObjectRequest{Bucket: fuzzBktName, Object: objName}, "")
|
|
r = r.WithContext(middleware.SetReqInfo(fuzzHc.Context(), reqInfo))
|
|
r = r.WithContext(middleware.SetBox(r.Context(), &middleware.Box{AccessBox: fuzzBox}))
|
|
|
|
err = addMD5Header(tp, r, rawBody)
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
fuzzHc.Handler().PutObjectLegalHoldHandler(w, r)
|
|
|
|
return fuzzSuccessExitCode
|
|
}
|
|
|
|
func FuzzPutObjectLegalHoldHandler(f *testing.F) {
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
|
DoFuzzPutObjectLegalHoldHandler(data)
|
|
})
|
|
}
|
|
|
|
func InitFuzzPutBucketObjectLockConfigHandler() {
|
|
createTestBucketAndInitContext()
|
|
}
|
|
|
|
func DoFuzzPutBucketObjectLockConfigHandler(input []byte) int {
|
|
// FUZZER INIT
|
|
if len(input) < 100 {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
tp, err := utils.NewTypeProvider(input)
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
var hold data.ObjectLockConfiguration
|
|
err = tp.Fill(&hold)
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
rawBody, err := xml.Marshal(&hold)
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
w := httptest.NewRecorder()
|
|
|
|
r := httptest.NewRequest(http.MethodPut, defaultURL+"?object-lock", bytes.NewReader(rawBody))
|
|
if r != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
reqInfo := middleware.NewReqInfo(w, r, middleware.ObjectRequest{Bucket: fuzzBktName, Object: ""}, "")
|
|
r = r.WithContext(middleware.SetReqInfo(fuzzHc.Context(), reqInfo))
|
|
r = r.WithContext(middleware.SetBox(r.Context(), &middleware.Box{AccessBox: fuzzBox}))
|
|
|
|
err = addMD5Header(tp, r, rawBody)
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
err = generateHeaders(tp, r, []string{"x-amz-expected-bucket-owner", "x-amz-bucket-object-lock-token"})
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
fuzzHc.Handler().PutBucketObjectLockConfigHandler(w, r)
|
|
|
|
return fuzzSuccessExitCode
|
|
}
|
|
|
|
func FuzzPutBucketObjectLockConfigHandler(f *testing.F) {
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
|
DoFuzzPutBucketObjectLockConfigHandler(data)
|
|
})
|
|
}
|
|
|
|
func InitFuzzPutObjectRetentionHandler() {
|
|
createTestBucketAndInitContext()
|
|
}
|
|
|
|
func DoFuzzPutObjectRetentionHandler(input []byte) int {
|
|
// FUZZER INIT
|
|
if len(input) < 100 {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
tp, err := utils.NewTypeProvider(input)
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
_, objName, err := postObject(tp)
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
var retention data.Retention
|
|
err = tp.Fill(&retention)
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
rawBody, err := xml.Marshal(retention)
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
w := httptest.NewRecorder()
|
|
|
|
defer func() {
|
|
if recover() != nil {
|
|
err = errors.New("panic in httptest.NewRequest")
|
|
}
|
|
}()
|
|
r := httptest.NewRequest(http.MethodPut, defaultURL+objName+"?retention", bytes.NewReader(rawBody))
|
|
if r != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
reqInfo := middleware.NewReqInfo(w, r, middleware.ObjectRequest{Bucket: fuzzBktName, Object: objName}, "")
|
|
r = r.WithContext(middleware.SetReqInfo(fuzzHc.Context(), reqInfo))
|
|
r = r.WithContext(middleware.SetBox(r.Context(), &middleware.Box{AccessBox: fuzzBox}))
|
|
|
|
err = addMD5Header(tp, r, rawBody)
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
err = generateHeaders(tp, r, []string{"x-amz-expected-bucket-owner", "x-amz-bypass-governance-retention"})
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
fuzzHc.Handler().PutObjectRetentionHandler(w, r)
|
|
|
|
return fuzzSuccessExitCode
|
|
}
|
|
|
|
func FuzzPutObjectRetentionHandler(f *testing.F) {
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
|
DoFuzzPutObjectRetentionHandler(data)
|
|
})
|
|
}
|
|
|
|
func InitFuzzPutBucketAclHandler() {
|
|
createTestBucketAndInitContext()
|
|
}
|
|
|
|
func DoFuzzPutBucketAclHandler(input []byte) int {
|
|
// FUZZER INIT
|
|
if len(input) < 100 {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
tp, err := utils.NewTypeProvider(input)
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
var policy AccessControlPolicy
|
|
err = tp.Fill(&policy)
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
rawBody, err := xml.Marshal(policy)
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
w := httptest.NewRecorder()
|
|
r := httptest.NewRequest(http.MethodPut, defaultURL+"?acl", bytes.NewReader(rawBody))
|
|
reqInfo := middleware.NewReqInfo(w, r, middleware.ObjectRequest{Bucket: fuzzBktName, Object: ""}, "")
|
|
r = r.WithContext(middleware.SetReqInfo(fuzzHc.Context(), reqInfo))
|
|
r = r.WithContext(middleware.SetBox(r.Context(), &middleware.Box{AccessBox: fuzzBox}))
|
|
|
|
err = addMD5Header(tp, r, rawBody)
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
err = generateHeaders(tp, r, []string{"x-amz-expected-bucket-owner", "x-amz-acl", "x-amz-expected-bucket-owner", "x-amz-grant-full-control", "x-amz-grant-read", "x-amz-grant-read-acp", "x-amz-grant-write", "x-amz-grant-write-acp"})
|
|
if err != nil {
|
|
return fuzzFailExitCode
|
|
}
|
|
|
|
fuzzHc.Handler().PutBucketACLHandler(w, r)
|
|
|
|
return fuzzSuccessExitCode
|
|
}
|
|
|
|
func FuzzPutBucketAclHandler(f *testing.F) {
|
|
f.Fuzz(func(t *testing.T, data []byte) {
|
|
DoFuzzPutBucketAclHandler(data)
|
|
})
|
|
}
|