1
0
forked from x/icebergs
This commit is contained in:
harveyshao 2022-08-16 17:39:12 +08:00
parent bf34e9ceee
commit 325d28f090
9 changed files with 98 additions and 138 deletions

View File

@ -21,7 +21,7 @@ func _sess_check(m *ice.Message, sessid string) {
if m.Warn(kit.Time(kit.Format(value[mdb.TIME])) < kit.Time(m.Time()), ice.ErrNotValid, sessid) { if m.Warn(kit.Time(kit.Format(value[mdb.TIME])) < kit.Time(m.Time()), ice.ErrNotValid, sessid) {
return // 会话超时 return // 会话超时
} }
m.Logs(ice.LOG_AUTH, m.Auth(
USERROLE, m.Option(ice.MSG_USERROLE, value[USERROLE]), USERROLE, m.Option(ice.MSG_USERROLE, value[USERROLE]),
USERNAME, m.Option(ice.MSG_USERNAME, value[USERNAME]), USERNAME, m.Option(ice.MSG_USERNAME, value[USERNAME]),
USERNICK, m.Option(ice.MSG_USERNICK, value[USERNICK]), USERNICK, m.Option(ice.MSG_USERNICK, value[USERNICK]),

View File

@ -34,7 +34,7 @@ func _user_login(m *ice.Message, name, word string) {
if m.Warn(word != "" && word != kit.Format(kit.Value(value, kit.Keys(mdb.EXTRA, PASSWORD))), ice.ErrNotRight) { if m.Warn(word != "" && word != kit.Format(kit.Value(value, kit.Keys(mdb.EXTRA, PASSWORD))), ice.ErrNotRight) {
return return
} }
m.Logs(ice.LOG_AUTH, m.Auth(
USERROLE, m.Option(ice.MSG_USERROLE, value[USERROLE]), USERROLE, m.Option(ice.MSG_USERROLE, value[USERROLE]),
USERNAME, m.Option(ice.MSG_USERNAME, value[USERNAME]), USERNAME, m.Option(ice.MSG_USERNAME, value[USERNAME]),
USERNICK, m.Option(ice.MSG_USERNICK, value[USERNICK]), USERNICK, m.Option(ice.MSG_USERNICK, value[USERNICK]),

View File

@ -54,7 +54,7 @@ func _islocalhost(m *ice.Message, ip string) (ok bool) {
return false return false
} }
if mdb.Richs(m, HOST, kit.Keym(aaa.WHITE), ip, nil) != nil { if mdb.Richs(m, HOST, kit.Keym(aaa.WHITE), ip, nil) != nil {
m.Logs(ice.LOG_AUTH, aaa.WHITE, ip) m.Auth(aaa.WHITE, ip)
return true return true
} }
return false return false

View File

@ -102,7 +102,7 @@ func _space_handle(m *ice.Message, safe bool, frame *Frame, c *websocket.Conn, n
if msg.Option(ice.MSG_USERROLE) == aaa.VOID && ice.Info.UserName == aaa.TECH { if msg.Option(ice.MSG_USERROLE) == aaa.VOID && ice.Info.UserName == aaa.TECH {
msg.Option(ice.MSG_USERROLE, aaa.TECH) // 演示空间 msg.Option(ice.MSG_USERROLE, aaa.TECH) // 演示空间
} }
msg.Logs(ice.LOG_AUTH, aaa.USERROLE, msg.Option(ice.MSG_USERROLE), aaa.USERNAME, msg.Option(ice.MSG_USERNAME)) msg.Auth(aaa.USERROLE, msg.Option(ice.MSG_USERROLE), aaa.USERNAME, msg.Option(ice.MSG_USERNAME))
msg.Go(func() { _space_exec(msg, source, target, c, name) }) msg.Go(func() { _space_exec(msg, source, target, c, name) })
continue continue
} }

View File

@ -45,7 +45,7 @@ func _action_auth(m *ice.Message, share string) *ice.Message {
msg.Append(mdb.TYPE, "") msg.Append(mdb.TYPE, "")
return msg // 共享过期 return msg // 共享过期
} }
m.Logs(ice.LOG_AUTH, m.Auth(
aaa.USERROLE, m.Option(ice.MSG_USERROLE, msg.Append(aaa.USERROLE)), aaa.USERROLE, m.Option(ice.MSG_USERROLE, msg.Append(aaa.USERROLE)),
aaa.USERNAME, m.Option(ice.MSG_USERNAME, msg.Append(aaa.USERNAME)), aaa.USERNAME, m.Option(ice.MSG_USERNAME, msg.Append(aaa.USERNAME)),
aaa.USERNICK, m.Option(ice.MSG_USERNICK, msg.Append(aaa.USERNICK)), aaa.USERNICK, m.Option(ice.MSG_USERNICK, msg.Append(aaa.USERNICK)),

View File

@ -18,6 +18,10 @@ func (m *Message) join(arg ...Any) (string, []Any) {
meta = append(meta, v) meta = append(meta, v)
i-- i--
continue continue
case []string:
list = append(list, v...)
i--
continue
} }
if key := strings.TrimSpace(kit.Format(arg[i])); i == len(arg)-1 { if key := strings.TrimSpace(kit.Format(arg[i])); i == len(arg)-1 {
list = append(list, key) list = append(list, key)
@ -72,6 +76,10 @@ func (m *Message) Logs(level string, arg ...Any) *Message {
return m.log(level, str, meta...) return m.log(level, str, meta...)
} }
func (m *Message) Auth(arg ...Any) *Message {
str, meta := m.join(arg...)
return m.log(LOG_AUTH, str, meta...)
}
func (m *Message) Cost(arg ...Any) *Message { func (m *Message) Cost(arg ...Any) *Message {
str, meta := m.join(arg...) str, meta := m.join(arg...)
if len(arg) == 0 { if len(arg) == 0 {

View File

@ -2,13 +2,9 @@ package ssh
import ( import (
"io" "io"
"net"
"os/exec"
"strings" "strings"
"golang.org/x/crypto/ssh"
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/aaa"
"shylinux.com/x/icebergs/base/ctx" "shylinux.com/x/icebergs/base/ctx"
"shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/mdb"
psh "shylinux.com/x/icebergs/base/ssh" psh "shylinux.com/x/icebergs/base/ssh"
@ -16,27 +12,7 @@ import (
kit "shylinux.com/x/toolkits" kit "shylinux.com/x/toolkits"
) )
func _ssh_exec(m *ice.Message, cmd string, arg []string, env []string, input io.Reader, output io.Writer, done func()) { func _ssh_watch(m *ice.Message, h string, output io.Writer, input io.Reader) io.Closer {
m.Logs(mdb.IMPORT, CMD, cmd, ARG, arg, ENV, env)
c := exec.Command(cmd, arg...)
// c.Env = env
c.Stdin = input
c.Stdout = output
c.Stderr = output
m.Assert(c.Start())
m.Go(func() {
defer done()
c.Process.Wait()
})
}
func _ssh_close(m *ice.Message, c net.Conn, channel ssh.Channel) {
defer channel.Close()
channel.Write([]byte(m.Conf(SERVICE, kit.Keym(GOODBYE))))
}
func _ssh_watch(m *ice.Message, meta ice.Maps, h string, input io.Reader, output io.Writer) {
r, w := io.Pipe() r, w := io.Pipe()
bio := io.TeeReader(input, w) bio := io.TeeReader(input, w)
m.Go(func() { io.Copy(output, r) }) m.Go(func() { io.Copy(output, r) })
@ -52,8 +28,7 @@ func _ssh_watch(m *ice.Message, meta ice.Maps, h string, input io.Reader, output
switch buf[i] { switch buf[i] {
case '\r', '\n': case '\r', '\n':
cmd := strings.TrimSpace(string(buf[:i])) cmd := strings.TrimSpace(string(buf[:i]))
m.Logs(mdb.IMPORT, tcp.HOSTNAME, meta[tcp.HOSTNAME], aaa.USERNAME, meta[aaa.USERNAME], CMD, cmd) m.Cmdy(mdb.INSERT, m.Prefix(CHANNEL), kit.Keys(mdb.HASH, h), mdb.LIST, mdb.TYPE, CMD, mdb.TEXT, cmd)
m.Cmdy(mdb.INSERT, CHANNEL, kit.Keys(mdb.HASH, h), mdb.LIST, mdb.TYPE, CMD, mdb.TEXT, cmd)
i = 0 i = 0
default: default:
if i += n; i >= ice.MOD_BUFS { if i += n; i >= ice.MOD_BUFS {
@ -62,6 +37,7 @@ func _ssh_watch(m *ice.Message, meta ice.Maps, h string, input io.Reader, output
} }
} }
}) })
return r
} }
const CHANNEL = "channel" const CHANNEL = "channel"
@ -70,34 +46,24 @@ func init() {
psh.Index.MergeCommands(ice.Commands{ psh.Index.MergeCommands(ice.Commands{
CHANNEL: {Name: "channel hash id auto", Help: "通道", Actions: ice.MergeActions(ice.Actions{ CHANNEL: {Name: "channel hash id auto", Help: "通道", Actions: ice.MergeActions(ice.Actions{
ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) {
mdb.Richs(m, CHANNEL, "", mdb.FOREACH, func(key string, value ice.Map) { mdb.HashSelectUpdate(m, mdb.FOREACH, func(value ice.Map) {
kit.Value(value, kit.Keym(mdb.STATUS), tcp.CLOSE) kit.Value(value, mdb.STATUS, tcp.CLOSE)
}) })
}}, }},
mdb.PRUNES: {Name: "prunes", Help: "清理", Hand: func(m *ice.Message, arg ...string) {
m.OptionFields(m.Config(mdb.FIELD))
m.Cmdy(mdb.PRUNES, SERVICE, "", mdb.HASH, mdb.STATUS, tcp.ERROR)
m.Cmdy(mdb.PRUNES, CHANNEL, "", mdb.HASH, mdb.STATUS, tcp.CLOSE)
}},
mdb.REPEAT: {Name: "repeat", Help: "执行", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(CHANNEL, ctx.ACTION, ctx.COMMAND, CMD, m.Option(mdb.TEXT))
}},
ctx.COMMAND: {Name: "command cmd=pwd", Help: "命令", Hand: func(m *ice.Message, arg ...string) { ctx.COMMAND: {Name: "command cmd=pwd", Help: "命令", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(mdb.INSERT, CHANNEL, kit.Keys(mdb.HASH, m.Option(mdb.HASH)), mdb.ZoneInsert(m, m.OptionSimple(mdb.HASH), mdb.TYPE, CMD, mdb.TEXT, m.Option(CMD))
mdb.LIST, mdb.TYPE, CMD, mdb.TEXT, m.Option(CMD)) if w, ok := mdb.HashTarget(m, m.Option(mdb.HASH), nil).(io.Writer); ok {
mdb.Richs(m, CHANNEL, "", m.Option(mdb.HASH), func(key string, value ice.Map) { w.Write([]byte(m.Option(CMD) + ice.NL))
if w, ok := kit.Value(value, kit.Keym(INPUT)).(io.Writer); ok { m.Sleep300ms()
w.Write([]byte(m.Option(CMD) + ice.NL)) }
}
})
m.ProcessRefresh300ms()
}}, }},
}, mdb.HashAction(mdb.FIELD, "time,hash,status,username,hostport,tty,count")), Hand: func(m *ice.Message, arg ...string) { mdb.REPEAT: {Name: "repeat", Help: "执行", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy("", ctx.COMMAND, CMD, m.Option(mdb.TEXT))
}},
}, mdb.HashAction(mdb.FIELD, "time,hash,status,tty,count,username,hostport")), Hand: func(m *ice.Message, arg ...string) {
if len(arg) == 0 { // 通道列表 if len(arg) == 0 { // 通道列表
m.Action(mdb.PRUNES) m.Action(mdb.PRUNES)
mdb.HashSelect(m, arg...) mdb.HashSelect(m, arg...).Tables(func(value ice.Maps) {
m.Set(ice.MSG_APPEND, ctx.ACTION)
m.Tables(func(value ice.Maps) {
m.PushButton(kit.Select("", ctx.COMMAND, value[mdb.STATUS] == tcp.OPEN), mdb.REMOVE) m.PushButton(kit.Select("", ctx.COMMAND, value[mdb.STATUS] == tcp.OPEN), mdb.REMOVE)
}) })
return return

View File

@ -5,10 +5,13 @@ import (
"encoding/base64" "encoding/base64"
"errors" "errors"
"fmt" "fmt"
"io"
"net" "net"
"os"
"strings" "strings"
"golang.org/x/crypto/ssh" "golang.org/x/crypto/ssh"
pty "shylinux.com/x/creackpty"
ice "shylinux.com/x/icebergs" ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/aaa" "shylinux.com/x/icebergs/base/aaa"
"shylinux.com/x/icebergs/base/cli" "shylinux.com/x/icebergs/base/cli"
@ -27,20 +30,20 @@ func _ssh_config(m *ice.Message, h string) *ssh.ServerConfig {
config := &ssh.ServerConfig{ config := &ssh.ServerConfig{
PublicKeyCallback: func(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) { PublicKeyCallback: func(conn ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) {
meta, err := _ssh_meta(conn), errors.New(ice.ErrNotRight) meta, err := _ssh_meta(conn), errors.New(ice.ErrNotRight)
if tcp.IsLocalHost(m, strings.Split(conn.RemoteAddr().String(), ice.DF)[0]) { if tcp.IsLocalHost(m, strings.Split(meta[tcp.HOSTPORT], ice.DF)[0]) {
m.Logs(ice.LOG_AUTH, tcp.HOSTPORT, conn.RemoteAddr(), aaa.USERNAME, conn.User()) m.Auth(aaa.USERNAME, meta[aaa.USERNAME], tcp.HOSTPORT, meta[tcp.HOSTPORT])
err = nil // 本机用户 err = nil // 本机用户
} else { } else {
mdb.ZoneSelectCB(m, h, func(value ice.Maps) { mdb.ZoneSelectCB(m, h, func(value ice.Maps) {
if !strings.HasPrefix(value[mdb.NAME], conn.User()+"@") { if !strings.HasPrefix(value[mdb.NAME], meta[aaa.USERNAME]+"@") {
return return
} }
if s, e := base64.StdEncoding.DecodeString(value[mdb.TEXT]); !m.Warn(e) { if s, e := base64.StdEncoding.DecodeString(value[mdb.TEXT]); !m.Warn(e) {
if pub, e := ssh.ParsePublicKey([]byte(s)); !m.Warn(e) { if pub, e := ssh.ParsePublicKey([]byte(s)); !m.Warn(e) {
if bytes.Compare(pub.Marshal(), key.Marshal()) == 0 { if bytes.Compare(pub.Marshal(), key.Marshal()) == 0 {
m.Logs(ice.LOG_AUTH, tcp.HOSTPORT, conn.RemoteAddr(), aaa.USERNAME, conn.User(), tcp.HOSTNAME, value[mdb.NAME])
meta[tcp.HOSTNAME] = kit.Select("", kit.Split(value[mdb.NAME], "@"), 1) meta[tcp.HOSTNAME] = kit.Select("", kit.Split(value[mdb.NAME], "@"), 1)
m.Auth(aaa.USERNAME, meta[aaa.USERNAME], tcp.HOSTPORT, meta[tcp.HOSTPORT], tcp.HOSTNAME, meta[tcp.HOSTNAME])
err = nil // 认证成功 err = nil // 认证成功
} }
} }
@ -51,16 +54,12 @@ func _ssh_config(m *ice.Message, h string) *ssh.ServerConfig {
}, },
PasswordCallback: func(conn ssh.ConnMetadata, password []byte) (*ssh.Permissions, error) { PasswordCallback: func(conn ssh.ConnMetadata, password []byte) (*ssh.Permissions, error) {
meta, err := _ssh_meta(conn), errors.New(ice.ErrNotRight) meta, err := _ssh_meta(conn), errors.New(ice.ErrNotRight)
if aaa.UserLogin(m, conn.User(), string(password)) { if aaa.UserLogin(m, meta[aaa.USERNAME], string(password)) {
m.Logs(ice.LOG_AUTH, tcp.HOSTPORT, conn.RemoteAddr(), aaa.USERNAME, conn.User(), aaa.PASSWORD, strings.Repeat("*", len(string(password)))) m.Auth(aaa.USERNAME, meta[aaa.USERNAME], tcp.HOSTPORT, meta[tcp.HOSTPORT], aaa.PASSWORD, strings.Repeat("*", len(string(password))))
err = nil // 密码登录 err = nil // 密码登录
} }
return &ssh.Permissions{Extensions: meta}, err return &ssh.Permissions{Extensions: meta}, err
}, },
BannerCallback: func(conn ssh.ConnMetadata) string {
m.Logs(ice.LOG_AUTH, tcp.HOSTPORT, conn.RemoteAddr(), aaa.USERNAME, conn.User())
return m.Config(WELCOME)
},
} }
if key, err := ssh.ParsePrivateKey([]byte(m.Cmdx(nfs.CAT, kit.HomePath(m.Option(PRIVATE))))); m.Assert(err) { if key, err := ssh.ParsePrivateKey([]byte(m.Cmdx(nfs.CAT, kit.HomePath(m.Option(PRIVATE))))); m.Assert(err) {
@ -73,7 +72,6 @@ func _ssh_accept(m *ice.Message, h string, c net.Conn) {
if m.Warn(err) { if m.Warn(err) {
return return
} }
m.Go(func() { ssh.DiscardRequests(reqs) }) m.Go(func() { ssh.DiscardRequests(reqs) })
for ch := range chans { for ch := range chans {
@ -81,12 +79,67 @@ func _ssh_accept(m *ice.Message, h string, c net.Conn) {
if m.Warn(err) { if m.Warn(err) {
continue continue
} }
m.Go(func() {
func(channel ssh.Channel, requests <-chan *ssh.Request) { m.Logs(CHANNEL, tcp.HOSTPORT, c.RemoteAddr().String(), "->", c.LocalAddr().String())
m.Go(func() { _ssh_handle(m, conn.Permissions.Extensions, c, channel, requests) }) defer m.Logs("dischan", tcp.HOSTPORT, c.RemoteAddr().String(), "->", c.LocalAddr().String())
}(channel, requests) _ssh_prepare(m.Spawn(conn.Permissions.Extensions), channel, requests)
})
} }
} }
func _ssh_prepare(m *ice.Message, channel ssh.Channel, requests <-chan *ssh.Request) {
pty, tty, err := pty.Open()
if m.Warn(err) {
return
}
defer tty.Close()
list := []string{cli.PATH + "=" + kit.Env(cli.PATH)}
for request := range requests {
m.Logs(REQUEST, tcp.HOSTPORT, m.Option(tcp.HOSTPORT), mdb.TYPE, request.Type)
switch request.Type {
case "pty-req":
termLen := request.Payload[3]
termEnv := string(request.Payload[4 : termLen+4])
_ssh_size(pty.Fd(), request.Payload[termLen+4:])
list = append(list, "TERM="+termEnv)
case "window-change":
_ssh_size(pty.Fd(), request.Payload)
case "env":
var env struct{ Name, Value string }
if err := ssh.Unmarshal(request.Payload, &env); err != nil {
continue
}
list = append(list, env.Name+"="+env.Value)
case "shell":
_ssh_handle(m, channel, pty, tty)
case "exec":
defer channel.Close()
m.Optionv(cli.CMD_OUTPUT, channel)
m.Cmd(cli.SYSTEM, kit.Select("sh", kit.Env(cli.SHELL)), "-c", string(request.Payload[4:request.Payload[3]+4]))
return
}
request.Reply(true, nil)
}
}
func _ssh_handle(m *ice.Message, channel ssh.Channel, pty, tty *os.File) {
h := m.Cmdx(mdb.INSERT, m.Prefix(CHANNEL), "", mdb.HASH, mdb.STATUS, tcp.OPEN, TTY, tty.Name(), m.OptionSimple(aaa.USERNAME, tcp.HOSTPORT), kit.Dict(mdb.TARGET, pty))
m.Go(func() { io.Copy(channel, pty) })
p := _ssh_watch(m, h, pty, channel)
m.Optionv(cli.CMD_INPUT, tty)
m.Optionv(cli.CMD_OUTPUT, tty)
channel.Write([]byte(m.Config(WELCOME)))
m.Cmd(cli.DAEMON, kit.Select("sh", kit.Env(cli.SHELL)), func() {
defer m.Cmd(mdb.MODIFY, m.Prefix(CHANNEL), "", mdb.HASH, mdb.HASH, h, mdb.STATUS, tcp.CLOSE)
channel.Write([]byte(m.Config(GOODBYE)))
channel.Close()
p.Close()
})
}
const ( const (
WELCOME = "welcome" WELCOME = "welcome"
@ -100,7 +153,7 @@ func init() {
psh.Index.Merge(&ice.Context{Configs: ice.Configs{ psh.Index.Merge(&ice.Context{Configs: ice.Configs{
SERVICE: {Name: SERVICE, Help: "服务", Value: kit.Data( SERVICE: {Name: SERVICE, Help: "服务", Value: kit.Data(
mdb.SHORT, tcp.PORT, mdb.FIELD, "time,port,status,private,authkey,count", mdb.SHORT, tcp.PORT, mdb.FIELD, "time,port,status,private,authkey,count",
WELCOME, "\r\nwelcome to contexts world\r\n", GOODBYE, "\r\ngoodbye of contexts world\r\n", WELCOME, "welcome to contexts world\r\n", GOODBYE, "goodbye of contexts world\r\n",
)}, )},
}, Commands: ice.Commands{ }, Commands: ice.Commands{
SERVICE: {Name: "service port id auto listen prunes", Help: "服务", Actions: ice.MergeActions(ice.Actions{ SERVICE: {Name: "service port id auto listen prunes", Help: "服务", Actions: ice.MergeActions(ice.Actions{
@ -128,7 +181,7 @@ func init() {
mdb.INSERT: {Name: "insert text:textarea", Help: "添加", Hand: func(m *ice.Message, arg ...string) { mdb.INSERT: {Name: "insert text:textarea", Help: "添加", Hand: func(m *ice.Message, arg ...string) {
if ls := kit.Split(m.Option(mdb.TEXT)); len(ls) > 2 { if ls := kit.Split(m.Option(mdb.TEXT)); len(ls) > 2 {
m.Cmdy(mdb.INSERT, SERVICE, kit.Keys(mdb.HASH, kit.Hashs(m.Option(tcp.PORT))), mdb.LIST, m.Cmdy(mdb.INSERT, m.Prefix(SERVICE), kit.Keys(mdb.HASH, kit.Hashs(m.Option(tcp.PORT))), mdb.LIST,
mdb.TYPE, ls[0], mdb.NAME, ls[len(ls)-1], mdb.TEXT, strings.Join(ls[1:len(ls)-1], "+")) mdb.TYPE, ls[0], mdb.NAME, ls[len(ls)-1], mdb.TEXT, strings.Join(ls[1:len(ls)-1], "+"))
} }
}}, }},

View File

@ -2,18 +2,8 @@ package ssh
import ( import (
"encoding/binary" "encoding/binary"
"io"
"net"
"syscall" "syscall"
"unsafe" "unsafe"
pty "shylinux.com/x/creackpty"
"golang.org/x/crypto/ssh"
ice "shylinux.com/x/icebergs"
"shylinux.com/x/icebergs/base/cli"
"shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/tcp"
kit "shylinux.com/x/toolkits"
) )
type Winsize struct{ Height, Width, x, y uint16 } type Winsize struct{ Height, Width, x, y uint16 }
@ -21,63 +11,6 @@ type Winsize struct{ Height, Width, x, y uint16 }
func _ssh_size(fd uintptr, b []byte) { func _ssh_size(fd uintptr, b []byte) {
w := binary.BigEndian.Uint32(b) w := binary.BigEndian.Uint32(b)
h := binary.BigEndian.Uint32(b[4:]) h := binary.BigEndian.Uint32(b[4:])
ws := &Winsize{Width: uint16(w), Height: uint16(h)} ws := &Winsize{Width: uint16(w), Height: uint16(h)}
syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(syscall.TIOCSWINSZ), uintptr(unsafe.Pointer(ws))) syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(syscall.TIOCSWINSZ), uintptr(unsafe.Pointer(ws)))
} }
func _ssh_sizes(fd uintptr, w, h int) {
ws := &Winsize{Width: uint16(w), Height: uint16(h)}
syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(syscall.TIOCSWINSZ), uintptr(unsafe.Pointer(ws)))
}
func _ssh_handle(m *ice.Message, meta ice.Maps, c net.Conn, channel ssh.Channel, requests <-chan *ssh.Request) {
m.Logs(CHANNEL, tcp.HOSTPORT, c.RemoteAddr(), "->", c.LocalAddr())
defer m.Logs("dischan", tcp.HOSTPORT, c.RemoteAddr(), "->", c.LocalAddr())
shell := kit.Select("bash", kit.Env("SHELL"))
list := []string{cli.PATH + "=" + kit.Env(cli.PATH)}
pty, tty, err := pty.Open()
if m.Warn(err) {
return
}
defer tty.Close()
h := mdb.Rich(m, CHANNEL, "", kit.Data(mdb.STATUS, tcp.OPEN, TTY, tty.Name(), INPUT, pty, OUTPUT, tty, meta))
meta[CHANNEL] = h
for request := range requests {
m.Logs(REQUEST, tcp.HOSTPORT, c.RemoteAddr(), mdb.TYPE, request.Type)
switch request.Type {
case "pty-req":
termLen := request.Payload[3]
termEnv := string(request.Payload[4 : termLen+4])
_ssh_size(pty.Fd(), request.Payload[termLen+4:])
list = append(list, "TERM="+termEnv)
case "window-change":
_ssh_size(pty.Fd(), request.Payload)
case "env":
var env struct{ Name, Value string }
if err := ssh.Unmarshal(request.Payload, &env); err != nil {
continue
}
list = append(list, env.Name+"="+env.Value)
case "exec":
_ssh_exec(m, shell, []string{"-c", string(request.Payload[4 : request.Payload[3]+4])}, list, channel, channel, func() {
channel.Close()
})
case "shell":
_ssh_watch(m, meta, h, channel, pty)
m.Go(func() { io.Copy(channel, pty) })
_ssh_exec(m, shell, nil, list, tty, tty, func() {
defer m.Cmd(mdb.MODIFY, CHANNEL, "", mdb.HASH, mdb.HASH, h, mdb.STATUS, tcp.CLOSE)
_ssh_close(m, c, channel)
})
}
request.Reply(true, nil)
}
}