2023-02-13 14:26:52 -05:00
|
|
|
// +build linux,go1.16 aix darwin dragonfly freebsd illumos netbsd openbsd solaris
|
|
|
|
|
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"log"
|
|
|
|
"os"
|
2023-02-19 07:17:24 -05:00
|
|
|
"os/user"
|
2023-02-13 14:26:52 -05:00
|
|
|
"strconv"
|
|
|
|
"syscall"
|
|
|
|
)
|
|
|
|
|
2023-02-19 07:17:24 -05:00
|
|
|
type userInfo struct {
|
|
|
|
uid int
|
|
|
|
euid int
|
|
|
|
gid int
|
|
|
|
egid int
|
|
|
|
supp_groups []int
|
|
|
|
is_setuid bool
|
|
|
|
is_setgid bool
|
|
|
|
root_user bool
|
|
|
|
root_prim_group bool
|
|
|
|
root_supp_group bool
|
|
|
|
need_drop bool
|
|
|
|
unpriv_uid int
|
|
|
|
unpriv_gid int
|
|
|
|
}
|
|
|
|
|
2023-02-23 12:49:15 -05:00
|
|
|
func getUserInfo(unprivUser string) (userInfo, error) {
|
2023-02-19 07:17:24 -05:00
|
|
|
var ui userInfo
|
|
|
|
ui.uid = os.Getuid()
|
|
|
|
ui.euid = os.Geteuid()
|
|
|
|
ui.gid = os.Getgid()
|
|
|
|
ui.egid = os.Getegid()
|
|
|
|
supp_groups, err := os.Getgroups()
|
|
|
|
if err != nil {
|
2023-02-19 08:40:54 -05:00
|
|
|
log.Println("Could not get supplementary groups: ", err.Error())
|
|
|
|
return ui, err
|
2023-02-19 07:17:24 -05:00
|
|
|
}
|
|
|
|
ui.supp_groups = supp_groups
|
|
|
|
ui.unpriv_uid = -1
|
|
|
|
ui.unpriv_gid = -1
|
2023-02-13 14:26:52 -05:00
|
|
|
|
2023-02-19 07:17:24 -05:00
|
|
|
ui.is_setuid = ui.uid != ui.euid
|
|
|
|
ui.is_setgid = ui.gid != ui.egid
|
|
|
|
ui.root_user = ui.uid == 0 || ui.euid == 0
|
|
|
|
ui.root_prim_group = ui.gid == 0 || ui.egid == 0
|
|
|
|
for _, gid := range ui.supp_groups {
|
|
|
|
if gid == 0 {
|
|
|
|
ui.root_supp_group = true
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ui.need_drop = ui.is_setuid || ui.is_setgid || ui.root_user || ui.root_prim_group || ui.root_supp_group
|
|
|
|
|
2023-02-19 12:28:52 -05:00
|
|
|
if ui.root_user || ui.root_prim_group {
|
2023-02-23 12:49:15 -05:00
|
|
|
nobody_user, err := user.Lookup(unprivUser)
|
2023-02-19 07:17:24 -05:00
|
|
|
if err != nil {
|
2023-02-23 12:49:15 -05:00
|
|
|
log.Println("Running as root but could not lookup UID for user " + unprivUser + ": " + err.Error())
|
2023-02-19 08:40:54 -05:00
|
|
|
return ui, err
|
2023-02-19 07:17:24 -05:00
|
|
|
}
|
|
|
|
ui.unpriv_uid, err = strconv.Atoi(nobody_user.Uid)
|
|
|
|
ui.unpriv_gid, err = strconv.Atoi(nobody_user.Gid)
|
|
|
|
if err != nil {
|
2023-02-23 12:49:15 -05:00
|
|
|
log.Println("Running as root but could not lookup UID for user " + unprivUser + ": " + err.Error())
|
2023-02-19 08:40:54 -05:00
|
|
|
return ui, err
|
2023-02-19 07:17:24 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-19 08:40:54 -05:00
|
|
|
return ui, nil
|
2023-02-19 07:17:24 -05:00
|
|
|
}
|
2023-02-19 09:04:34 -05:00
|
|
|
func DropPrivs(ui userInfo) error {
|
2023-02-19 07:17:24 -05:00
|
|
|
|
|
|
|
// If we're already unprivileged, all good
|
|
|
|
if !ui.need_drop {
|
2023-02-19 08:40:54 -05:00
|
|
|
return nil
|
2023-02-19 07:17:24 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// Drop supplementary groups
|
2023-02-23 14:04:48 -05:00
|
|
|
if ui.root_supp_group {
|
2023-02-23 14:03:21 -05:00
|
|
|
err := syscall.Setgroups([]int{})
|
|
|
|
if err != nil {
|
|
|
|
log.Println("Could not unset supplementary groups: " + err.Error())
|
2023-02-19 08:40:54 -05:00
|
|
|
return err
|
2023-02-19 07:17:24 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-19 12:28:52 -05:00
|
|
|
// Setgid()
|
|
|
|
if ui.root_prim_group || ui.is_setgid {
|
|
|
|
var target_gid int
|
|
|
|
if ui.root_prim_group {
|
|
|
|
target_gid = ui.unpriv_gid
|
|
|
|
} else {
|
|
|
|
target_gid = ui.gid
|
|
|
|
}
|
|
|
|
err := syscall.Setgid(target_gid)
|
2023-02-19 07:17:24 -05:00
|
|
|
if err != nil {
|
2023-02-19 12:28:52 -05:00
|
|
|
log.Println("Could not setgid to " + strconv.Itoa(target_gid) + ": " + err.Error())
|
2023-02-19 08:40:54 -05:00
|
|
|
return err
|
2023-02-19 07:17:24 -05:00
|
|
|
}
|
|
|
|
}
|
2023-02-13 14:26:52 -05:00
|
|
|
|
2023-02-19 07:17:24 -05:00
|
|
|
// Setuid()
|
2023-02-19 12:28:52 -05:00
|
|
|
if ui.root_user || ui.is_setuid {
|
|
|
|
var target_uid int
|
|
|
|
if ui.root_user {
|
|
|
|
target_uid = ui.unpriv_uid
|
|
|
|
} else {
|
|
|
|
target_uid = ui.uid
|
|
|
|
}
|
|
|
|
err := syscall.Setuid(target_uid)
|
2023-02-13 14:26:52 -05:00
|
|
|
if err != nil {
|
2023-02-19 12:28:52 -05:00
|
|
|
log.Println("Could not setuid to " + strconv.Itoa(target_uid) + ": " + err.Error())
|
2023-02-19 08:40:54 -05:00
|
|
|
return err
|
2023-02-13 14:26:52 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-19 08:40:54 -05:00
|
|
|
return nil
|
2023-02-13 14:26:52 -05:00
|
|
|
}
|