From 210847ee8cff61f0fdad34782d36bb2b0ca57e26 Mon Sep 17 00:00:00 2001 From: shaoying Date: Fri, 9 Oct 2020 17:26:46 +0800 Subject: [PATCH] opt ssh.connect.open --- base/aaa/totp.go | 2 ++ base/ssh/connect.go | 84 ++++++++++++++++++++++++++++++++++----------- base/ssh/scripts.go | 4 +-- base/web/serve.go | 3 +- init.go | 11 +++--- 5 files changed, 76 insertions(+), 28 deletions(-) diff --git a/base/aaa/totp.go b/base/aaa/totp.go index 61f7aaa9..57ee81f6 100644 --- a/base/aaa/totp.go +++ b/base/aaa/totp.go @@ -43,6 +43,8 @@ func _totp_get(key string, num int, per int64) string { return kit.Format(kit.Format("%%0%dd", num), res%int64(math.Pow10(num))) } +func TOTP_GET(key string, num int, per int64) string { return _totp_get(key, num, per) } + const ( SECRET = "secret" NUMBER = "number" diff --git a/base/ssh/connect.go b/base/ssh/connect.go index 14d1d5e0..31b45322 100644 --- a/base/ssh/connect.go +++ b/base/ssh/connect.go @@ -8,19 +8,41 @@ import ( "github.com/shylinux/icebergs/base/tcp" kit "github.com/shylinux/toolkits" + "golang.org/x/crypto/ssh" + "golang.org/x/crypto/ssh/terminal" + + "encoding/json" "net" "os" "path" - - "golang.org/x/crypto/ssh" + "strings" ) func _ssh_conn(m *ice.Message, conn net.Conn, username, hostport string) (*ssh.Client, error) { - key, e := ssh.ParsePrivateKey([]byte(m.Cmdx(nfs.CAT, path.Join(os.Getenv("HOME"), m.Option("private"))))) - m.Assert(e) - methods := []ssh.AuthMethod{} - methods = append(methods, ssh.PublicKeys(key)) + methods = append(methods, ssh.KeyboardInteractive(func(user, instruction string, questions []string, echos []bool) (res []string, err error) { + for _, k := range questions { + switch strings.TrimSpace(strings.ToLower(k)) { + case "verification code:": + res = append(res, aaa.TOTP_GET(m.Option("verify"), 6, 30)) + case "password:": + res = append(res, m.Option(aaa.PASSWORD)) + default: + } + } + m.Debug("question: %v res: %d", questions, len(res)) + return + })) + + methods = append(methods, ssh.PublicKeysCallback(func() ([]ssh.Signer, error) { + key, err := ssh.ParsePrivateKey([]byte(m.Cmdx(nfs.CAT, path.Join(os.Getenv("HOME"), m.Option("private"))))) + m.Debug("publickeys") + return []ssh.Signer{key}, err + })) + methods = append(methods, ssh.PasswordCallback(func() (string, error) { + m.Debug("password") + return m.Option(aaa.PASSWORD), nil + })) c, chans, reqs, err := ssh.NewClientConn(conn, hostport, &ssh.ClientConfig{ User: username, Auth: methods, HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error { @@ -29,10 +51,7 @@ func _ssh_conn(m *ice.Message, conn net.Conn, username, hostport string) (*ssh.C }, }) - if err != nil { - return nil, err - } - return ssh.NewClient(c, chans, reqs), nil + return ssh.NewClient(c, chans, reqs), err } const CONNECT = "connect" @@ -79,27 +98,52 @@ func init() { }) }}, - "open": {Name: "dial username=shy host=shylinux.com port=22 private=.ssh/id_rsa", Help: "添加", Hand: func(m *ice.Message, arg ...string) { + "open": {Name: "open authfile= username=shy password= verfiy= host=shylinux.com port=22 private=.ssh/id_rsa", Help: "终端", Hand: func(m *ice.Message, arg ...string) { + if f, e := os.Open(m.Option("authfile")); e == nil { + defer f.Close() + + var data interface{} + json.NewDecoder(f).Decode(&data) + + kit.Fetch(data, func(key string, value string) { m.Option(key, value) }) + } + m.Option(tcp.DIAL_CB, func(c net.Conn) { - client, e := _ssh_conn(m, c, kit.Select("shy", m.Option(aaa.USERNAME)), - kit.Select("shylinux.com", m.Option(tcp.HOST))+":"+kit.Select("22", m.Option(tcp.PORT)), - ) + client, e := _ssh_conn(m, c, m.Option(aaa.USERNAME), m.Option(tcp.HOST)+":"+m.Option(tcp.PORT)) m.Assert(e) - m.Debug("what") - m.Debug("some") session, e := client.NewSession() m.Assert(e) + fd := int(os.Stdin.Fd()) + oldState, err := terminal.MakeRaw(fd) + if err != nil { + panic(err) + } + defer terminal.Restore(fd, oldState) + + w, h, e := terminal.GetSize(fd) + m.Assert(e) + session.Stdin = os.Stdin session.Stdout = os.Stdout session.Stderr = os.Stderr - session.Start("/bin/bash") - m.Debug("what") - m.Debug("some") + + modes := ssh.TerminalModes{ + ssh.ECHO: 1, + ssh.TTY_OP_ISPEED: 14400, + ssh.TTY_OP_OSPEED: 14400, + } + + session.RequestPty(os.Getenv("TERM"), h, w, modes) + session.Shell() + session.Wait() }) - m.Cmd(tcp.CLIENT, tcp.DIAL, tcp.PORT, m.Option(tcp.PORT), tcp.HOST, m.Option(tcp.HOST), arg) + m.Cmdy(tcp.CLIENT, tcp.DIAL, kit.MDB_TYPE, "ssh", kit.MDB_NAME, m.Option(tcp.HOST), + tcp.PORT, m.Option(tcp.PORT), tcp.HOST, m.Option(tcp.HOST), arg) + + m.Echo("exit %s\n", m.Option(tcp.HOST)) }}, mdb.DELETE: {Name: "delete", Help: "删除", Hand: func(m *ice.Message, arg ...string) { m.Cmdy(mdb.DELETE, CONNECT, "", mdb.HASH, kit.MDB_HASH, m.Option(kit.MDB_HASH)) diff --git a/base/ssh/scripts.go b/base/ssh/scripts.go index 66766c27..a1c1326c 100644 --- a/base/ssh/scripts.go +++ b/base/ssh/scripts.go @@ -18,7 +18,7 @@ import ( ) func Render(msg *ice.Message, cmd string, args ...interface{}) { - defer func() { msg.Log_EXPORT(mdb.RENDER, cmd, kit.MDB_TEXT, args) }() + defer func() { msg.Log_EXPORT(mdb.RENDER, cmd, kit.Simple(args...)) }() switch arg := kit.Simple(args...); cmd { case ice.RENDER_VOID: @@ -191,8 +191,6 @@ func (f *Frame) parse(m *ice.Message, line string) string { } for _, one := range kit.Split(line, ";", ";", ";") { - m.Log_IMPORT("stdin", one, "length", len(one)) - async, one := false, strings.TrimSpace(one) if strings.TrimSuffix(one, "&") != one { async, one = true, strings.TrimSuffix(one, "&") diff --git a/base/web/serve.go b/base/web/serve.go index d6091203..724d977b 100644 --- a/base/web/serve.go +++ b/base/web/serve.go @@ -266,7 +266,8 @@ func init() { }, Commands: map[string]*ice.Command{ SERVE: {Name: "serve name auto start", Help: "服务器", Action: map[string]*ice.Action{ - gdb.START: {Name: "start name=self proto=http host= port=9020 dev=", Help: "启动", Hand: func(m *ice.Message, arg ...string) { + gdb.START: {Name: "start dev= name=self proto=http host= port=9020", Help: "启动", Hand: func(m *ice.Message, arg ...string) { + m.Debug("what %v %v", m.Option("name"), m.Option("dev")) if cli.NodeInfo(m, SERVER, ice.Info.HostName); m.Option(tcp.PORT) == "random" { m.Option(tcp.PORT, m.Cmdx(tcp.PORT, aaa.Right)) } diff --git a/init.go b/init.go index 9bc1d2c6..eecd886a 100644 --- a/init.go +++ b/init.go @@ -154,7 +154,6 @@ func Run(arg ...string) string { Pulse.root = Pulse Pulse.Option("cache.limit", "30") Pulse.Option("begin_time", Pulse.Time()) - _log_disable = true switch kit.Select("", arg, 0) { case "space", "serve": if _log_disable = false; frame.Begin(Pulse.Spawns(), arg...).Start(Pulse, arg...) { @@ -163,10 +162,14 @@ func Run(arg ...string) string { <-wait os.Exit(frame.code) + default: - if m := Pulse.Cmdy(arg); m.Result() == "" { - m.Table() - m.Sleep("100ms") + _log_disable = false + if Pulse.Cmdy(arg); Pulse.Result() == "" { + Pulse.Table() + } + if strings.TrimSpace(Pulse.Result()) == "" { + Pulse.Set(MSG_RESULT).Cmdy("cli.system", arg) } }