ssh/tailssh: make pty termios options match OpenSSH
Still not sure the exact rules of how/when/who's supposed to set these, but this works for now on making them match. Baby steps. Will research more and adjust later. Updates #4146 (but not enough to fix it, something's still wrong) Updates #3802 Change-Id: I496d8cd7e31d45fe9ede88fc8894f35dc096de67 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:

committed by
Brad Fitzpatrick

parent
1dd5cf62a5
commit
ba1adf6c24
@ -28,6 +28,7 @@ import (
|
||||
|
||||
"github.com/creack/pty"
|
||||
"github.com/gliderlabs/ssh"
|
||||
"github.com/u-root/u-root/pkg/termios"
|
||||
"golang.org/x/sys/unix"
|
||||
"tailscale.com/cmd/tailscaled/childproc"
|
||||
"tailscale.com/types/logger"
|
||||
@ -209,12 +210,50 @@ func startWithPTY(cmd *exec.Cmd, ptyReq ssh.Pty) (ptyFile *os.File, err error) {
|
||||
tty.Close()
|
||||
}
|
||||
}()
|
||||
if err = pty.Setsize(ptyFile, &pty.Winsize{
|
||||
Rows: uint16(ptyReq.Window.Height),
|
||||
Cols: uint16(ptyReq.Window.Width),
|
||||
ptyRawConn, err := ptyFile.SyscallConn()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("SyscallConn: %w", err)
|
||||
}
|
||||
var ctlErr error
|
||||
if err := ptyRawConn.Control(func(fd uintptr) {
|
||||
// Load existing PTY settings to modify them & save them back.
|
||||
tios, err := termios.GTTY(int(fd))
|
||||
if err != nil {
|
||||
ctlErr = fmt.Errorf("GTTY: %w", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Set the rows & cols to those advertised from the ptyReq frame
|
||||
// received over SSH.
|
||||
tios.Row = int(ptyReq.Window.Height)
|
||||
tios.Col = int(ptyReq.Window.Width)
|
||||
|
||||
// And these are just stumbling around in the dark temporarily
|
||||
// while we try to match OpenSSH settings. Empirically this makes
|
||||
// stty -a output be the same, but we're still having problems:
|
||||
// https://github.com/tailscale/tailscale/issues/4146
|
||||
// TODO(bradfitz): figure all this out and do something more principled
|
||||
// and confident and documented, once we have a clue.
|
||||
tios.Ispeed = 9600
|
||||
tios.Ospeed = 9600
|
||||
tios.CC["eol"] = 255
|
||||
tios.CC["eol2"] = 255
|
||||
tios.Opts["echok"] = false
|
||||
tios.Opts["imaxbel"] = true
|
||||
tios.Opts["iutf8"] = true
|
||||
tios.Opts["ixany"] = true
|
||||
tios.Opts["pendin"] = true
|
||||
|
||||
// Save PTY settings.
|
||||
if _, err := tios.STTY(int(fd)); err != nil {
|
||||
ctlErr = fmt.Errorf("STTY: %w", err)
|
||||
return
|
||||
}
|
||||
}); err != nil {
|
||||
err = fmt.Errorf("pty.Setsize: %w", err)
|
||||
return
|
||||
return nil, fmt.Errorf("ptyRawConn.Control: %w", err)
|
||||
}
|
||||
if ctlErr != nil {
|
||||
return nil, fmt.Errorf("ptyRawConn.Control func: %w", ctlErr)
|
||||
}
|
||||
cmd.SysProcAttr = &syscall.SysProcAttr{
|
||||
Setctty: true,
|
||||
|
Reference in New Issue
Block a user