From 3ca8450a8496e1743af1cc0b9ef994e0af0c9a16 Mon Sep 17 00:00:00 2001 From: "kim (grufwub)" Date: Thu, 14 May 2020 13:10:31 +0100 Subject: [PATCH] update gophermap + cgi-bin path checks to use regex (should be more reliable) Signed-off-by: kim (grufwub) --- config.go | 35 ++++++++++++++++++++--------------- filecontents.go | 2 +- filesystem.go | 6 +++--- gophor.go | 4 ++++ regex.go | 20 ++++++++++++++++++++ 5 files changed, 48 insertions(+), 19 deletions(-) diff --git a/config.go b/config.go index be40793..6731e58 100644 --- a/config.go +++ b/config.go @@ -2,6 +2,7 @@ package main import ( "time" + "regexp" ) /* ServerConfig: @@ -12,31 +13,35 @@ import ( */ type ServerConfig struct { /* Executable Settings */ - Env []string - CgiEnv []string - CgiEnabled bool - MaxExecRunTime time.Duration + Env []string + CgiEnv []string + CgiEnabled bool + MaxExecRunTime time.Duration /* Content settings */ - CharSet string - FooterText []byte - PageWidth int + CharSet string + FooterText []byte + PageWidth int /* Logging */ - SysLog LoggerInterface - AccLog LoggerInterface + SysLog LoggerInterface + AccLog LoggerInterface /* Filesystem access */ - FileSystem *FileSystem + FileSystem *FileSystem /* Buffer sizes */ - SocketWriteBufSize int - SocketReadBufSize int - SocketReadMax int - SkipPrefixBufSize int - FileReadBufSize int + SocketWriteBufSize int + SocketReadBufSize int + SocketReadMax int + SkipPrefixBufSize int + FileReadBufSize int /* Socket deadlines */ SocketReadDeadline time.Duration SocketWriteDeadline time.Duration + + /* Precompiled regular expressions for performance */ + RgxGophermap *regexp.Regexp + RgxCgiBin *regexp.Regexp } diff --git a/filecontents.go b/filecontents.go index a7d32d5..42eb146 100644 --- a/filecontents.go +++ b/filecontents.go @@ -238,7 +238,7 @@ func readGophermap(path *RequestPath) ([]GophermapSection, *GophorError) { } /* Check if we've been supplied subgophermap or regular file */ - if subPath.HasAbsSuffix(GophermapFileStr) { + if isGophermap(subPath) { /* If executable, store as GophermapExecFileSection, else GophermapSubmapSection */ if stat.Mode().Perm() & 0100 != 0 { sections = append(sections, &GophermapExecFileSection { &Request{ subPath, parameters } }) diff --git a/filesystem.go b/filesystem.go index 1ab03a7..b040ea9 100644 --- a/filesystem.go +++ b/filesystem.go @@ -32,7 +32,7 @@ func (fs *FileSystem) Init(size int, fileSizeMax float64) { fs.CacheMap = NewFixedMap(size) fs.CacheMutex = sync.RWMutex{} fs.CacheFileMax = int64(BytesInMegaByte * fileSizeMax) - /* {,Reverse}Remap map is setup in `gophor.go`, no need to here */ + /* .Remaps and .Restricted are handled within gopher.go */ } func (fs *FileSystem) IsRestricted(path string) bool { @@ -103,7 +103,7 @@ func (fs *FileSystem) HandleRequest(responder *Responder) *GophorError { /* Directory */ case stat.Mode() & os.ModeDir != 0: /* Ignore anything under cgi-bin directory */ - if responder.Request.Path.HasRelPrefix(CgiBinDirStr) { + if withinCgiBin(responder.Request.Path) { return &GophorError{ IllegalPathErr, nil } } @@ -215,7 +215,7 @@ func (fs *FileSystem) FetchFile(responder *Responder) *GophorError { /* Create new file contents */ var contents FileContents - if responder.Request.Path.HasRelSuffix(GophermapFileStr) { + if isGophermap(responder.Request.Path) { contents = &GophermapContents{ responder.Request.Path, nil } } else { contents = &RegularFileContents{ responder.Request.Path, nil } diff --git a/gophor.go b/gophor.go index e22f33d..c887706 100644 --- a/gophor.go +++ b/gophor.go @@ -229,6 +229,10 @@ func setupServer() []*GophorListener { Config.FileSystem.Restricted = compileUserRestrictedRegex(*restrictedFiles) Config.FileSystem.Remaps = compileUserRemapRegex(*fileRemaps) + /* Precompile some helpful regex */ + Config.RgxGophermap = compileGophermapCheckRegex() + Config.RgxCgiBin = compileCgiBinCheckRegex() + /* Return the created listeners slice :) */ return listeners } diff --git a/regex.go b/regex.go index 9213ea0..3bc5b30 100644 --- a/regex.go +++ b/regex.go @@ -15,6 +15,16 @@ type FileRemap struct { Template string } +/* Pre-compile gophermap file string regex */ +func compileGophermapCheckRegex() *regexp.Regexp { + return regexp.MustCompile(`^(|.+/|.+\.)gophermap$`) +} + +/* Pre-compile cgi-bin path string regex */ +func compileCgiBinCheckRegex() *regexp.Regexp { + return regexp.MustCompile(`^cgi-bin(|/.*)$`) +} + /* Compile a user supplied new line separated list of regex statements */ func compileUserRestrictedRegex(restrictions string) []*regexp.Regexp { /* Return slice */ @@ -72,3 +82,13 @@ func compileUserRemapRegex(remaps string) []*FileRemap { return fileRemaps } + +/* Check if file path is gophermap */ +func isGophermap(path *RequestPath) bool { + return Config.RgxGophermap.MatchString(path.Relative()) +} + +/* Check if file path within cgi-bin */ +func withinCgiBin(path *RequestPath) bool { + return Config.RgxCgiBin.MatchString(path.Relative()) +}