Skip to content

Commit

Permalink
Fall back to "/" when home directory doesn't exist for tsh ssh (#9413)
Browse files Browse the repository at this point in the history
This change drops ssh users into the root directory when their home directory doesn't exist. This is the same behavior as OpenSSH.
  • Loading branch information
atburke committed Jan 5, 2022
1 parent aee8af2 commit a96401b
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 12 deletions.
15 changes: 12 additions & 3 deletions lib/srv/exec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ func (s *ExecSuite) TestOSCommandPrep(c *check.C) {
// Empty command (simple shell).
execCmd, err := s.ctx.ExecCommand()
c.Assert(err, check.IsNil)
cmd, err := buildCommand(execCmd, nil, nil, nil)
cmd, err := buildCommand(execCmd, s.usr, nil, nil, nil)
c.Assert(err, check.IsNil)
c.Assert(cmd, check.NotNil)
c.Assert(cmd.Path, check.Equals, "/bin/sh")
Expand All @@ -191,7 +191,7 @@ func (s *ExecSuite) TestOSCommandPrep(c *check.C) {
s.ctx.ExecRequest.SetCommand("ls -lh /etc")
execCmd, err = s.ctx.ExecCommand()
c.Assert(err, check.IsNil)
cmd, err = buildCommand(execCmd, nil, nil, nil)
cmd, err = buildCommand(execCmd, s.usr, nil, nil, nil)
c.Assert(err, check.IsNil)
c.Assert(cmd, check.NotNil)
c.Assert(cmd.Path, check.Equals, "/bin/sh")
Expand All @@ -204,11 +204,20 @@ func (s *ExecSuite) TestOSCommandPrep(c *check.C) {
s.ctx.ExecRequest.SetCommand("top")
execCmd, err = s.ctx.ExecCommand()
c.Assert(err, check.IsNil)
cmd, err = buildCommand(execCmd, nil, nil, nil)
cmd, err = buildCommand(execCmd, s.usr, nil, nil, nil)
c.Assert(err, check.IsNil)
c.Assert(cmd.Path, check.Equals, "/bin/sh")
c.Assert(cmd.Args, check.DeepEquals, []string{"/bin/sh", "-c", "top"})
c.Assert(cmd.SysProcAttr.Pdeathsig, check.Equals, syscall.SIGKILL)

// Missing home directory
s.usr.HomeDir = "/wrong/place"
root := string(os.PathSeparator)
expectedEnv[2] = fmt.Sprintf("HOME=%s", root)
cmd, err = buildCommand(execCmd, s.usr, nil, nil, nil)
c.Assert(err, check.IsNil)
c.Assert(cmd.Dir, check.Equals, root)
c.Assert(cmd.Env, check.DeepEquals, expectedEnv)
}

func (s *ExecSuite) TestLoginDefsParser(c *check.C) {
Expand Down
26 changes: 17 additions & 9 deletions lib/srv/reexec.go
Original file line number Diff line number Diff line change
Expand Up @@ -215,8 +215,13 @@ func RunCommand() (io.Writer, int, error) {
pamEnvironment = pamContext.Environment()
}

localUser, err := user.Lookup(c.Login)
if err != nil {
return errorWriter, teleport.RemoteCommandFailure, trace.Wrap(err)
}

// Build the actual command that will launch the shell.
cmd, err := buildCommand(&c, tty, pty, pamEnvironment)
cmd, err := buildCommand(&c, localUser, tty, pty, pamEnvironment)
if err != nil {
return errorWriter, teleport.RemoteCommandFailure, trace.Wrap(err)
}
Expand Down Expand Up @@ -359,14 +364,10 @@ func RunAndExit(commandType string) {

// buildCommand constructs a command that will execute the users shell. This
// function is run by Teleport while it's re-executing.
func buildCommand(c *ExecCommand, tty *os.File, pty *os.File, pamEnvironment []string) (*exec.Cmd, error) {
func buildCommand(c *ExecCommand, localUser *user.User, tty *os.File, pty *os.File, pamEnvironment []string) (*exec.Cmd, error) {
var cmd exec.Cmd

// Lookup the UID and GID for the user.
localUser, err := user.Lookup(c.Login)
if err != nil {
return nil, trace.Wrap(err)
}
// Get UID and GID.
uid, err := strconv.Atoi(localUser.Uid)
if err != nil {
return nil, trace.Wrap(err)
Expand Down Expand Up @@ -423,11 +424,18 @@ func buildCommand(c *ExecCommand, tty *os.File, pty *os.File, pamEnvironment []s
cmd.Args = []string{shellPath, "-c", c.Command}
}

// Ensure that the user has a home directory.
// TODO: Generalize this to support Windows.
homeDir := string(os.PathSeparator)
if utils.IsDir(localUser.HomeDir) {
homeDir = localUser.HomeDir
}

// Create default environment for user.
cmd.Env = []string{
"LANG=en_US.UTF-8",
getDefaultEnvPath(localUser.Uid, defaultLoginDefsPath),
"HOME=" + localUser.HomeDir,
"HOME=" + homeDir,
"USER=" + c.Login,
"SHELL=" + shellPath,
}
Expand All @@ -450,7 +458,7 @@ func buildCommand(c *ExecCommand, tty *os.File, pty *os.File, pamEnvironment []s
cmd.Env = append(cmd.Env, pamEnvironment...)

// Set the home directory for the user.
cmd.Dir = localUser.HomeDir
cmd.Dir = homeDir

// If a terminal was requested, connect std{in,out,err} to the TTY and set
// the controlling TTY. Otherwise, connect std{in,out,err} to
Expand Down

0 comments on commit a96401b

Please sign in to comment.