From 80985077f54601b12c189026034201a079b4f692 Mon Sep 17 00:00:00 2001 From: ljun20160606 Date: Tue, 24 Jul 2018 16:48:04 +0800 Subject: [PATCH] refactor: hide password when it's right #6 --- client.go | 123 +++++++++++++++++++++++++++++++++++++++++++++++ cmd/sshw/main.go | 117 ++------------------------------------------ config.go | 26 +++++++++- 3 files changed, 152 insertions(+), 114 deletions(-) create mode 100644 client.go diff --git a/client.go b/client.go new file mode 100644 index 0000000..c648688 --- /dev/null +++ b/client.go @@ -0,0 +1,123 @@ +package sshw + +import ( + "fmt" + "golang.org/x/crypto/ssh" + "golang.org/x/crypto/ssh/terminal" + "io/ioutil" + "os" + "os/user" + "path" + "time" +) + +type Client interface { + Login() +} + +type defaultClient struct { + clientConfig *ssh.ClientConfig + node *Node +} + +func NewClient(node *Node) Client { + u, err := user.Current() + if err != nil { + l.Error(err) + return nil + } + + var authMethods []ssh.AuthMethod + + var pemBytes []byte + if node.KeyPath == "" { + pemBytes, err = ioutil.ReadFile(path.Join(u.HomeDir, ".ssh/id_rsa")) + } else { + pemBytes, err = ioutil.ReadFile(node.KeyPath) + } + + if err == nil { + signer, err := ssh.ParsePrivateKey(pemBytes) + if err == nil { + authMethods = append(authMethods, ssh.PublicKeys(signer)) + } + } + + password := node.password() + + if password != nil { + authMethods = append(authMethods, password) + } + + config := &ssh.ClientConfig{ + User: node.user(), + Auth: authMethods, + HostKeyCallback: ssh.InsecureIgnoreHostKey(), + Timeout: time.Second * 10, + } + + config.SetDefaults() + config.Ciphers = append(config.Ciphers, "aes128-cbc", "3des-cbc", "blowfish-cbc", "cast128-cbc", "aes192-cbc", "aes256-cbc") + + return &defaultClient{ + clientConfig: config, + node: node, + } +} + +func (c *defaultClient) Login() { + host := c.node.Host + port := c.node.port() + client, err := ssh.Dial("tcp", fmt.Sprintf("%s:%d", host, port), c.clientConfig) + if err != nil { + l.Error(err) + return + } + defer client.Close() + + l.Infof("connect server ssh -p %d %s@%s version: %s\n", port, c.node.user(), host, string(client.ServerVersion())) + + session, err := client.NewSession() + if err != nil { + l.Error(err) + return + } + defer session.Close() + + fd := int(os.Stdin.Fd()) + state, err := terminal.MakeRaw(fd) + if err != nil { + l.Error(err) + return + } + defer terminal.Restore(fd, state) + + w, h, err := terminal.GetSize(fd) + if err != nil { + l.Error(err) + return + } + + modes := ssh.TerminalModes{ + ssh.ECHO: 1, + ssh.TTY_OP_ISPEED: 14400, + ssh.TTY_OP_OSPEED: 14400, + } + err = session.RequestPty("xterm", h, w, modes) + if err != nil { + l.Error(err) + return + } + + session.Stdout = os.Stdout + session.Stderr = os.Stderr + session.Stdin = os.Stdin + + err = session.Shell() + if err != nil { + l.Error(err) + return + } + + session.Wait() +} diff --git a/cmd/sshw/main.go b/cmd/sshw/main.go index 41747e2..46be43e 100644 --- a/cmd/sshw/main.go +++ b/cmd/sshw/main.go @@ -5,15 +5,9 @@ import ( "fmt" "github.com/manifoldco/promptui" "github.com/yinheli/sshw" - "golang.org/x/crypto/ssh" - "golang.org/x/crypto/ssh/terminal" - "io/ioutil" "os" - "os/user" - "path" "runtime" "strings" - "time" ) const prev = "-parent-" @@ -62,7 +56,8 @@ func main() { return } - login(node) + client := sshw.NewClient(node) + client.Login() } func choose(parent, trees []*sshw.Node) *sshw.Node { @@ -84,10 +79,9 @@ func choose(parent, trees []*sshw.Node) *sshw.Node { } } return true - } else { - if strings.Contains(content, input) { - return true - } + } + if strings.Contains(content, input) { + return true } return false }, @@ -113,104 +107,3 @@ func choose(parent, trees []*sshw.Node) *sshw.Node { return node } - -func login(node *sshw.Node) { - u, err := user.Current() - if err != nil { - log.Error(err) - return - } - - var authMethods []ssh.AuthMethod - - var b []byte - if node.KeyPath == "" { - b, err = ioutil.ReadFile(path.Join(u.HomeDir, ".ssh/id_rsa")) - } else { - b, err = ioutil.ReadFile(node.KeyPath) - } - if err == nil { - signer, err := ssh.ParsePrivateKey(b) - if err == nil { - authMethods = append(authMethods, ssh.PublicKeys(signer)) - } - } - - if node.Password != "" { - authMethods = append(authMethods, ssh.Password(node.Password)) - } - - username := node.User - host := node.Host - port := node.Port - - if username == "" { - username = "root" - } - if port <= 0 { - port = 22 - } - - config := &ssh.ClientConfig{ - User: username, - Auth: authMethods, - HostKeyCallback: ssh.InsecureIgnoreHostKey(), - Timeout: time.Second * 10, - } - - config.SetDefaults() - config.Ciphers = append(config.Ciphers, "aes128-cbc", "3des-cbc", "blowfish-cbc", "cast128-cbc", "aes192-cbc", "aes256-cbc") - - client, err := ssh.Dial("tcp", fmt.Sprintf("%s:%d", host, port), config) - if err != nil { - log.Error(err) - return - } - defer client.Close() - - log.Infof("connect server ssh -p %d %s@%s password:%s version: %s\n", port, username, host, node.Password, string(client.ServerVersion())) - - session, err := client.NewSession() - if err != nil { - log.Error(err) - return - } - defer session.Close() - - fd := int(os.Stdin.Fd()) - state, err := terminal.MakeRaw(fd) - if err != nil { - log.Error(err) - return - } - defer terminal.Restore(fd, state) - - w, h, err := terminal.GetSize(fd) - if err != nil { - log.Error(err) - return - } - - modes := ssh.TerminalModes{ - ssh.ECHO: 1, - ssh.TTY_OP_ISPEED: 14400, - ssh.TTY_OP_OSPEED: 14400, - } - err = session.RequestPty("xterm", h, w, modes) - if err != nil { - log.Error(err) - return - } - - session.Stdout = os.Stdout - session.Stderr = os.Stderr - session.Stdin = os.Stdin - - err = session.Shell() - if err != nil { - log.Error(err) - return - } - - session.Wait() -} diff --git a/config.go b/config.go index 71e92ca..066ff02 100644 --- a/config.go +++ b/config.go @@ -2,6 +2,7 @@ package sshw import ( "github.com/go-yaml/yaml" + "golang.org/x/crypto/ssh" "io/ioutil" "os/user" "path" @@ -17,8 +18,29 @@ type Node struct { Children []*Node `json:"children"` } -func (node *Node) String() string { - return node.Name +func (n *Node) String() string { + return n.Name +} + +func (n *Node) user() string { + if n.User == "" { + return "root" + } + return n.User +} + +func (n *Node) port() int { + if n.Port <= 0 { + return 22 + } + return n.Port +} + +func (n *Node) password() ssh.AuthMethod { + if n.Password == "" { + return nil + } + return ssh.Password(n.Password) } var (