eb85a6e94c
The split reflects that between variables which can and cannot be overridden by .molly files, and this greatly simplifies the processing of said files, getting rid of the need for lots of ugly temporary variable thrashing.
77 lines
2.2 KiB
Go
77 lines
2.2 KiB
Go
package main
|
|
|
|
import (
|
|
"golang.org/x/sys/unix"
|
|
"log"
|
|
"path/filepath"
|
|
)
|
|
|
|
// Restrict access to the files specified in config in an OS-dependent way.
|
|
// The OpenBSD implementation uses pledge(2) and unveil(2) to restrict the
|
|
// operations available to the molly brown executable. Please note that (S)CGI
|
|
// processes that molly brown spawns or communicates with are unrestricted
|
|
// and should pledge their own restrictions and unveil their own files.
|
|
func enableSecurityRestrictions(config SysConfig, ui userInfo) error {
|
|
|
|
// Setuid to an unprivileged user
|
|
err := DropPrivs(ui)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Unveil the configured document base as readable.
|
|
log.Println("Unveiling \"" + config.DocBase + "\" as readable.")
|
|
err = unix.Unveil(config.DocBase, "r")
|
|
if err != nil {
|
|
log.Println("Could not unveil DocBase: " + err.Error())
|
|
return err
|
|
}
|
|
|
|
// Unveil cgi path globs as executable.
|
|
for _, cgiPath := range config.CGIPaths {
|
|
cgiGlobbedPaths, err := filepath.Glob(cgiPath)
|
|
for _, cgiGlobbedPath := range cgiGlobbedPaths {
|
|
log.Println("Unveiling \"" + cgiGlobbedPath + "\" as executable.")
|
|
err = unix.Unveil(cgiGlobbedPath, "rx")
|
|
if err != nil {
|
|
log.Println("Could not unveil CGIPaths: " + err.Error())
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
|
|
// Unveil scgi socket paths as readable and writeable.
|
|
for _, scgiSocket := range config.SCGIPaths {
|
|
log.Println("Unveiling \"" + scgiSocket + "\" as read/write.")
|
|
err = unix.Unveil(scgiSocket, "rw")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
// Finalize the unveil list.
|
|
// Any files not whitelisted above won't be accessible to molly brown.
|
|
err = unix.UnveilBlock()
|
|
if err != nil {
|
|
log.Println("Could not block unveil: " + err.Error())
|
|
return err
|
|
}
|
|
|
|
// Pledge to only use stdio, inet, and rpath syscalls.
|
|
promises := "stdio inet rpath"
|
|
if len(config.CGIPaths) > 0 {
|
|
// If CGI paths have been specified, also allow exec syscalls.
|
|
promises += " exec proc"
|
|
}
|
|
if len(config.SCGIPaths) > 0 {
|
|
// If SCGI paths have been specified, also allow unix sockets.
|
|
promises += " unix"
|
|
}
|
|
err = unix.PledgePromises(promises)
|
|
if err != nil {
|
|
log.Println("Could not pledge: " + err.Error())
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|