mirror of
https://github.com/la5nta/pat
synced 2026-08-07 22:32:06 -04:00
Limit prehook executable paths to the prehooks dir
This commit is contained in:
parent
ba089e05dd
commit
6592fcf937
3 changed files with 48 additions and 22 deletions
|
|
@ -167,9 +167,14 @@ func (a *App) Connect(connectStr string) (success bool) {
|
|||
a.dialing = url
|
||||
a.websocketHub.UpdateStatus()
|
||||
|
||||
if exec := url.Params.Get("prehook"); exec != "" {
|
||||
if err := prehook.Verify(exec); err != nil {
|
||||
log.Printf("prehook invalid: %s", err)
|
||||
prehookScript := prehook.Script{
|
||||
Dir: a.options.PrehooksPath,
|
||||
File: url.Params.Get("prehook"),
|
||||
Args: url.Params["prehook-arg"],
|
||||
}
|
||||
if prehookScript.File != "" {
|
||||
if err := prehookScript.VerifyFile(); err != nil {
|
||||
log.Printf("invalid prehook: %s", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
@ -192,19 +197,15 @@ func (a *App) Connect(connectStr string) (success bool) {
|
|||
return
|
||||
}
|
||||
|
||||
if exec := url.Params.Get("prehook"); exec != "" {
|
||||
if prehookScript.File != "" {
|
||||
log.Println("Running prehook...")
|
||||
script := prehook.Script{
|
||||
File: exec,
|
||||
Args: url.Params["prehook-arg"],
|
||||
Env: append([]string{
|
||||
buildinfo.AppName + "_DIAL_URL=" + connectStr,
|
||||
buildinfo.AppName + "_REMOTE_ADDR=" + conn.RemoteAddr().String(),
|
||||
buildinfo.AppName + "_LOCAL_ADDR=" + conn.LocalAddr().String(),
|
||||
}, append(os.Environ(), a.Env()...)...),
|
||||
}
|
||||
prehookScript.Env = append([]string{
|
||||
buildinfo.AppName + "_DIAL_URL=" + connectStr,
|
||||
buildinfo.AppName + "_REMOTE_ADDR=" + conn.RemoteAddr().String(),
|
||||
buildinfo.AppName + "_LOCAL_ADDR=" + conn.LocalAddr().String(),
|
||||
}, append(os.Environ(), a.Env()...)...)
|
||||
conn = prehook.Wrap(conn)
|
||||
if err := script.Execute(ctx, conn); err != nil {
|
||||
if err := prehookScript.Execute(ctx, conn); err != nil {
|
||||
conn.Close()
|
||||
log.Printf("Prehook script failed: %s", err)
|
||||
return
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ params:
|
|||
?freq= Sets QSY frequency (ardop and ax25 only)
|
||||
?host= Overrides the host part of the path. Useful for serial-tnc to specify e.g. /dev/ttyS0.
|
||||
?prehook= Sets an executable middleware to run before the connection is handed over to the B2F protocol.
|
||||
The executable must be given as full path, or a file located in $PATH or {CONFIG_DIR}/prehooks/.
|
||||
The executable must be located in {CONFIG_DIR}/prehooks/.
|
||||
Received packets are forwarded to STDIN. Data written to STDOUT forwarded to the remote node.
|
||||
Additional arguments can be passed with one or more &prehook-arg=.
|
||||
Environment variables describing the dialed connection are provided.
|
||||
|
|
|
|||
|
|
@ -12,9 +12,11 @@ import (
|
|||
"net"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/la5nta/pat/internal/debug"
|
||||
"github.com/la5nta/pat/internal/directories"
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
|
||||
|
|
@ -22,6 +24,7 @@ var ErrConnNotWrapped = errors.New("connection not wrapped for prehook")
|
|||
|
||||
type Script struct {
|
||||
File string
|
||||
Dir string
|
||||
Args []string
|
||||
Env []string
|
||||
}
|
||||
|
|
@ -41,13 +44,31 @@ type Conn struct {
|
|||
br *bufio.Reader
|
||||
}
|
||||
|
||||
// Verify returns nil if the given script file is found and valid.
|
||||
func Verify(file string) error {
|
||||
_, err := exec.LookPath(file)
|
||||
if errors.Is(err, exec.ErrDot) {
|
||||
err = nil
|
||||
// VerifyFile returns nil if the given script file is found and valid.
|
||||
func (s Script) VerifyFile() error {
|
||||
p, err := s.Path()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
info, err := os.Stat(p)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if info.IsDir() {
|
||||
return fmt.Errorf("%s: is a directory", s.File)
|
||||
}
|
||||
if _, err := exec.LookPath(p); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s Script) Path() (string, error) {
|
||||
p := filepath.Join(s.Dir, s.File)
|
||||
if !directories.IsInPath(s.Dir, p) {
|
||||
return "", fmt.Errorf("%s: escapes base path", p)
|
||||
}
|
||||
return p, nil
|
||||
}
|
||||
|
||||
// Wrap returns a wrapped connection with the ability to execute a prehook.
|
||||
|
|
@ -67,7 +88,11 @@ func (p *Conn) Read(b []byte) (int, error) { return p.br.Read(b) }
|
|||
// Execute executes the prehook script, returning nil if the process
|
||||
// terminated successfully (exit code 0).
|
||||
func (p *Conn) Execute(ctx context.Context, script Script) error {
|
||||
cmd := exec.CommandContext(ctx, script.File, script.Args...)
|
||||
name, err := script.Path()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cmd := exec.CommandContext(ctx, name, script.Args...)
|
||||
cmd.Env = script.Env
|
||||
cmd.Stderr = os.Stderr
|
||||
cmd.Stdout = p.Conn
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue