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
…) (#9661)

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 authored Jan 7, 2022
1 parent 3509bfe commit 3115350
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 @@ -177,7 +177,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 @@ -190,7 +190,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 @@ -203,11 +203,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 3115350

Please sign in to comment.