apply termios settings

ws
dingjun 4 years ago
parent d8a19c9c82
commit f909c4be98

@ -20,3 +20,7 @@ func newPty() (console.Console, string, error) {
func setProcAttr(attr *syscall.SysProcAttr) { func setProcAttr(attr *syscall.SysProcAttr) {
} }
func setTermios(fd int, args ssh.TerminalModes) error {
return errors.New("not supported")
}

@ -10,6 +10,7 @@ import (
"github.com/containerd/console" "github.com/containerd/console"
"github.com/fangdingjun/go-log/v5" "github.com/fangdingjun/go-log/v5"
"golang.org/x/crypto/ssh" "golang.org/x/crypto/ssh"
"golang.org/x/sys/unix"
) )
func consoleChange(_console console.Console, session *ssh.Session) { func consoleChange(_console console.Console, session *ssh.Session) {
@ -37,3 +38,63 @@ func setProcAttr(attr *syscall.SysProcAttr) {
attr.Setsid = true attr.Setsid = true
attr.Setctty = true attr.Setctty = true
} }
func setFlag(f *uint32, k uint8, v uint32) {
v1, ok := termiosMap[k]
if !ok {
return
}
if v != 0 {
*f |= v1
return
}
*f &^= v1
}
func applyTermios(flag *unix.Termios, t ssh.TerminalModes) {
for k, v := range t {
switch k {
case ssh.IGNPAR, ssh.PARMRK, ssh.INPCK, ssh.ISTRIP, ssh.INLCR, ssh.IGNCR, ssh.ICRNL, ssh.IUCLC, ssh.IXON, ssh.IXANY, ssh.IXOFF, ssh.IMAXBEL:
setFlag(&flag.Iflag, k, v)
case ssh.OPOST, ssh.OLCUC, ssh.ONLCR, ssh.OCRNL, ssh.ONOCR, ssh.ONLRET:
setFlag(&flag.Oflag, k, v)
case ssh.CS7, ssh.CS8, ssh.PARENB, ssh.PARODD:
setFlag(&flag.Cflag, k, v)
case ssh.ISIG, ssh.ICANON, ssh.XCASE, ssh.ECHO, ssh.ECHOE, ssh.ECHOK, ssh.ECHONL, ssh.ECHOCTL, ssh.ECHOKE, ssh.NOFLSH, ssh.TOSTOP, ssh.PENDIN, ssh.IEXTEN:
setFlag(&flag.Lflag, k, v)
case ssh.VEOF, ssh.VEOL, ssh.VEOL2, ssh.VDISCARD, ssh.VDSUSP, ssh.VERASE, ssh.VINTR, ssh.VKILL, ssh.VLNEXT, ssh.VQUIT, ssh.VREPRINT, ssh.VSTART, ssh.VSTATUS, ssh.VSTOP, ssh.VSUSP, ssh.VSWTCH, ssh.VWERASE:
v1, ok := termiosMap[k]
if ok {
flag.Cc[v1] = uint8(v)
}
case ssh.TTY_OP_ISPEED:
flag.Ispeed = v
case ssh.TTY_OP_OSPEED:
flag.Ospeed = v
}
}
}
func setTermios(fd int, args ssh.TerminalModes) error {
t1, err := unix.IoctlGetTermios(fd, unix.TCGETS)
if err != nil {
return err
}
log.Debugf("before %+v", t1)
applyTermios(t1, args)
err = unix.IoctlSetTermios(fd, unix.TCSETS, t1)
if err != nil {
return err
}
t1, err = unix.IoctlGetTermios(fd, unix.TCGETS)
if err != nil {
return err
}
log.Debugf("after %+v", t1)
return nil
}

@ -12,4 +12,5 @@ require (
github.com/kr/fs v0.1.0 github.com/kr/fs v0.1.0
github.com/pkg/sftp v1.11.0 github.com/pkg/sftp v1.11.0
golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899 golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e
) )

@ -1,6 +1,7 @@
package obfssh package obfssh
import ( import (
"encoding/binary"
"fmt" "fmt"
"io" "io"
"net" "net"
@ -164,6 +165,22 @@ type windowChange struct {
Height uint32 Height uint32
} }
func parseTerminalModes(s string) ssh.TerminalModes {
// log.Debugf("%x", s)
s1 := []byte(s)
t := ssh.TerminalModes{}
for i := 0; i < len(s1); i += 5 {
k := uint8(s1[i])
if k == 0 {
break
}
v := binary.BigEndian.Uint32(s1[i+1 : i+5])
t[k] = v
// log.Debugf("k %d, v %d", k, v)
}
return t
}
func (sc *Server) handleSession(newch ssh.NewChannel) { func (sc *Server) handleSession(newch ssh.NewChannel) {
ch, req, err := newch.Accept() ch, req, err := newch.Accept()
if err != nil { if err != nil {
@ -232,11 +249,17 @@ func (sc *Server) handleSession(newch ssh.NewChannel) {
log.Errorln(err) log.Errorln(err)
ret = false ret = false
} }
log.Debugf("pty req %+v", _ptyReq) log.Debugf("pty req Rows: %d, Columns: %d, Mode: %x", _ptyReq.Rows, _ptyReq.Columns, _ptyReq.Mode)
if err == nil && (runtime.GOOS == "unix" || runtime.GOOS == "linux") { if err == nil && (runtime.GOOS == "unix" || runtime.GOOS == "linux") {
termios := parseTerminalModes(_ptyReq.Mode)
log.Debugf("parsed terminal mode %+v", termios)
_console, ptsname, err = newPty() _console, ptsname, err = newPty()
if err == nil { if err == nil {
log.Debugf("allocate pty %s", ptsname) log.Debugf("allocate pty %s", ptsname)
log.Debugf("set termios")
if err1 := setTermios(int(_console.Fd()), termios); err1 != nil {
log.Errorln(err)
}
env = append(env, fmt.Sprintf("SSH_TTY=%s", ptsname)) env = append(env, fmt.Sprintf("SSH_TTY=%s", ptsname))
ws, err := _console.Size() ws, err := _console.Size()
if err != nil { if err != nil {

@ -0,0 +1,63 @@
package obfssh
import (
"golang.org/x/crypto/ssh"
)
var termiosMap = map[uint8]uint32{
ssh.VINTR: 0,
ssh.VQUIT: 1,
ssh.VERASE: 2,
ssh.VKILL: 3,
ssh.VEOF: 4,
ssh.VSTART: 8,
ssh.VSTOP: 9,
ssh.VSUSP: 10,
ssh.VEOL: 11,
ssh.VREPRINT: 12,
ssh.VDISCARD: 13,
ssh.VWERASE: 14,
ssh.VLNEXT: 15,
ssh.VEOL2: 16,
ssh.IGNPAR: 0000004,
ssh.PARMRK: 0000010,
ssh.INPCK: 0000020,
ssh.ISTRIP: 0000040,
ssh.INLCR: 0000100,
ssh.IGNCR: 0000200,
ssh.ICRNL: 0000400,
ssh.IUCLC: 0001000,
ssh.IXON: 0002000,
ssh.IXANY: 0004000,
ssh.IXOFF: 0010000,
ssh.IMAXBEL: 0020000,
ssh.OPOST: 0000001,
ssh.PARENB: 0000400,
ssh.OLCUC: 0000002,
ssh.ONLCR: 0000004,
ssh.OCRNL: 0000010,
ssh.ONOCR: 0000020,
ssh.ONLRET: 0000040,
ssh.CS7: 0000040,
ssh.CS8: 0000060,
ssh.PARODD: 0001000,
ssh.ISIG: 0000001,
ssh.ICANON: 0000002,
ssh.XCASE: 0000004,
ssh.ECHO: 0000010,
ssh.ECHOE: 0000020,
ssh.ECHOK: 0000040,
ssh.ECHONL: 0000100,
ssh.NOFLSH: 0000200,
ssh.TOSTOP: 0000400,
ssh.ECHOCTL: 0001000,
ssh.ECHOKE: 0004000,
ssh.PENDIN: 0040000,
ssh.IEXTEN: 0100000,
/*
ssh.VFLUSH: 0,
ssh.VSWTCH: 0,
ssh.VSTATUS: 0,
ssh.VDSUSP: 0,
*/
}
Loading…
Cancel
Save