Skip to content

Commit ddca637

Browse files
committed
argument to change uid/gid
1 parent 41b4bf6 commit ddca637

File tree

3 files changed

+93
-0
lines changed

3 files changed

+93
-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: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
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+
"fmt"
8+
osuser "os/user"
9+
"strconv"
10+
"strings"
11+
"syscall"
12+
)
13+
14+
func chuser(user string) error {
15+
group := ""
16+
if i := strings.IndexByte(user, ':'); i >= 0 {
17+
user, group = user[:i], user[i+1:]
18+
}
19+
20+
u := (*osuser.User)(nil)
21+
g := (*osuser.Group)(nil)
22+
23+
if user != "" {
24+
if _, err := strconv.ParseUint(user, 10, 32); err == nil {
25+
u, err = osuser.LookupId(user)
26+
if err != nil {
27+
return fmt.Errorf("failed to lookup user by id %q: %v", user, err)
28+
}
29+
} else {
30+
u, err = osuser.Lookup(user)
31+
if err != nil {
32+
return fmt.Errorf("failed to lookup user by name %q: %v", user, err)
33+
}
34+
}
35+
}
36+
if group != "" {
37+
if _, err := strconv.ParseUint(group, 10, 32); err == nil {
38+
g, err = osuser.LookupGroupId(group)
39+
if err != nil {
40+
return fmt.Errorf("failed to lookup group by id %q: %v", user, err)
41+
}
42+
} else {
43+
g, err = osuser.LookupGroup(group)
44+
if err != nil {
45+
return fmt.Errorf("failed to lookup group by name %q: %v", user, err)
46+
}
47+
}
48+
}
49+
50+
if g != nil {
51+
gid, _ := strconv.ParseUint(g.Gid, 10, 32)
52+
err := syscall.Setgid(int(gid))
53+
if err != nil {
54+
return fmt.Errorf("failed to setgid %d: %v", gid, err)
55+
}
56+
} else if u != nil {
57+
gid, _ := strconv.ParseUint(u.Gid, 10, 32)
58+
err := syscall.Setgid(int(gid))
59+
if err != nil {
60+
return fmt.Errorf("failed to setgid %d: %v", gid, err)
61+
}
62+
}
63+
64+
if u != nil {
65+
uid, _ := strconv.ParseUint(u.Uid, 10, 32)
66+
err := syscall.Setuid(int(uid))
67+
if err != nil {
68+
return fmt.Errorf("failed to setuid %d: %v", uid, err)
69+
}
70+
}
71+
72+
return nil
73+
}

cmd/yggdrasil/main.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ type yggArgs struct {
194194
useconffile string
195195
logto string
196196
loglevel string
197+
chuser string
197198
}
198199

199200
func getArgs() yggArgs {
@@ -208,6 +209,7 @@ func getArgs() yggArgs {
208209
getaddr := flag.Bool("address", false, "returns the IPv6 address as derived from the supplied configuration")
209210
getsnet := flag.Bool("subnet", false, "returns the IPv6 subnet as derived from the supplied configuration")
210211
loglevel := flag.String("loglevel", "info", "loglevel to enable")
212+
chuser := flag.String("user", "", "user (and, optionally, group) to set UID/GID to")
211213
flag.Parse()
212214
return yggArgs{
213215
genconf: *genconf,
@@ -221,6 +223,7 @@ func getArgs() yggArgs {
221223
getaddr: *getaddr,
222224
getsnet: *getsnet,
223225
loglevel: *loglevel,
226+
chuser: *chuser,
224227
}
225228
}
226229

@@ -361,6 +364,13 @@ func run(args yggArgs, ctx context.Context, done chan struct{}) {
361364
logger.Errorln("An error occurred starting TUN/TAP:", err)
362365
}
363366
n.tuntap.SetupAdminHandlers(n.admin)
367+
// Change user if requested
368+
if args.chuser != "" {
369+
err = chuser(args.chuser)
370+
if err != nil {
371+
panic(err)
372+
}
373+
}
364374
// Make some nice output that tells us what our IPv6 address and subnet are.
365375
// This is just logged to stdout for the user.
366376
address := n.core.Address()

0 commit comments

Comments
 (0)