Path sanitation

master
Caj Larsson 3 years ago
parent e6e2f372dd
commit 82067ca87c

@ -57,6 +57,12 @@ func (s SwampFileService) getOrCreateNs(namespace_in string) *namespace.Namespac
func (s SwampFileService) SaveFile(ref swampfile.FileReference, src io.Reader, size int64) error {
ns := s.getOrCreateNs(ref.UserAgent)
err := ref.Clean(true)
if err != nil {
return err
}
if !ns.FileQuota.Allows(size) {
return namespace.ErrExceedQuota
}
@ -78,9 +84,11 @@ func (s SwampFileService) SaveFile(ref swampfile.FileReference, src io.Reader, s
func (s SwampFileService) OpenOutFile(ref swampfile.FileReference) (swampfile.SwampOutFile, error) {
ns := s.getOrCreateNs(ref.UserAgent)
// if err == namespace.ErrNotExists {
// return nil, err
// }
err := ref.Clean(true)
if err != nil {
return nil, err
}
f, err := s.swamp_file_repo.Open(ref.Path, strconv.FormatInt(ns.ID, 10))

@ -11,9 +11,9 @@ import (
m_swampfile "caj-larsson/bog/infrastructure/memory/swampfile"
)
var file_ref1 = swampfile.FileReference{"ptah1", "ua1"}
var file_ref2 = swampfile.FileReference{"path1", "ua2"}
var file_ref3 = swampfile.FileReference{"path2", "ua1"}
var file_ref1 = swampfile.FileReference{"/ptah1", "ns1"}
var file_ref2 = swampfile.FileReference{"/path1", "ns2"}
var file_ref3 = swampfile.FileReference{"/path2", "ns1"}
func NewTestSwampFileService() SwampFileService {
file_repo := m_swampfile.NewRepository()
@ -67,12 +67,12 @@ func TestFileIsReadBack(t *testing.T) {
is.Equal(outfile.String(), "My bog data")
}
func TestUAIsolation(t *testing.T) {
func TestNSIsolation(t *testing.T) {
is := is.New(t)
s := NewTestSwampFileService()
ns1_file := bytes.NewBufferString("My bog data ua1")
ns2_file := bytes.NewBufferString("My bog data ua2")
ns1_file := bytes.NewBufferString("My bog data ns1")
ns2_file := bytes.NewBufferString("My bog data ns2")
_ = s.SaveFile(file_ref1, ns1_file, int64(ns1_file.Len()))
_ = s.SaveFile(file_ref2, ns2_file, int64(ns2_file.Len()))
@ -82,11 +82,26 @@ func TestUAIsolation(t *testing.T) {
outfile := bytes.NewBufferString("")
_, _ = outfile.ReadFrom(outswampfile)
is.Equal(outfile.String(), "My bog data ua1")
is.Equal(outfile.String(), "My bog data ns1")
}
func TestCleanPath(t *testing.T) {
func TestPathStrictMode(t *testing.T) {
is := is.New(t)
s := NewTestSwampFileService()
ns_file := bytes.NewBufferString("My bog data ns1")
ref := swampfile.FileReference {
"/path/../with/../backrefs",
"ns1",
}
outfile, err := s.OpenOutFile(ref)
is.Equal(err, swampfile.ErrUnacceptablePath)
is.Equal(outfile, nil)
is.Equal(CleanPath("/"), "/")
err = s.SaveFile(ref, ns_file, int64(ns_file.Len()))
is.Equal(err, swampfile.ErrUnacceptablePath)
}

@ -19,4 +19,5 @@ var (
ErrNotExists = errors.New("row not exists")
ErrUpdateFailed = errors.New("update failed")
ErrDeleteFailed = errors.New("delete failed")
ErrUnacceptablePath = errors.New("unacceptable path")
)

@ -2,6 +2,9 @@ package swampfile
import (
"io"
"path"
"path/filepath"
"strings"
"time"
)
@ -27,3 +30,15 @@ type FileReference struct {
Path string
UserAgent string
}
func (fr *FileReference) Clean(strict bool) error {
c := filepath.FromSlash(path.Clean("/" + strings.Trim(fr.Path, "/")))
if c != fr.Path && strict {
return ErrUnacceptablePath
}
fr.Path = c
return nil
}

@ -0,0 +1,44 @@
package swampfile
import (
"github.com/matryer/is"
"testing"
)
func TestSwampPathNotStrict(t *testing.T) {
cases := []struct {
dirty string
clean string
}{
{"/", "/"},
{"..", "/"},
{"/../a", "/a"},
{"/../a/../a", "/a"},
{"../b", "/b"},
}
is := is.New(t)
for _, tc := range cases {
rf := FileReference{
tc.dirty,
"ns",
}
err := rf.Clean(false)
is.NoErr(err)
is.Equal(rf.Path, tc.clean)
}
}
func TestSwampPathStrict(t *testing.T) {
is := is.New(t)
rf := FileReference{
"/a/../b",
"ns",
}
err := rf.Clean(true)
is.Equal(err, ErrUnacceptablePath)
}
Loading…
Cancel
Save