File: security_dropprivs.go

package info (click to toggle)
molly-brown 0.0~git20230820.2068c3b-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 224 kB
  • sloc: sh: 67; makefile: 4
file content (119 lines) | stat: -rw-r--r-- 2,609 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
// +build linux,go1.16 aix darwin dragonfly freebsd illumos netbsd openbsd solaris

package main

import (
	"log"
	"os"
	"os/user"
	"strconv"
	"syscall"
)

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
}

func getUserInfo(unprivUser string) (userInfo, error) {
	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 {
		log.Println("Could not get supplementary groups: ", err.Error())
		return ui, err
	}
	ui.supp_groups = supp_groups
	ui.unpriv_uid = -1
	ui.unpriv_gid = -1

	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

	if ui.root_user || ui.root_prim_group {
		nobody_user, err := user.Lookup(unprivUser)
		if err != nil {
			log.Println("Running as root but could not lookup UID for user " + unprivUser + ": " + err.Error())
			return ui, err
		}
		ui.unpriv_uid, err = strconv.Atoi(nobody_user.Uid)
		ui.unpriv_gid, err = strconv.Atoi(nobody_user.Gid)
		if err != nil {
			log.Println("Running as root but could not lookup UID for user " + unprivUser + ": " + err.Error())
			return ui, err
		}
	}

	return ui, nil
}
func DropPrivs(ui userInfo) error {

	// If we're already unprivileged, all good
	if !ui.need_drop {
		return nil
	}

	// Drop supplementary groups
	if ui.root_supp_group {
		err := syscall.Setgroups([]int{})
		if err != nil {
			log.Println("Could not unset supplementary groups: " + err.Error())
			return err
		}
	}

	// 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)
		if err != nil {
			log.Println("Could not setgid to " + strconv.Itoa(target_gid) + ": " + err.Error())
			return err
		}
	}

	// Setuid()
	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)
		if err != nil {
			log.Println("Could not setuid to " + strconv.Itoa(target_uid) + ": " + err.Error())
			return err
		}
	}

	return nil
}