ssh/tailssh: exec into `login` when launching a shell

This has the added benefit of displaying the MOTD and reducing our
dependency on the DBus interface.

Fixes #4627
Updates #3802

Signed-off-by: Maisem Ali <maisem@tailscale.com>
pull/4651/head
Maisem Ali 3 years ago committed by Maisem Ali
parent a253057fc3
commit 5cd56fe8d5

@ -65,6 +65,7 @@ func (ss *sshSession) newIncubatorCommand() *exec.Cmd {
name string
args []string
isSFTP bool
isShell bool
)
switch ss.Subsystem() {
case "sftp":
@ -74,6 +75,7 @@ func (ss *sshSession) newIncubatorCommand() *exec.Cmd {
if rawCmd := ss.RawCommand(); rawCmd != "" {
args = append(args, "-c", rawCmd)
} else {
isShell = true
args = append(args, "-l") // login shell
}
default:
@ -107,6 +109,13 @@ func (ss *sshSession) newIncubatorCommand() *exec.Cmd {
if isSFTP {
incubatorArgs = append(incubatorArgs, "--sftp")
} else {
if isShell {
incubatorArgs = append(incubatorArgs, "--shell")
// Currently (2022-05-09) `login` is only used for shells
if lp, err := exec.LookPath("login"); err == nil {
incubatorArgs = append(incubatorArgs, "--login-cmd="+lp)
}
}
incubatorArgs = append(incubatorArgs, "--cmd="+name)
if len(args) > 0 {
incubatorArgs = append(incubatorArgs, "--")
@ -144,6 +153,7 @@ type incubatorArgs struct {
hasTTY bool
cmdName string
isSFTP bool
isShell bool
loginCmdPath string
cmdArgs []string
}
@ -159,7 +169,9 @@ func parseIncubatorArgs(args []string) (a incubatorArgs) {
flags.StringVar(&a.ttyName, "tty-name", "", "the tty name (pts/3)")
flags.BoolVar(&a.hasTTY, "has-tty", false, "is the output attached to a tty")
flags.StringVar(&a.cmdName, "cmd", "", "the cmd to launch (ignored in sftp mode)")
flags.BoolVar(&a.isShell, "shell", false, "is launching a shell (with no cmds)")
flags.BoolVar(&a.isSFTP, "sftp", false, "run sftp server (cmd is ignored)")
flags.StringVar(&a.loginCmdPath, "login-cmd", "", "the path to `login` cmd")
flags.Parse(args)
a.cmdArgs = flags.Args()
return a
@ -176,6 +188,9 @@ func parseIncubatorArgs(args []string) (a incubatorArgs) {
// `--groups` and then launches the requested `--cmd`.
func beIncubator(args []string) error {
ia := parseIncubatorArgs(args)
if ia.isSFTP && ia.isShell {
return fmt.Errorf("--sftp and --shell are mutually exclusive")
}
logf := logger.Discard
if debugIncubator {
@ -186,6 +201,11 @@ func beIncubator(args []string) error {
}
euid := uint64(os.Geteuid())
runningAsRoot := euid == 0
if runningAsRoot && ia.isShell && ia.loginCmdPath != "" {
// If we are trying to launch a login shell, just exec into login instead.
return unix.Exec(ia.loginCmdPath, []string{ia.loginCmdPath, "-f", ia.localUser, "-h", ia.remoteIP, "-p"}, os.Environ())
}
// Inform the system that we are about to log someone in.
// We can only do this if we are running as root.

Loading…
Cancel
Save