From 93a8c153a611d090d2dcf25287c9f64827926273 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Tue, 2 Jul 2013 22:00:31 -0700 Subject: [PATCH] communicator/ssh: add keyboard interactive auth [GH-121] --- communicator/ssh/password.go | 23 +++++++++++++++++++++++ communicator/ssh/password_test.go | 22 ++++++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/communicator/ssh/password.go b/communicator/ssh/password.go index 8253985b8..3fc6e5f35 100644 --- a/communicator/ssh/password.go +++ b/communicator/ssh/password.go @@ -1,5 +1,7 @@ package ssh +import "log" + // An implementation of ssh.ClientPassword so that you can use a static // string password for the password to ClientAuthPassword. type Password string @@ -7,3 +9,24 @@ type Password string func (p Password) Password(user string) (string, error) { return string(p), nil } + +// An implementation of ssh.ClientKeyboardInteractive 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) + } + + // 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 87de99edb..bed2d1cb1 100644 --- a/communicator/ssh/password_test.go +++ b/communicator/ssh/password_test.go @@ -2,6 +2,7 @@ package ssh import ( "code.google.com/p/go.crypto/ssh" + "reflect" "testing" ) @@ -24,3 +25,24 @@ func TestPasswordPassword(t *testing.T) { 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") + } +} + +func TestPasswordKeybardInteractive_Challenge(t *testing.T) { + p := PasswordKeyboardInteractive("foo") + result, err := p.Challenge("foo", "bar", []string{"one", "two"}, nil) + if err != nil { + t.Fatalf("err not nil: %s", err) + } + + if !reflect.DeepEqual(result, []string{"foo", "foo"}) { + t.Fatalf("invalid password: %#v", result) + } +} +