Add path sanitizer for Exec, fix error check in dynamic rendering (#38)

[X] Check for Exec path outside of root in Transformer
[X] Fix error checking in DynamicRenderingTransformer

Closes #37

Co-authored-by: Nicolas Herry <beastieboy@beastieboy.net>
Reviewed-on: #38
pull/40/head
beastieboy 7 months ago
parent b5d4cfdf15
commit ee8290bf49
  1. 2
      cmd/marmotte/main.go
  2. 2
      gopher/dynamic.go
  3. 9
      gopher/response.go
  4. 30
      gopher/transformers.go
  5. 1
      testdata/gophermap

@ -104,7 +104,7 @@ func main() {
Str("UsersGopherspace", viper.GetString("users_gopherspace")).
Send()
log.Info().
Str("ErrorRoot", viper.GetString("error")).
Str("ErrorRoot", viper.GetString("errors")).
Send()

@ -23,7 +23,7 @@ func RunTemplate(dc *DynamicContext, p string) ([]string, error) {
var err error
// read the template found in the FullPath
t := template.Must(template.ParseFiles(p))
if t != nil {
var buf bytes.Buffer
if err := t.Execute(io.Writer(&buf), dc); err == nil {

@ -52,15 +52,6 @@ func NewResponse(c Context, rq Request) *Response {
if rq.Type == Map {
r.Type = PlainText
} else {
// mtype, err := mimetype.DetectFile(rq.FullPath)
// if err != nil {
// log.Error().
// Err(err).
// Str("FullPath", rq.FullPath).
// Msg("Error detecting a MIME file type")
// return &r
// }
t, err := FileType(rq.FullPath)
if err != nil {

@ -164,6 +164,13 @@ func SelectorRewriteTransformerFor(from string, to string) func(*Context, *Reque
// ExecutableTransformer is a ResponseTransformerFunc that runs the executable found at rq.Fullpath, and crafts a new Request object with the paths set to the filename or the directory name returned by the executable. Parameters are returned unchanged in case of errors. Note that the executable must have the executable bit set in its Unix permission mode for the owner or the group.
func ExecutableTransformer(c *Context, rq Request, rs *Response, err error) (*Context, Request, *Response, error) {
execpath, _ := filepath.Abs(filepath.Clean(rq.FullPath))
absroot, _ := filepath.Abs(c.Root)
if ! strings.HasPrefix(execpath, absroot) {
// err = os.ErrPermission
rs.ErrorCode = GopherErrorWrongPermissions
return ErrorRedirectTransformer(c, rq, rs, err)
}
fi, err := os.Stat(rq.FullPath)
if err == nil && fi.Mode()&0110 != 0 {
@ -186,7 +193,7 @@ func ExecutableTransformer(c *Context, rq Request, rs *Response, err error) (*Co
Str("Executable", rq.FullPath).
Msg("An error occurred creating a Request for an executable")
}
}
}
// by default, return parameters unchanged
return c, rq, rs, err
}
@ -198,19 +205,6 @@ func ErrorRedirectTransformer(c *Context, rq Request, rs *Response, err error) (
rs.ErrorCode = GopherErrorSelectorNotFound
}
// // read the template found in c.ErrorRoot / rs.ErrorCode.gt
// p := filepath.Clean(fmt.Sprint(c.ErrorRoot, "/", rs.ErrorCode,".gt"))
// t := template.Must(template.ParseFiles(p))
// if t != nil {
// var buf bytes.Buffer
// err = t.Execute(io.Writer(&buf), GopherErrorInfo { Selector: rq.Path })
// rs.ContentText = []string{buf.String()}
// rs.Type = PlainText
// return c, rq, rs, err
// }
// Prepare a new Request with the path
newRq := rq
newRq.Path = fmt.Sprint(rs.ErrorCode, ".gt")
@ -228,6 +222,7 @@ func ErrorRedirectTransformer(c *Context, rq Request, rs *Response, err error) (
if c, newRq, rs, err = DynamicRenderingTransformerFor(&dc)(c, newRq, rs, err); err != nil {
log.Error().
Str("FullPath", newRq.FullPath).
Err(err).
Msg("Error reading an error template")
rs.ContentText = []string {fmt.Sprint("Error retrieving the error page for the request. The original error code was ", rs.ErrorCode, " for the selector ", rq.Path)}
@ -254,12 +249,13 @@ func DynamicRenderingTransformer(c *Context, rq Request, rs *Response, err error
// DynamicRenderingTransformerFor is a function that returns a function that executes the template found in rq.FullPath, and passes it the DynamicContext instance given in argument. It returns the result of runnig the template as a rs.PlainText response, in the .ContentText field.
func DynamicRenderingTransformerFor(dc *DynamicContext) func(*Context, Request, *Response, error) (*Context, Request, *Response, error) {
return func(c *Context, rq Request, rs *Response, err error) (*Context, Request, *Response, error) {
if s, err := RunTemplate(dc, rq.FullPath); err == nil {
var s []string
if s, err = RunTemplate(dc, rq.FullPath); err == nil {
rs.ContentText = s
rs.Type = PlainText
}
return c, rq, rs, err
}
}

@ -4,3 +4,4 @@ iThis is the menu from the gophermap! fake (NULL) 0
0About this server /about-server localhost 7070
0About me /about-me localhost 7070
0Generate a text file /createtextfile.sh localhost 7070
0Call a program outside the gopher root ../../../../../bin/echo localhost 7070

Loading…
Cancel
Save