From 097a640e79c08e51173e2dd28d73df2fc2c14269 Mon Sep 17 00:00:00 2001 From: Wataru Ashihara Date: Wed, 17 Oct 2018 23:39:14 +0900 Subject: [PATCH] [easyssh] fix: panic when using ssh-agent (appleboy/easyssh-proxy#42) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before changes: ```sh $ # This is what `keychain --eval --inherit any` does on Ubuntu. $ # https://www.funtoo.org/Keychain $ export SSH_AUTH_SOCK=/run/user/1000/keyring/ssh $ go build example/ssh/ssh.go $ ./ssh panic: Can't run remote command: ssh: handshake failed: agent: client error: write unix @->/run/user/1000/keyring/ssh: use of closed network connection goroutine 1 [running]: main.main() /home/wsh/go/src/github.com/wataash/easyssh-proxy/example/ssh/ssh.go:32 +0x2d3 ``` Error message `write unix @->/run/user/1000/keyring/ssh: use of closed network connection` comes from [`Write()`](https://github.com/golang/crypto/blob/2b6c08872f4/ssh/agent/client.go#L277) where `SSH_AUTH_SOCK` is already `Close()`ed. After changes: ```sh $ export SSH_AUTH_SOCK=/run/user/1000/keyring/ssh $ go build example/ssh/ssh.go $ ./ssh github.com/wataash/easyssh-proxy command-line-arguments don is : true stdout is : total 640 drwxr-xr-x 68 wsh wsh 4096 10月 16 21:25 . drwxr-xr-x 3 root root 4096 9月 12 08:39 .. drwxr-xr-x 2 wsh wsh 4096 9月 20 20:48 .android ... -rw-rw-r-- 1 wsh wsh 202 9月 12 19:51 .zshrc ; stderr is : Identity added: /home/wsh/.ssh/id_rsa (/home/wsh/.ssh/id_rsa) Identity added: /home/wsh/.ssh/id_ed25519 (wsh@wsh9b) ``` https://github.com/appleboy/drone-ssh/commit/9b697286281 --- .../appleboy/easyssh-proxy/easyssh.go | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/vendor/github.com/appleboy/easyssh-proxy/easyssh.go b/vendor/github.com/appleboy/easyssh-proxy/easyssh.go index 80be120..de50948 100644 --- a/vendor/github.com/appleboy/easyssh-proxy/easyssh.go +++ b/vendor/github.com/appleboy/easyssh-proxy/easyssh.go @@ -67,7 +67,12 @@ func getKeyFile(keypath string) (ssh.Signer, error) { return pubkey, nil } -func getSSHConfig(config DefaultConfig) *ssh.ClientConfig { +// returns *ssh.ClientConfig and io.Closer. +// if io.Closer is not nil, io.Closer.Close() should be called when +// *ssh.ClientConfig is no longer used. +func getSSHConfig(config DefaultConfig) (*ssh.ClientConfig, io.Closer) { + var sshAgent io.Closer + // auths holds the detected ssh auth methods auths := []ssh.AuthMethod{} @@ -93,7 +98,6 @@ func getSSHConfig(config DefaultConfig) *ssh.ClientConfig { if sshAgent, err := net.Dial("unix", os.Getenv("SSH_AUTH_SOCK")); err == nil { auths = append(auths, ssh.PublicKeysCallback(agent.NewClient(sshAgent).Signers)) - defer sshAgent.Close() } return &ssh.ClientConfig{ @@ -101,7 +105,7 @@ func getSSHConfig(config DefaultConfig) *ssh.ClientConfig { User: config.User, Auth: auths, HostKeyCallback: ssh.InsecureIgnoreHostKey(), - } + }, sshAgent } // Connect to remote server using MakeConfig struct and returns *ssh.Session @@ -109,23 +113,29 @@ func (ssh_conf *MakeConfig) Connect() (*ssh.Session, error) { var client *ssh.Client var err error - targetConfig := getSSHConfig(DefaultConfig{ + targetConfig, closer := getSSHConfig(DefaultConfig{ User: ssh_conf.User, Key: ssh_conf.Key, KeyPath: ssh_conf.KeyPath, Password: ssh_conf.Password, Timeout: ssh_conf.Timeout, }) + if closer != nil { + defer closer.Close() + } // Enable proxy command if ssh_conf.Proxy.Server != "" { - proxyConfig := getSSHConfig(DefaultConfig{ + proxyConfig, closer := getSSHConfig(DefaultConfig{ User: ssh_conf.Proxy.User, Key: ssh_conf.Proxy.Key, KeyPath: ssh_conf.Proxy.KeyPath, Password: ssh_conf.Proxy.Password, Timeout: ssh_conf.Proxy.Timeout, }) + if closer != nil { + defer closer.Close() + } proxyClient, err := ssh.Dial("tcp", net.JoinHostPort(ssh_conf.Proxy.Server, ssh_conf.Proxy.Port), proxyConfig) if err != nil {