Merge branch 'update-ssh-package' of github.com:higebu/packer into higebu-update-ssh-package
Conflicts: builder/amazon/common/ssh.go builder/digitalocean/ssh.go builder/googlecompute/ssh.go builder/openstack/ssh.go communicator/ssh/communicator_test.go communicator/ssh/keychain.go communicator/ssh/keychain_test.go
This commit is contained in:
commit
e84e5e4f2c
|
@ -1,12 +1,11 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
gossh "code.google.com/p/gosshold/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
|
||||
}
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
package digitalocean
|
||||
|
||||
import (
|
||||
gossh "code.google.com/p/gosshold/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
|
||||
}
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
package googlecompute
|
||||
|
||||
import (
|
||||
"code.google.com/p/go.crypto/ssh"
|
||||
"fmt"
|
||||
|
||||
gossh "code.google.com/p/gosshold/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
|
||||
}
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
package openstack
|
||||
|
||||
import (
|
||||
gossh "code.google.com/p/gosshold/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
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -249,9 +249,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)),
|
||||
}
|
||||
|
||||
|
@ -265,7 +265,7 @@ func (d *ESX5Driver) connect() error {
|
|||
NoPty: true,
|
||||
}
|
||||
|
||||
comm, err := ssh.New(sshConfig)
|
||||
comm, err := ssh.New(address, sshConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -18,9 +18,10 @@ import (
|
|||
)
|
||||
|
||||
type comm struct {
|
||||
client *ssh.ClientConn
|
||||
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,
|
||||
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
|
||||
}
|
||||
|
|
|
@ -4,7 +4,8 @@ package ssh
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"code.google.com/p/gosshold/ssh"
|
||||
"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.
|
||||
t.Logf("Handshaking error: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
t.Log("Accepted SSH connection")
|
||||
defer c.Close()
|
||||
|
||||
channel, err := c.Accept()
|
||||
conn, chans, _, err := ssh.NewServerConn(c, serverConfig)
|
||||
if err != nil {
|
||||
t.Errorf("Unable to accept a channel: %s", err)
|
||||
return
|
||||
t.Logf("Handshaking error: %v", err)
|
||||
}
|
||||
t.Log("Accepted SSH connection")
|
||||
for newChannel := range chans {
|
||||
channel, _, err := newChannel.Accept()
|
||||
if err != nil {
|
||||
t.Errorf("Unable to accept channel.")
|
||||
}
|
||||
|
||||
// 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")
|
||||
|
||||
go func() {
|
||||
defer channel.Close()
|
||||
conn.OpenChannel(newChannel.ChannelType(), nil)
|
||||
}()
|
||||
}
|
||||
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)
|
||||
}
|
||||
|
|
|
@ -1,81 +0,0 @@
|
|||
package ssh
|
||||
|
||||
import (
|
||||
"code.google.com/p/gosshold/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")
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
package ssh
|
||||
|
||||
import (
|
||||
"code.google.com/p/gosshold/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")
|
||||
}
|
||||
}
|
|
@ -1,20 +1,14 @@
|
|||
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) {
|
||||
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)
|
||||
|
@ -25,8 +19,9 @@ func (p PasswordKeyboardInteractive) Challenge(user, instruction string, questio
|
|||
// Just send the password back for all questions
|
||||
answers := make([]string, len(questions))
|
||||
for i, _ := range answers {
|
||||
answers[i] = string(p)
|
||||
answers[i] = string(password)
|
||||
}
|
||||
|
||||
return answers, nil
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue