|
|
|
// +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)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|