Add uid and gid handling

Add the ability to drop to normal user with configurable user and group
ids
This commit is contained in:
Felix Niederwanger 2022-02-13 10:44:35 +01:00
parent 1985b09e8a
commit f1a9fdef88
Signed by: phoenix
GPG key ID: 6E77A590E3F6D71C
3 changed files with 54 additions and 0 deletions

View file

@ -4,6 +4,7 @@ import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
@ -14,6 +15,8 @@ type Config struct {
BindAddr string // Optional binding address
ContentDir string // Gemini content directory to serve
Chroot string // chroot directory, if configured
Uid int // If not 0 the program will switch to this user id after initialization
Gid int // If not 0 the program will switch to this group id after initialization
}
func (cf *Config) SetDefaults() {
@ -56,6 +59,16 @@ func (cf *Config) LoadConfigFile(filename string) error {
cf.ContentDir = value
} else if name == "chroot" {
cf.Chroot = value
} else if name == "uid" {
cf.Uid, err = strconv.Atoi(value)
if err != nil || cf.Uid < 0 || cf.Uid > 65536 {
return fmt.Errorf("Invalid uid in line %d", lineCount)
}
} else if name == "gid" {
cf.Gid, err = strconv.Atoi(value)
if err != nil || cf.Gid < 0 || cf.Gid > 65536 {
return fmt.Errorf("Invalid gid in line %d", lineCount)
}
} else {
return fmt.Errorf("Unknown setting in line %d", lineCount)
}

View file

@ -52,6 +52,26 @@ func chroot(dir string) error {
return nil
}
func setuid(uid int) error {
if err := syscall.Setuid(uid); err != nil {
return err
}
if syscall.Getuid() != uid {
return fmt.Errorf("getuid != %d", uid)
}
return nil
}
func setgid(gid int) error {
if err := syscall.Setgid(gid); err != nil {
return err
}
if syscall.Getgid() != gid {
return fmt.Errorf("getgid != %d", gid)
}
return nil
}
func main() {
config.SetDefaults()
@ -84,6 +104,8 @@ func main() {
os.Exit(1)
}
/* Drop privileges here*/
// Chroot, if configured to do so
if config.Chroot != "" {
if err := chroot(config.Chroot); err != nil {
@ -91,6 +113,21 @@ func main() {
os.Exit(1)
}
}
// Setuid and setgid if configured
if config.Gid > 0 {
if err := setgid(config.Gid); err != nil {
fmt.Fprintf(os.Stderr, "setgid failed: %s\n", err)
os.Exit(1)
}
fmt.Printf("gid = %d\n", syscall.Getgid())
}
if config.Uid > 0 {
if err := setuid(config.Uid); err != nil {
fmt.Fprintf(os.Stderr, "setuid failed: %s\n", err)
os.Exit(1)
}
fmt.Printf("uid = %d\n", syscall.Getuid())
}
// Make the content dir absolute
if !strings.HasPrefix(config.ContentDir, "/") {

View file

@ -18,3 +18,7 @@ ContentDir = ./gemini/
## Chroot into this directory (uncomment to enable)
## Note: If enabled, the ContentDir needs to be adapted accordingly
# chroot = /srv/gemini/
## Custom user and group ids to run orion as
# Uid = 5000
# Gid = 5000