78 lines
1.6 KiB
Go
78 lines
1.6 KiB
Go
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"errors"
|
|
"fmt"
|
|
"log"
|
|
"os"
|
|
"strings"
|
|
"syscall"
|
|
)
|
|
|
|
func parseUint32Fast(s string) (int, error) {
|
|
sLen := len(s)
|
|
if sLen < 1 {
|
|
return -1, errors.New("zero length string")
|
|
}
|
|
if sLen > 10 {
|
|
return -1, errors.New("string too long")
|
|
}
|
|
|
|
n := 0
|
|
for i, ch := range []byte(s) {
|
|
ch -= '0'
|
|
if ch > 9 {
|
|
return -1, fmt.Errorf("invalid character '%s' at index %d", string([]byte{ch}), i)
|
|
}
|
|
n = n*10 + int(ch)
|
|
}
|
|
return n, nil
|
|
}
|
|
|
|
func parseConfig(p string, puid int) (fid int, ok bool) {
|
|
// refuse to run if fsurc is not protected correctly
|
|
if s, err := os.Stat(p); err != nil {
|
|
log.Fatal(err)
|
|
} else if s.Mode().Perm() != 0400 {
|
|
log.Fatal("bad fsurc perm")
|
|
} else if st := s.Sys().(*syscall.Stat_t); st.Uid != 0 || st.Gid != 0 {
|
|
log.Fatal("fsurc must be owned by uid 0")
|
|
}
|
|
|
|
if r, err := os.Open(p); err != nil {
|
|
log.Fatal(err)
|
|
return -1, false
|
|
} else {
|
|
s := bufio.NewScanner(r)
|
|
var line int
|
|
for s.Scan() {
|
|
line++
|
|
|
|
// <puid> <fid>
|
|
lf := strings.SplitN(s.Text(), " ", 2)
|
|
if len(lf) != 2 {
|
|
log.Fatalf("invalid entry on line %d", line)
|
|
}
|
|
|
|
var puid0 int
|
|
if puid0, err = parseUint32Fast(lf[0]); err != nil || puid0 < 1 {
|
|
log.Fatalf("invalid parent uid on line %d", line)
|
|
}
|
|
|
|
ok = puid0 == puid
|
|
if ok {
|
|
// allowed fid range 0 to 99
|
|
if fid, err = parseUint32Fast(lf[1]); err != nil || fid < 0 || fid > 99 {
|
|
log.Fatalf("invalid fortify uid on line %d", line)
|
|
}
|
|
return
|
|
}
|
|
}
|
|
if err = s.Err(); err != nil {
|
|
log.Fatalf("cannot read fsurc: %v", err)
|
|
}
|
|
return -1, false
|
|
}
|
|
}
|