ssh/tailssh: set groups and gid in the incubated process

Updates #3802

Signed-off-by: Maisem Ali <maisem@tailscale.com>
This commit is contained in:
Maisem Ali 2022-04-21 14:44:39 -07:00 committed by Maisem Ali
parent 8ac4d52b59
commit 337c77964b
2 changed files with 32 additions and 4 deletions

View File

@ -24,6 +24,7 @@
"os/user" "os/user"
"path/filepath" "path/filepath"
"runtime" "runtime"
"strconv"
"strings" "strings"
"syscall" "syscall"
@ -93,6 +94,8 @@ func (ss *sshSession) newIncubatorCommand() *exec.Cmd {
"be-child", "be-child",
"ssh", "ssh",
"--uid=" + lu.Uid, "--uid=" + lu.Uid,
"--gid=" + lu.Gid,
"--groups=" + strings.Join(ss.conn.userGroupIDs, ","),
"--local-user=" + lu.Username, "--local-user=" + lu.Username,
"--remote-user=" + remoteUser, "--remote-user=" + remoteUser,
"--remote-ip=" + ci.src.IP().String(), "--remote-ip=" + ci.src.IP().String(),
@ -141,6 +144,8 @@ func beIncubator(args []string) error {
var ( var (
flags = flag.NewFlagSet("", flag.ExitOnError) flags = flag.NewFlagSet("", flag.ExitOnError)
uid = flags.Uint64("uid", 0, "the uid of local-user") uid = flags.Uint64("uid", 0, "the uid of local-user")
gid = flags.Int("gid", 0, "the gid of local-user")
groups = flags.String("groups", "", "comma-separated list of gids of local-user")
localUser = flags.String("local-user", "", "the user to run as") localUser = flags.String("local-user", "", "the user to run as")
remoteUser = flags.String("remote-user", "", "the remote user/tags") remoteUser = flags.String("remote-user", "", "the remote user/tags")
remoteIP = flags.String("remote-ip", "", "the remote Tailscale IP") remoteIP = flags.String("remote-ip", "", "the remote Tailscale IP")
@ -171,6 +176,23 @@ func beIncubator(args []string) error {
if err == nil && sessionCloser != nil { if err == nil && sessionCloser != nil {
defer sessionCloser() defer sessionCloser()
} }
var groupIDs []int
for _, g := range strings.Split(*groups, ",") {
gid, err := strconv.ParseInt(g, 10, 32)
if err != nil {
return err
}
groupIDs = append(groupIDs, int(gid))
}
if err := syscall.Setgroups(groupIDs); err != nil {
return err
}
if egid := os.Getegid(); egid != *gid {
if err := syscall.Setgid(int(*gid)); err != nil {
logf(err.Error())
os.Exit(1)
}
}
if euid != *uid { if euid != *uid {
// Switch users if required before starting the desired process. // Switch users if required before starting the desired process.
if err := syscall.Setuid(int(*uid)); err != nil { if err := syscall.Setuid(int(*uid)); err != nil {

View File

@ -118,10 +118,11 @@ type conn struct {
// purposes of rule evaluation. // purposes of rule evaluation.
now time.Time now time.Time
action0 *tailcfg.SSHAction // first matching action action0 *tailcfg.SSHAction // first matching action
srv *server srv *server
info *sshConnInfo // set by setInfo info *sshConnInfo // set by setInfo
localUser *user.User // set by checkAuth localUser *user.User // set by checkAuth
userGroupIDs []string // set by checkAuth
insecureSkipTailscaleAuth bool // used by tests. insecureSkipTailscaleAuth bool // used by tests.
} }
@ -191,6 +192,11 @@ func (c *conn) checkAuth(pubKey ssh.PublicKey) error {
Message: fmt.Sprintf("failed to lookup %v\r\n", localUser), Message: fmt.Sprintf("failed to lookup %v\r\n", localUser),
} }
} }
gids, err := lu.GroupIds()
if err != nil {
return err
}
c.userGroupIDs = gids
c.localUser = lu c.localUser = lu
return nil return nil
} }