Skip to content

Commit 34f087d

Browse files
cathuggerneilalexanderXephobia
authored
argument to change uid/gid (#927)
different from #817 in that it can resolve user names, automatically use user's primary gid & allows specifying gid in the same argument, with `:` eg `username:groupname`. feel free to criticize & suggest different argument name & description because i didn't put much of thought to that. --------- Co-authored-by: Neil <[email protected]> Co-authored-by: VNAT <[email protected]> Co-authored-by: Neil Alexander <[email protected]>
1 parent c4b29b7 commit 34f087d

File tree

3 files changed

+106
-0
lines changed

3 files changed

+106
-0
lines changed

cmd/yggdrasil/chuser_other.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
//go:build !aix && !darwin && !dragonfly && !freebsd && !linux && !netbsd && !openbsd && !solaris
2+
// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris
3+
4+
package main
5+
6+
import "errors"
7+
8+
func chuser(user string) error {
9+
return errors.New("setting uid/gid is not supported on this platform")
10+
}

cmd/yggdrasil/chuser_unix.go

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
2+
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
3+
4+
package main
5+
6+
import (
7+
"errors"
8+
"fmt"
9+
"math"
10+
osuser "os/user"
11+
"strconv"
12+
"strings"
13+
"syscall"
14+
)
15+
16+
func chuser(user string) error {
17+
group := ""
18+
if i := strings.IndexByte(user, ':'); i >= 0 {
19+
user, group = user[:i], user[i+1:]
20+
}
21+
22+
u := (*osuser.User)(nil)
23+
g := (*osuser.Group)(nil)
24+
25+
if user != "" {
26+
if _, err := strconv.ParseUint(user, 10, 32); err == nil {
27+
u, err = osuser.LookupId(user)
28+
if err != nil {
29+
return fmt.Errorf("failed to lookup user by id %q: %v", user, err)
30+
}
31+
} else {
32+
u, err = osuser.Lookup(user)
33+
if err != nil {
34+
return fmt.Errorf("failed to lookup user by name %q: %v", user, err)
35+
}
36+
}
37+
}
38+
if group != "" {
39+
if _, err := strconv.ParseUint(group, 10, 32); err == nil {
40+
g, err = osuser.LookupGroupId(group)
41+
if err != nil {
42+
return fmt.Errorf("failed to lookup group by id %q: %v", user, err)
43+
}
44+
} else {
45+
g, err = osuser.LookupGroup(group)
46+
if err != nil {
47+
return fmt.Errorf("failed to lookup group by name %q: %v", user, err)
48+
}
49+
}
50+
}
51+
52+
if g != nil {
53+
gid, _ := strconv.ParseUint(g.Gid, 10, 32)
54+
var err error
55+
if gid < math.MaxInt {
56+
err = syscall.Setgid(int(gid))
57+
} else {
58+
err = errors.New("gid too big")
59+
}
60+
61+
if err != nil {
62+
return fmt.Errorf("failed to setgid %d: %v", gid, err)
63+
}
64+
} else if u != nil {
65+
gid, _ := strconv.ParseUint(u.Gid, 10, 32)
66+
err := syscall.Setgid(int(uint32(gid)))
67+
if err != nil {
68+
return fmt.Errorf("failed to setgid %d: %v", gid, err)
69+
}
70+
}
71+
72+
if u != nil {
73+
uid, _ := strconv.ParseUint(u.Uid, 10, 32)
74+
var err error
75+
if uid < math.MaxInt {
76+
err = syscall.Setuid(int(uid))
77+
} else {
78+
err = errors.New("uid too big")
79+
}
80+
81+
if err != nil {
82+
return fmt.Errorf("failed to setuid %d: %v", uid, err)
83+
}
84+
}
85+
86+
return nil
87+
}

cmd/yggdrasil/main.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ func main() {
5252
getsnet := flag.Bool("subnet", false, "use in combination with either -useconf or -useconffile, outputs your IPv6 subnet")
5353
getpkey := flag.Bool("publickey", false, "use in combination with either -useconf or -useconffile, outputs your public key")
5454
loglevel := flag.String("loglevel", "info", "loglevel to enable")
55+
chuserto := flag.String("user", "", "user (and, optionally, group) to set UID/GID to")
5556
flag.Parse()
5657

5758
done := make(chan struct{})
@@ -280,6 +281,14 @@ func main() {
280281
<-done
281282
})
282283

284+
// Change user if requested
285+
if *chuserto != "" {
286+
err = chuser(*chuserto)
287+
if err != nil {
288+
panic(err)
289+
}
290+
}
291+
283292
// Block until we are told to shut down.
284293
<-ctx.Done()
285294

0 commit comments

Comments
 (0)