From f087ce16dc097170874cc0a43778c9eb2c330192 Mon Sep 17 00:00:00 2001 From: higebu Date: Thu, 10 Apr 2014 17:48:55 +0900 Subject: [PATCH] Fix the build problem by updating ssh package --- builder/amazon/common/ssh.go | 17 +++-- builder/digitalocean/ssh.go | 15 ++--- builder/googlecompute/ssh.go | 20 +++--- builder/openstack/ssh.go | 17 +++-- builder/qemu/builder.go | 2 +- builder/qemu/ssh.go | 20 +++--- builder/virtualbox/common/ssh.go | 22 +++--- builder/virtualbox/common/ssh_config.go | 2 +- builder/vmware/common/ssh.go | 20 +++--- builder/vmware/common/ssh_config.go | 2 +- builder/vmware/iso/driver_esx5.go | 8 +-- common/step_connect_ssh.go | 2 +- communicator/ssh/communicator.go | 17 +++-- communicator/ssh/communicator_test.go | 89 ++++++++++++------------- communicator/ssh/keychain.go | 81 ---------------------- communicator/ssh/keychain_test.go | 32 --------- communicator/ssh/password.go | 47 ++++++------- communicator/ssh/password_test.go | 26 +------- packer/rpc/client_test.go | 2 +- packer/rpc/muxconn_test.go | 2 +- 20 files changed, 150 insertions(+), 293 deletions(-) delete mode 100644 communicator/ssh/keychain.go delete mode 100644 communicator/ssh/keychain_test.go diff --git a/builder/amazon/common/ssh.go b/builder/amazon/common/ssh.go index 6756c62e7..88a3dafbd 100644 --- a/builder/amazon/common/ssh.go +++ b/builder/amazon/common/ssh.go @@ -1,12 +1,11 @@ package common import ( - gossh "code.google.com/p/go.crypto/ssh" + "code.google.com/p/go.crypto/ssh" "errors" "fmt" "github.com/mitchellh/goamz/ec2" "github.com/mitchellh/multistep" - "github.com/mitchellh/packer/communicator/ssh" "time" ) @@ -51,19 +50,19 @@ func SSHAddress(e *ec2.EC2, port int) func(multistep.StateBag) (string, error) { // SSHConfig returns a function that can be used for the SSH communicator // config for connecting to the instance created over SSH using the generated // private key. -func SSHConfig(username string) func(multistep.StateBag) (*gossh.ClientConfig, error) { - return func(state multistep.StateBag) (*gossh.ClientConfig, error) { +func SSHConfig(username string) func(multistep.StateBag) (*ssh.ClientConfig, error) { + return func(state multistep.StateBag) (*ssh.ClientConfig, error) { privateKey := state.Get("privateKey").(string) - keyring := new(ssh.SimpleKeychain) - if err := keyring.AddPEMKey(privateKey); err != nil { + signer, err := ssh.ParsePrivateKey([]byte(privateKey)) + if err != nil { return nil, fmt.Errorf("Error setting up SSH config: %s", err) } - return &gossh.ClientConfig{ + return &ssh.ClientConfig{ User: username, - Auth: []gossh.ClientAuth{ - gossh.ClientAuthKeyring(keyring), + Auth: []ssh.AuthMethod{ + ssh.PublicKeys(signer), }, }, nil } diff --git a/builder/digitalocean/ssh.go b/builder/digitalocean/ssh.go index 90de48400..2e9afcf7a 100644 --- a/builder/digitalocean/ssh.go +++ b/builder/digitalocean/ssh.go @@ -1,10 +1,9 @@ package digitalocean import ( - gossh "code.google.com/p/go.crypto/ssh" + "code.google.com/p/go.crypto/ssh" "fmt" "github.com/mitchellh/multistep" - "github.com/mitchellh/packer/communicator/ssh" ) func sshAddress(state multistep.StateBag) (string, error) { @@ -13,19 +12,19 @@ func sshAddress(state multistep.StateBag) (string, error) { return fmt.Sprintf("%s:%d", ipAddress, config.SSHPort), nil } -func sshConfig(state multistep.StateBag) (*gossh.ClientConfig, error) { +func sshConfig(state multistep.StateBag) (*ssh.ClientConfig, error) { config := state.Get("config").(config) privateKey := state.Get("privateKey").(string) - keyring := new(ssh.SimpleKeychain) - if err := keyring.AddPEMKey(privateKey); err != nil { + signer, err := ssh.ParsePrivateKey([]byte(privateKey)) + if err != nil { return nil, fmt.Errorf("Error setting up SSH config: %s", err) } - return &gossh.ClientConfig{ + return &ssh.ClientConfig{ User: config.SSHUsername, - Auth: []gossh.ClientAuth{ - gossh.ClientAuthKeyring(keyring), + Auth: []ssh.AuthMethod{ + ssh.PublicKeys(signer), }, }, nil } diff --git a/builder/googlecompute/ssh.go b/builder/googlecompute/ssh.go index 4254c916a..c921ecbfd 100644 --- a/builder/googlecompute/ssh.go +++ b/builder/googlecompute/ssh.go @@ -2,10 +2,8 @@ package googlecompute import ( "fmt" - - gossh "code.google.com/p/go.crypto/ssh" + "code.google.com/p/go.crypto/ssh" "github.com/mitchellh/multistep" - "github.com/mitchellh/packer/communicator/ssh" ) // sshAddress returns the ssh address. @@ -16,19 +14,19 @@ func sshAddress(state multistep.StateBag) (string, error) { } // sshConfig returns the ssh configuration. -func sshConfig(state multistep.StateBag) (*gossh.ClientConfig, error) { +func sshConfig(state multistep.StateBag) (*ssh.ClientConfig, error) { config := state.Get("config").(*Config) privateKey := state.Get("ssh_private_key").(string) - keyring := new(ssh.SimpleKeychain) - if err := keyring.AddPEMKey(privateKey); err != nil { + signer, err := ssh.ParsePrivateKey([]byte(privateKey)) + if err != nil { return nil, fmt.Errorf("Error setting up SSH config: %s", err) } - sshConfig := &gossh.ClientConfig{ + return &ssh.ClientConfig{ User: config.SSHUsername, - Auth: []gossh.ClientAuth{gossh.ClientAuthKeyring(keyring)}, - } - - return sshConfig, nil + Auth: []ssh.AuthMethod{ + ssh.PublicKeys(signer), + }, + }, nil } diff --git a/builder/openstack/ssh.go b/builder/openstack/ssh.go index 35876e342..a27a7f3c4 100644 --- a/builder/openstack/ssh.go +++ b/builder/openstack/ssh.go @@ -1,11 +1,10 @@ package openstack import ( - gossh "code.google.com/p/go.crypto/ssh" + "code.google.com/p/go.crypto/ssh" "errors" "fmt" "github.com/mitchellh/multistep" - "github.com/mitchellh/packer/communicator/ssh" "github.com/rackspace/gophercloud" "time" ) @@ -39,19 +38,19 @@ func SSHAddress(csp gophercloud.CloudServersProvider, port int) func(multistep.S // SSHConfig returns a function that can be used for the SSH communicator // config for connecting to the instance created over SSH using the generated // private key. -func SSHConfig(username string) func(multistep.StateBag) (*gossh.ClientConfig, error) { - return func(state multistep.StateBag) (*gossh.ClientConfig, error) { +func SSHConfig(username string) func(multistep.StateBag) (*ssh.ClientConfig, error) { + return func(state multistep.StateBag) (*ssh.ClientConfig, error) { privateKey := state.Get("privateKey").(string) - keyring := new(ssh.SimpleKeychain) - if err := keyring.AddPEMKey(privateKey); err != nil { + signer, err := ssh.ParsePrivateKey([]byte(privateKey)) + if err != nil { return nil, fmt.Errorf("Error setting up SSH config: %s", err) } - return &gossh.ClientConfig{ + return &ssh.ClientConfig{ User: username, - Auth: []gossh.ClientAuth{ - gossh.ClientAuthKeyring(keyring), + Auth: []ssh.AuthMethod{ + ssh.PublicKeys(signer), }, }, nil } diff --git a/builder/qemu/builder.go b/builder/qemu/builder.go index 9782c4a00..7f404a566 100644 --- a/builder/qemu/builder.go +++ b/builder/qemu/builder.go @@ -338,7 +338,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { if _, err := os.Stat(b.config.SSHKeyPath); err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("ssh_key_path is invalid: %s", err)) - } else if _, err := sshKeyToKeyring(b.config.SSHKeyPath); err != nil { + } else if _, err := sshKeyToSigner(b.config.SSHKeyPath); err != nil { errs = packer.MultiErrorAppend( errs, fmt.Errorf("ssh_key_path is invalid: %s", err)) } diff --git a/builder/qemu/ssh.go b/builder/qemu/ssh.go index 30eec134e..d22f611bc 100644 --- a/builder/qemu/ssh.go +++ b/builder/qemu/ssh.go @@ -17,19 +17,19 @@ func sshAddress(state multistep.StateBag) (string, error) { func sshConfig(state multistep.StateBag) (*gossh.ClientConfig, error) { config := state.Get("config").(*config) - auth := []gossh.ClientAuth{ - gossh.ClientAuthPassword(ssh.Password(config.SSHPassword)), - gossh.ClientAuthKeyboardInteractive( + auth := []gossh.AuthMethod{ + gossh.Password(config.SSHPassword), + gossh.KeyboardInteractive( ssh.PasswordKeyboardInteractive(config.SSHPassword)), } if config.SSHKeyPath != "" { - keyring, err := sshKeyToKeyring(config.SSHKeyPath) + signer, err := sshKeyToSigner(config.SSHKeyPath) if err != nil { return nil, err } - auth = append(auth, gossh.ClientAuthKeyring(keyring)) + auth = append(auth, gossh.PublicKeys(signer)) } return &gossh.ClientConfig{ @@ -38,7 +38,7 @@ func sshConfig(state multistep.StateBag) (*gossh.ClientConfig, error) { }, nil } -func sshKeyToKeyring(path string) (gossh.ClientKeyring, error) { +func sshKeyToSigner(path string) (gossh.Signer, error) { f, err := os.Open(path) if err != nil { return nil, err @@ -50,10 +50,10 @@ func sshKeyToKeyring(path string) (gossh.ClientKeyring, error) { return nil, err } - keyring := new(ssh.SimpleKeychain) - if err := keyring.AddPEMKey(string(keyBytes)); err != nil { - return nil, err + signer, err := gossh.ParsePrivateKey(keyBytes) + if err != nil { + return nil, fmt.Errorf("Error setting up SSH config: %s", err) } - return keyring, nil + return signer, nil } diff --git a/builder/virtualbox/common/ssh.go b/builder/virtualbox/common/ssh.go index 79f6c46f3..4ab09f20d 100644 --- a/builder/virtualbox/common/ssh.go +++ b/builder/virtualbox/common/ssh.go @@ -16,19 +16,19 @@ func SSHAddress(state multistep.StateBag) (string, error) { func SSHConfigFunc(config SSHConfig) func(multistep.StateBag) (*gossh.ClientConfig, error) { return func(state multistep.StateBag) (*gossh.ClientConfig, error) { - auth := []gossh.ClientAuth{ - gossh.ClientAuthPassword(ssh.Password(config.SSHPassword)), - gossh.ClientAuthKeyboardInteractive( + auth := []gossh.AuthMethod{ + gossh.Password(config.SSHPassword), + gossh.KeyboardInteractive( ssh.PasswordKeyboardInteractive(config.SSHPassword)), } if config.SSHKeyPath != "" { - keyring, err := sshKeyToKeyring(config.SSHKeyPath) + signer, err := sshKeyToSigner(config.SSHKeyPath) if err != nil { return nil, err } - - auth = append(auth, gossh.ClientAuthKeyring(keyring)) + + auth = append(auth, gossh.PublicKeys(signer)) } return &gossh.ClientConfig{ @@ -38,7 +38,7 @@ func SSHConfigFunc(config SSHConfig) func(multistep.StateBag) (*gossh.ClientConf } } -func sshKeyToKeyring(path string) (gossh.ClientKeyring, error) { +func sshKeyToSigner(path string) (gossh.Signer, error) { f, err := os.Open(path) if err != nil { return nil, err @@ -50,10 +50,10 @@ func sshKeyToKeyring(path string) (gossh.ClientKeyring, error) { return nil, err } - keyring := new(ssh.SimpleKeychain) - if err := keyring.AddPEMKey(string(keyBytes)); err != nil { - return nil, err + signer, err := gossh.ParsePrivateKey(keyBytes) + if err != nil { + return nil, fmt.Errorf("Error setting up SSH config: %s", err) } - return keyring, nil + return signer, nil } diff --git a/builder/virtualbox/common/ssh_config.go b/builder/virtualbox/common/ssh_config.go index c73cb0386..00c6167c6 100644 --- a/builder/virtualbox/common/ssh_config.go +++ b/builder/virtualbox/common/ssh_config.go @@ -56,7 +56,7 @@ func (c *SSHConfig) Prepare(t *packer.ConfigTemplate) []error { if c.SSHKeyPath != "" { if _, err := os.Stat(c.SSHKeyPath); err != nil { errs = append(errs, fmt.Errorf("ssh_key_path is invalid: %s", err)) - } else if _, err := sshKeyToKeyring(c.SSHKeyPath); err != nil { + } else if _, err := sshKeyToSigner(c.SSHKeyPath); err != nil { errs = append(errs, fmt.Errorf("ssh_key_path is invalid: %s", err)) } } diff --git a/builder/vmware/common/ssh.go b/builder/vmware/common/ssh.go index 7bf8bac72..c463f5f78 100644 --- a/builder/vmware/common/ssh.go +++ b/builder/vmware/common/ssh.go @@ -63,19 +63,19 @@ func SSHAddressFunc(config *SSHConfig) func(multistep.StateBag) (string, error) func SSHConfigFunc(config *SSHConfig) func(multistep.StateBag) (*gossh.ClientConfig, error) { return func(state multistep.StateBag) (*gossh.ClientConfig, error) { - auth := []gossh.ClientAuth{ - gossh.ClientAuthPassword(ssh.Password(config.SSHPassword)), - gossh.ClientAuthKeyboardInteractive( + auth := []gossh.AuthMethod{ + gossh.Password(config.SSHPassword), + gossh.KeyboardInteractive( ssh.PasswordKeyboardInteractive(config.SSHPassword)), } if config.SSHKeyPath != "" { - keyring, err := sshKeyToKeyring(config.SSHKeyPath) + signer, err := sshKeyToSigner(config.SSHKeyPath) if err != nil { return nil, err } - auth = append(auth, gossh.ClientAuthKeyring(keyring)) + auth = append(auth, gossh.PublicKeys(signer)) } return &gossh.ClientConfig{ @@ -85,7 +85,7 @@ func SSHConfigFunc(config *SSHConfig) func(multistep.StateBag) (*gossh.ClientCon } } -func sshKeyToKeyring(path string) (gossh.ClientKeyring, error) { +func sshKeyToSigner(path string) (gossh.Signer, error) { f, err := os.Open(path) if err != nil { return nil, err @@ -97,10 +97,10 @@ func sshKeyToKeyring(path string) (gossh.ClientKeyring, error) { return nil, err } - keyring := new(ssh.SimpleKeychain) - if err := keyring.AddPEMKey(string(keyBytes)); err != nil { - return nil, err + signer, err := gossh.ParsePrivateKey(keyBytes) + if err != nil { + return nil, fmt.Errorf("Error setting up SSH config: %s", err) } - return keyring, nil + return signer, nil } diff --git a/builder/vmware/common/ssh_config.go b/builder/vmware/common/ssh_config.go index 0eab2ac3c..1299bc772 100644 --- a/builder/vmware/common/ssh_config.go +++ b/builder/vmware/common/ssh_config.go @@ -48,7 +48,7 @@ func (c *SSHConfig) Prepare(t *packer.ConfigTemplate) []error { if c.SSHKeyPath != "" { if _, err := os.Stat(c.SSHKeyPath); err != nil { errs = append(errs, fmt.Errorf("ssh_key_path is invalid: %s", err)) - } else if _, err := sshKeyToKeyring(c.SSHKeyPath); err != nil { + } else if _, err := sshKeyToSigner(c.SSHKeyPath); err != nil { errs = append(errs, fmt.Errorf("ssh_key_path is invalid: %s", err)) } } diff --git a/builder/vmware/iso/driver_esx5.go b/builder/vmware/iso/driver_esx5.go index 3314a7a9c..10bb467d0 100644 --- a/builder/vmware/iso/driver_esx5.go +++ b/builder/vmware/iso/driver_esx5.go @@ -260,9 +260,9 @@ func (d *ESX5Driver) datastorePath(path string) string { func (d *ESX5Driver) connect() error { address := fmt.Sprintf("%s:%d", d.Host, d.Port) - auth := []gossh.ClientAuth{ - gossh.ClientAuthPassword(ssh.Password(d.Password)), - gossh.ClientAuthKeyboardInteractive( + auth := []gossh.AuthMethod{ + gossh.Password(d.Password), + gossh.KeyboardInteractive( ssh.PasswordKeyboardInteractive(d.Password)), } @@ -276,7 +276,7 @@ func (d *ESX5Driver) connect() error { NoPty: true, } - comm, err := ssh.New(sshConfig) + comm, err := ssh.New(address, sshConfig) if err != nil { return err } diff --git a/common/step_connect_ssh.go b/common/step_connect_ssh.go index 39e32a3d8..fa2f7d64f 100644 --- a/common/step_connect_ssh.go +++ b/common/step_connect_ssh.go @@ -137,7 +137,7 @@ func (s *StepConnectSSH) waitForSSH(state multistep.StateBag, cancel <-chan stru } log.Println("Attempting SSH connection...") - comm, err = ssh.New(config) + comm, err = ssh.New(address, config) if err != nil { log.Printf("SSH handshake err: %s", err) diff --git a/communicator/ssh/communicator.go b/communicator/ssh/communicator.go index 642b270dc..f242916bf 100644 --- a/communicator/ssh/communicator.go +++ b/communicator/ssh/communicator.go @@ -18,9 +18,10 @@ import ( ) type comm struct { - client *ssh.ClientConn - config *Config - conn net.Conn + client *ssh.Client + config *Config + conn net.Conn + address string } // Config is the structure used to configure the SSH communicator. @@ -39,10 +40,11 @@ type Config struct { // Creates a new packer.Communicator implementation over SSH. This takes // an already existing TCP connection and SSH configuration. -func New(config *Config) (result *comm, err error) { +func New(address string, config *Config) (result *comm, err error) { // Establish an initial connection and connect result = &comm{ - config: config, + config: config, + address: address, } if err = result.reconnect(); err != nil { @@ -253,10 +255,13 @@ func (c *comm) reconnect() (err error) { } log.Printf("handshaking with SSH") - c.client, err = ssh.Client(c.conn, c.config.SSHConfig) + sshConn, sshChan, req, err := ssh.NewClientConn(c.conn, c.address, c.config.SSHConfig) if err != nil { log.Printf("handshake error: %s", err) } + if sshConn != nil { + c.client = ssh.NewClient(sshConn, sshChan, req) + } return } diff --git a/communicator/ssh/communicator_test.go b/communicator/ssh/communicator_test.go index 60612fd00..c5b8832dd 100644 --- a/communicator/ssh/communicator_test.go +++ b/communicator/ssh/communicator_test.go @@ -5,6 +5,7 @@ package ssh import ( "bytes" "code.google.com/p/go.crypto/ssh" + "fmt" "github.com/mitchellh/packer/packer" "net" "testing" @@ -39,65 +40,57 @@ gqnBycHj6AhEycjda75cs+0zybZvN4x65KZHOGW/O/7OAWEcZP5TPb3zf9ned3Hl NsZoFj52ponUM6+99A2CmezFCN16c4mbA//luWF+k3VVqR6BpkrhKw== -----END RSA PRIVATE KEY-----` -// password implements the ClientPassword interface -type password string - -func (p password) Password(user string) (string, error) { - return string(p), nil -} - var serverConfig = &ssh.ServerConfig{ - PasswordCallback: func(c *ssh.ServerConn, user, pass string) bool { - return user == "user" && pass == "pass" + PasswordCallback: func(c ssh.ConnMetadata, pass []byte) (*ssh.Permissions, error) { + if c.User() == "user" && string(pass) == "pass" { + return nil, nil + } + return nil, fmt.Errorf("password rejected for %q", c.User()) }, } func init() { - // Set the private key of the server, required to accept connections - if err := serverConfig.SetRSAPrivateKey([]byte(testServerPrivateKey)); err != nil { - panic("unable to set private key: " + err.Error()) + // Parse and set the private key of the server, required to accept connections + signer, err := ssh.ParsePrivateKey([]byte(testServerPrivateKey)) + if err != nil { + panic("unable to parse private key: " + err.Error()) } + serverConfig.AddHostKey(signer) } func newMockLineServer(t *testing.T) string { - l, err := ssh.Listen("tcp", "127.0.0.1:0", serverConfig) + l, err := net.Listen("tcp", "127.0.0.1:0") if err != nil { - t.Fatalf("unable to newMockAuthServer: %s", err) + t.Fatalf("Unable to listen for connection: %s", err) } + go func() { defer l.Close() c, err := l.Accept() if err != nil { - t.Errorf("Unable to accept incoming connection: %v", err) - return + t.Errorf("Unable to accept incoming connection: %s", err) } - - if err := c.Handshake(); err != nil { - // not Errorf because this is expected to - // fail for some tests. + defer c.Close() + conn, chans, _, err := ssh.NewServerConn(c, serverConfig) + if err != nil { t.Logf("Handshaking error: %v", err) - return } - t.Log("Accepted SSH connection") - defer c.Close() - - channel, err := c.Accept() - if err != nil { - t.Errorf("Unable to accept a channel: %s", err) - return + for newChannel := range chans { + channel, _, err := newChannel.Accept() + if err != nil { + t.Errorf("Unable to accept channel.") + } + t.Log("Accepted channel") + + go func() { + defer channel.Close() + conn.OpenChannel(newChannel.ChannelType(), nil) + }() } - - // Just go in a loop now accepting things... we need to - // do this to handle packets for SSH. - go func() { - c.Accept() - }() - - channel.Accept() - t.Log("Accepted channel") - defer channel.Close() + conn.Close() }() + return l.Addr().String() } @@ -112,15 +105,16 @@ func TestCommIsCommunicator(t *testing.T) { func TestNew_Invalid(t *testing.T) { clientConfig := &ssh.ClientConfig{ User: "user", - Auth: []ssh.ClientAuth{ - ssh.ClientAuthPassword(password("i-am-invalid")), + Auth: []ssh.AuthMethod{ + ssh.Password("i-am-invalid"), }, } + address := newMockLineServer(t) conn := func() (net.Conn, error) { - conn, err := net.Dial("tcp", newMockLineServer(t)) + conn, err := net.Dial("tcp", address) if err != nil { - t.Fatalf("unable to dial to remote side: %s", err) + t.Errorf("Unable to accept incoming connection: %v", err) } return conn, err } @@ -130,7 +124,7 @@ func TestNew_Invalid(t *testing.T) { SSHConfig: clientConfig, } - _, err := New(config) + _, err := New(address, config) if err == nil { t.Fatal("should have had an error connecting") } @@ -139,13 +133,14 @@ func TestNew_Invalid(t *testing.T) { func TestStart(t *testing.T) { clientConfig := &ssh.ClientConfig{ User: "user", - Auth: []ssh.ClientAuth{ - ssh.ClientAuthPassword(password("pass")), + Auth: []ssh.AuthMethod{ + ssh.Password("pass"), }, } + address := newMockLineServer(t) conn := func() (net.Conn, error) { - conn, err := net.Dial("tcp", newMockLineServer(t)) + conn, err := net.Dial("tcp", address) if err != nil { t.Fatalf("unable to dial to remote side: %s", err) } @@ -157,7 +152,7 @@ func TestStart(t *testing.T) { SSHConfig: clientConfig, } - client, err := New(config) + client, err := New(address, config) if err != nil { t.Fatalf("error connecting to SSH: %s", err) } diff --git a/communicator/ssh/keychain.go b/communicator/ssh/keychain.go deleted file mode 100644 index f9965c0da..000000000 --- a/communicator/ssh/keychain.go +++ /dev/null @@ -1,81 +0,0 @@ -package ssh - -import ( - "code.google.com/p/go.crypto/ssh" - "crypto" - "crypto/dsa" - "crypto/rsa" - "crypto/x509" - "encoding/pem" - "errors" - "io" -) - -// SimpleKeychain makes it easy to use private keys in order to connect -// via SSH, since the interface exposed by Go isn't the easiest to use -// right away. -type SimpleKeychain struct { - keys []interface{} -} - -// AddPEMKey adds a simple PEM encoded private key to the keychain. -func (k *SimpleKeychain) AddPEMKey(key string) (err error) { - block, _ := pem.Decode([]byte(key)) - if block == nil { - return errors.New("no block in key") - } - - var rsakey interface{} - rsakey, err = x509.ParsePKCS1PrivateKey(block.Bytes) - if err != nil { - rsakey, err = x509.ParsePKCS8PrivateKey(block.Bytes) - } - - if err != nil { - return - } - - k.keys = append(k.keys, rsakey) - return -} - -// AddPEMKeyPassword adds a PEM encoded private key that is protected by -// a password to the keychain. -func (k *SimpleKeychain) AddPEMKeyPassword(key string, password string) (err error) { - block, _ := pem.Decode([]byte(key)) - bytes, _ := x509.DecryptPEMBlock(block, []byte(password)) - rsakey, err := x509.ParsePKCS1PrivateKey(bytes) - if err != nil { - return - } - - k.keys = append(k.keys, rsakey) - return -} - -// Key method for ssh.ClientKeyring interface -func (k *SimpleKeychain) Key(i int) (ssh.PublicKey, error) { - if i < 0 || i >= len(k.keys) { - return nil, nil - } - switch key := k.keys[i].(type) { - case *rsa.PrivateKey: - return ssh.NewPublicKey(&key.PublicKey) - case *dsa.PrivateKey: - return ssh.NewPublicKey(&key.PublicKey) - } - panic("unknown key type") -} - -// Sign method for ssh.ClientKeyring interface -func (k *SimpleKeychain) Sign(i int, rand io.Reader, data []byte) (sig []byte, err error) { - hashFunc := crypto.SHA1 - h := hashFunc.New() - h.Write(data) - digest := h.Sum(nil) - switch key := k.keys[i].(type) { - case *rsa.PrivateKey: - return rsa.SignPKCS1v15(rand, key, hashFunc, digest) - } - return nil, errors.New("ssh: unknown key type") -} diff --git a/communicator/ssh/keychain_test.go b/communicator/ssh/keychain_test.go deleted file mode 100644 index 5f9ba3ae5..000000000 --- a/communicator/ssh/keychain_test.go +++ /dev/null @@ -1,32 +0,0 @@ -package ssh - -import ( - "code.google.com/p/go.crypto/ssh" - "testing" -) - -const testPrivateKey = `-----BEGIN RSA PRIVATE KEY----- -MIIBOwIBAAJBALdGZxkXDAjsYk10ihwU6Id2KeILz1TAJuoq4tOgDWxEEGeTrcld -r/ZwVaFzjWzxaf6zQIJbfaSEAhqD5yo72+sCAwEAAQJBAK8PEVU23Wj8mV0QjwcJ -tZ4GcTUYQL7cF4+ezTCE9a1NrGnCP2RuQkHEKxuTVrxXt+6OF15/1/fuXnxKjmJC -nxkCIQDaXvPPBi0c7vAxGwNY9726x01/dNbHCE0CBtcotobxpwIhANbbQbh3JHVW -2haQh4fAG5mhesZKAGcxTyv4mQ7uMSQdAiAj+4dzMpJWdSzQ+qGHlHMIBvVHLkqB -y2VdEyF7DPCZewIhAI7GOI/6LDIFOvtPo6Bj2nNmyQ1HU6k/LRtNIXi4c9NJAiAr -rrxx26itVhJmcvoUhOjwuzSlP2bE5VHAvkGB352YBg== ------END RSA PRIVATE KEY-----` - -func TestAddPEMKey(t *testing.T) { - k := &SimpleKeychain{} - err := k.AddPEMKey(testPrivateKey) - if err != nil { - t.Fatalf("error while adding key: %s", err) - } -} - -func TestSimpleKeyChain_ImplementsClientkeyring(t *testing.T) { - var raw interface{} - raw = &SimpleKeychain{} - if _, ok := raw.(ssh.ClientKeyring); !ok { - t.Fatal("SimpleKeychain is not a valid ssh.ClientKeyring") - } -} diff --git a/communicator/ssh/password.go b/communicator/ssh/password.go index 3fc6e5f35..7ce18171d 100644 --- a/communicator/ssh/password.go +++ b/communicator/ssh/password.go @@ -1,32 +1,27 @@ package ssh -import "log" +import ( + "log" + "code.google.com/p/go.crypto/ssh" +) -// An implementation of ssh.ClientPassword so that you can use a static -// string password for the password to ClientAuthPassword. -type Password string - -func (p Password) Password(user string) (string, error) { - return string(p), nil -} - -// An implementation of ssh.ClientKeyboardInteractive that simply sends +// An implementation of ssh.KeyboardInteractiveChallenge that simply sends // back the password for all questions. The questions are logged. -type PasswordKeyboardInteractive string - -func (p PasswordKeyboardInteractive) Challenge(user, instruction string, questions []string, echos []bool) ([]string, error) { - log.Printf("Keyboard interactive challenge: ") - log.Printf("-- User: %s", user) - log.Printf("-- Instructions: %s", instruction) - for i, question := range questions { - log.Printf("-- Question %d: %s", i+1, question) +func PasswordKeyboardInteractive (password string) (ssh.KeyboardInteractiveChallenge) { + return func (user, instruction string, questions []string, echos []bool) ([]string, error) { + log.Printf("Keyboard interactive challenge: ") + log.Printf("-- User: %s", user) + log.Printf("-- Instructions: %s", instruction) + for i, question := range questions { + log.Printf("-- Question %d: %s", i+1, question) + } + + // Just send the password back for all questions + answers := make([]string, len(questions)) + for i, _ := range answers { + answers[i] = string(password) + } + + return answers, nil } - - // Just send the password back for all questions - answers := make([]string, len(questions)) - for i, _ := range answers { - answers[i] = string(p) - } - - return answers, nil } diff --git a/communicator/ssh/password_test.go b/communicator/ssh/password_test.go index e55779e82..e74b46e06 100644 --- a/communicator/ssh/password_test.go +++ b/communicator/ssh/password_test.go @@ -6,37 +6,17 @@ import ( "testing" ) -func TestPassword_Impl(t *testing.T) { - var raw interface{} - raw = Password("foo") - if _, ok := raw.(ssh.ClientPassword); !ok { - t.Fatal("Password must implement ClientPassword") - } -} - -func TestPasswordPassword(t *testing.T) { - p := Password("foo") - result, err := p.Password("user") - if err != nil { - t.Fatalf("err not nil: %s", err) - } - - if result != "foo" { - t.Fatalf("invalid password: %s", result) - } -} - func TestPasswordKeyboardInteractive_Impl(t *testing.T) { var raw interface{} raw = PasswordKeyboardInteractive("foo") - if _, ok := raw.(ssh.ClientKeyboardInteractive); !ok { - t.Fatal("PasswordKeyboardInteractive must implement ClientKeyboardInteractive") + if _, ok := raw.(ssh.KeyboardInteractiveChallenge); !ok { + t.Fatal("PasswordKeyboardInteractive must implement KeyboardInteractiveChallenge") } } func TestPasswordKeybardInteractive_Challenge(t *testing.T) { p := PasswordKeyboardInteractive("foo") - result, err := p.Challenge("foo", "bar", []string{"one", "two"}, nil) + result, err := p("foo", "bar", []string{"one", "two"}, nil) if err != nil { t.Fatalf("err not nil: %s", err) } diff --git a/packer/rpc/client_test.go b/packer/rpc/client_test.go index c0595cbe4..44c972e66 100644 --- a/packer/rpc/client_test.go +++ b/packer/rpc/client_test.go @@ -6,7 +6,7 @@ import ( ) func testConn(t *testing.T) (net.Conn, net.Conn) { - l, err := net.Listen("tcp", ":0") + l, err := net.Listen("tcp", "127.0.0.1:0") if err != nil { t.Fatalf("err: %s", err) } diff --git a/packer/rpc/muxconn_test.go b/packer/rpc/muxconn_test.go index 8784b1410..27a77fb46 100644 --- a/packer/rpc/muxconn_test.go +++ b/packer/rpc/muxconn_test.go @@ -18,7 +18,7 @@ func readStream(t *testing.T, s io.Reader) string { } func testMux(t *testing.T) (client *MuxConn, server *MuxConn) { - l, err := net.Listen("tcp", ":0") + l, err := net.Listen("tcp", "127.0.0.1:0") if err != nil { t.Fatalf("err: %s", err) }