You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
obfssh/console_unix.go

139 lines
3.1 KiB
Go

// +build darwin freebsd linux openbsd solaris
package obfssh
import (
"fmt"
"os"
"os/exec"
"os/signal"
"os/user"
"strconv"
"strings"
"syscall"
"github.com/containerd/console"
"github.com/fangdingjun/go-log/v5"
"golang.org/x/crypto/ssh"
"golang.org/x/sys/unix"
)
func consoleChange(_console console.Console, session *ssh.Session) {
ch := make(chan os.Signal, 2)
signal.Notify(ch, syscall.SIGWINCH)
go func() {
for {
select {
case <-ch:
ws, _ := _console.Size()
_winCh := windowChange{Rows: uint32(ws.Height), Columns: uint32(ws.Width)}
d := ssh.Marshal(_winCh)
ok, err := session.SendRequest("window-change", true, d)
log.Debugf("send window change request %+v %+v", ok, err)
}
}
}()
}
func newPty() (console.Console, string, error) {
return console.NewPty()
}
func setProcAttr(attr *syscall.SysProcAttr) {
attr.Setsid = 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
}
func setUserEnv(_cmd *exec.Cmd, u *user.User, attr *syscall.SysProcAttr) {
if u == nil {
return
}
_uid, _ := strconv.ParseUint(u.Uid, 10, 32)
_gid, _ := strconv.ParseUint(u.Gid, 10, 32)
_cmd.Env = append(_cmd.Env, fmt.Sprintf("HOME=%s", u.HomeDir))
_cmd.Env = append(_cmd.Env, fmt.Sprintf("LOGNAME=%s", u.Name))
_cmd.Dir = u.HomeDir
if os.Getuid() != 0 {
return
}
if attr.Credential == nil {
attr.Credential = &syscall.Credential{}
}
attr.Credential.Uid = uint32(_uid)
attr.Credential.Gid = uint32(_gid)
for _, _env := range _cmd.Env {
ss := strings.Split(_env, "=")
if ss[0] == "SSH_AUTH_SOCK" {
os.Chown(ss[1], int(_uid), int(_gid))
}
if ss[0] == "SSH_TTY" {
os.Chown(ss[1], int(_uid), 0)
}
}
}