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 @@ import (
"os/user"
"path/filepath"
"runtime"
"strconv"
"strings"
"syscall"
@ -93,6 +94,8 @@ func (ss *sshSession) newIncubatorCommand() *exec.Cmd {
"be-child",
"ssh",
"--uid=" + lu.Uid,
"--gid=" + lu.Gid,
"--groups=" + strings.Join(ss.conn.userGroupIDs, ","),
"--local-user=" + lu.Username,
"--remote-user=" + remoteUser,
"--remote-ip=" + ci.src.IP().String(),
@ -141,6 +144,8 @@ func beIncubator(args []string) error {
var (
flags = flag.NewFlagSet("", flag.ExitOnError)
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")
remoteUser = flags.String("remote-user", "", "the remote user/tags")
remoteIP = flags.String("remote-ip", "", "the remote Tailscale IP")
@ -171,6 +176,23 @@ func beIncubator(args []string) error {
if err == nil && sessionCloser != nil {
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 {
// Switch users if required before starting the desired process.
if err := syscall.Setuid(int(*uid)); err != nil {

View File

@ -118,10 +118,11 @@ type conn struct {
// purposes of rule evaluation.
now time.Time
action0 *tailcfg.SSHAction // first matching action
srv *server
info *sshConnInfo // set by setInfo
localUser *user.User // set by checkAuth
action0 *tailcfg.SSHAction // first matching action
srv *server
info *sshConnInfo // set by setInfo
localUser *user.User // set by checkAuth
userGroupIDs []string // set by checkAuth
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),
}
}
gids, err := lu.GroupIds()
if err != nil {
return err
}
c.userGroupIDs = gids
c.localUser = lu
return nil
}