From d35673d0f2238874d9d12e85202b21140648ebb0 Mon Sep 17 00:00:00 2001 From: ccamel Date: Thu, 13 Apr 2023 08:53:31 +0200 Subject: [PATCH] feat(logic): add filtered virtual FS --- x/logic/fs/filtered_fs.go | 49 +++++++++++++++++++++++++++++++++++++++ x/logic/fs/virtual_fs.go | 6 ++--- 2 files changed, 52 insertions(+), 3 deletions(-) create mode 100644 x/logic/fs/filtered_fs.go diff --git a/x/logic/fs/filtered_fs.go b/x/logic/fs/filtered_fs.go new file mode 100644 index 00000000..1aac4e65 --- /dev/null +++ b/x/logic/fs/filtered_fs.go @@ -0,0 +1,49 @@ +package fs + +import ( + "io/fs" + "net/url" + + "github.com/okp4/okp4d/x/logic/util" +) + +// FilteredFS is a wrapper around a fs.FS that filters out files that are not allowed to be read. +// This is used to prevent the interpreter from reading files, using protocols that are not allowed to be used +// by the interpreter on the blockchain. +// The whitelist and blacklist are mutually exclusive. If both are set, the blacklist will be ignored. +type FilteredFS struct { + decorated fs.FS + whitelist []*url.URL + blacklist []*url.URL +} + +var _ fs.FS = (*FilteredFS)(nil) + +// NewFilteredFS returns a new FilteredFS object that will filter out files that are not allowed to be read +// according to the whitelist and blacklist parameters. +func NewFilteredFS(whitelist, blacklist []*url.URL, decorated fs.FS) *FilteredFS { + return &FilteredFS{ + decorated: decorated, + whitelist: whitelist, + blacklist: blacklist, + } +} + +// Open opens the named file. +// The name parameter is a URL that will be parsed and checked against the whitelist and blacklist configured. +func (f *FilteredFS) Open(name string) (fs.File, error) { + urlFile, err := url.Parse(name) + if err != nil { + return nil, err + } + + if !util.WhitelistBlacklistMatches(f.whitelist, f.blacklist, util.UrlMatches)(urlFile) { + return nil, &fs.PathError{ + Op: "open", + Path: name, + Err: fs.ErrPermission, + } + } + + return f.decorated.Open(name) +} diff --git a/x/logic/fs/virtual_fs.go b/x/logic/fs/virtual_fs.go index 9529e6ab..dba6a235 100644 --- a/x/logic/fs/virtual_fs.go +++ b/x/logic/fs/virtual_fs.go @@ -16,12 +16,12 @@ var _ fs.FS = (*VirtualFS)(nil) // NewVirtualFS return a new VirtualFS object that will handle all virtual file on the interpreter. // File can be provided from different sources like CosmWasm cw-storage smart contract. -func NewVirtualFS(ctx goctx.Context, handlers []URIHandler) VirtualFS { +func NewVirtualFS(ctx goctx.Context, handlers []URIHandler) *VirtualFS { router := NewRouter() for _, handler := range handlers { router.RegisterHandler(handler) } - return VirtualFS{ + return &VirtualFS{ ctx: ctx, router: router, } @@ -36,7 +36,7 @@ func NewVirtualFS(ctx goctx.Context, handlers []URIHandler) VirtualFS { // Open should reject attempts to open names that do not satisfy // ValidPath(name), returning a *PathError with Err set to // ErrInvalid or ErrNotExist. -func (f VirtualFS) Open(name string) (fs.File, error) { +func (f *VirtualFS) Open(name string) (fs.File, error) { data, err := f.router.Open(f.ctx, name) if err != nil { return nil, &fs.PathError{