1
// Copyright 2011 The Go Authors. All rights reserved.
2
// Use of this source code is governed by a BSD-style
3
// license that can be found in the LICENSE file.
16
type keyboardInteractive map[string]string
18
func (cr keyboardInteractive) Challenge(user string, instruction string, questions []string, echos []bool) ([]string, error) {
20
for _, q := range questions {
21
answers = append(answers, cr[q])
26
// reused internally by tests
27
var clientPassword = "tiger"
29
// tryAuth runs a handshake with a given config against an SSH server
30
// with config serverConfig
31
func tryAuth(t *testing.T, config *ClientConfig) error {
32
c1, c2, err := netPipe()
34
t.Fatalf("netPipe: %v", err)
39
certChecker := CertChecker{
40
IsAuthority: func(k PublicKey) bool {
41
return bytes.Equal(k.Marshal(), testPublicKeys["ecdsa"].Marshal())
43
UserKeyFallback: func(conn ConnMetadata, key PublicKey) (*Permissions, error) {
44
if conn.User() == "testuser" && bytes.Equal(key.Marshal(), testPublicKeys["rsa"].Marshal()) {
48
return nil, fmt.Errorf("pubkey for %q not acceptable", conn.User())
50
IsRevoked: func(c *Certificate) bool {
51
return c.Serial == 666
55
serverConfig := &ServerConfig{
56
PasswordCallback: func(conn ConnMetadata, pass []byte) (*Permissions, error) {
57
if conn.User() == "testuser" && string(pass) == clientPassword {
60
return nil, errors.New("password auth failed")
62
PublicKeyCallback: certChecker.Authenticate,
63
KeyboardInteractiveCallback: func(conn ConnMetadata, challenge KeyboardInteractiveChallenge) (*Permissions, error) {
64
ans, err := challenge("user",
66
[]string{"question1", "question2"},
71
ok := conn.User() == "testuser" && ans[0] == "answer1" && ans[1] == "answer2"
73
challenge("user", "motd", nil, nil)
76
return nil, errors.New("keyboard-interactive failed")
78
AuthLogCallback: func(conn ConnMetadata, method string, err error) {
79
t.Logf("user %q, method %q: %v", conn.User(), method, err)
82
serverConfig.AddHostKey(testSigners["rsa"])
84
go newServer(c1, serverConfig)
85
_, _, _, err = NewClientConn(c2, "", config)
89
func TestClientAuthPublicKey(t *testing.T) {
90
config := &ClientConfig{
93
PublicKeys(testSigners["rsa"]),
96
if err := tryAuth(t, config); err != nil {
97
t.Fatalf("unable to dial remote side: %s", err)
101
func TestAuthMethodPassword(t *testing.T) {
102
config := &ClientConfig{
105
Password(clientPassword),
109
if err := tryAuth(t, config); err != nil {
110
t.Fatalf("unable to dial remote side: %s", err)
114
func TestAuthMethodFallback(t *testing.T) {
115
var passwordCalled bool
116
config := &ClientConfig{
119
PublicKeys(testSigners["rsa"]),
121
func() (string, error) {
122
passwordCalled = true
128
if err := tryAuth(t, config); err != nil {
129
t.Fatalf("unable to dial remote side: %s", err)
133
t.Errorf("password auth tried before public-key auth.")
137
func TestAuthMethodWrongPassword(t *testing.T) {
138
config := &ClientConfig{
142
PublicKeys(testSigners["rsa"]),
146
if err := tryAuth(t, config); err != nil {
147
t.Fatalf("unable to dial remote side: %s", err)
151
func TestAuthMethodKeyboardInteractive(t *testing.T) {
152
answers := keyboardInteractive(map[string]string{
153
"question1": "answer1",
154
"question2": "answer2",
156
config := &ClientConfig{
159
KeyboardInteractive(answers.Challenge),
163
if err := tryAuth(t, config); err != nil {
164
t.Fatalf("unable to dial remote side: %s", err)
168
func TestAuthMethodWrongKeyboardInteractive(t *testing.T) {
169
answers := keyboardInteractive(map[string]string{
170
"question1": "answer1",
171
"question2": "WRONG",
173
config := &ClientConfig{
176
KeyboardInteractive(answers.Challenge),
180
if err := tryAuth(t, config); err == nil {
181
t.Fatalf("wrong answers should not have authenticated with KeyboardInteractive")
185
// the mock server will only authenticate ssh-rsa keys
186
func TestAuthMethodInvalidPublicKey(t *testing.T) {
187
config := &ClientConfig{
190
PublicKeys(testSigners["dsa"]),
194
if err := tryAuth(t, config); err == nil {
195
t.Fatalf("dsa private key should not have authenticated with rsa public key")
199
// the client should authenticate with the second key
200
func TestAuthMethodRSAandDSA(t *testing.T) {
201
config := &ClientConfig{
204
PublicKeys(testSigners["dsa"], testSigners["rsa"]),
207
if err := tryAuth(t, config); err != nil {
208
t.Fatalf("client could not authenticate with rsa key: %v", err)
212
func TestClientHMAC(t *testing.T) {
213
for _, mac := range supportedMACs {
214
config := &ClientConfig{
217
PublicKeys(testSigners["rsa"]),
223
if err := tryAuth(t, config); err != nil {
224
t.Fatalf("client could not authenticate with mac algo %s: %v", mac, err)
230
func TestClientUnsupportedCipher(t *testing.T) {
231
config := &ClientConfig{
237
Ciphers: []string{"aes128-cbc"}, // not currently supported
240
if err := tryAuth(t, config); err == nil {
241
t.Errorf("expected no ciphers in common")
245
func TestClientUnsupportedKex(t *testing.T) {
246
config := &ClientConfig{
252
KeyExchanges: []string{"diffie-hellman-group-exchange-sha256"}, // not currently supported
255
if err := tryAuth(t, config); err == nil || !strings.Contains(err.Error(), "common algorithm") {
256
t.Errorf("got %v, expected 'common algorithm'", err)
260
func TestClientLoginCert(t *testing.T) {
261
cert := &Certificate{
262
Key: testPublicKeys["rsa"],
263
ValidBefore: CertTimeInfinity,
266
cert.SignCert(rand.Reader, testSigners["ecdsa"])
267
certSigner, err := NewCertSigner(cert, testSigners["rsa"])
269
t.Fatalf("NewCertSigner: %v", err)
272
clientConfig := &ClientConfig{
275
clientConfig.Auth = append(clientConfig.Auth, PublicKeys(certSigner))
277
t.Log("should succeed")
278
if err := tryAuth(t, clientConfig); err != nil {
279
t.Errorf("cert login failed: %v", err)
282
t.Log("corrupted signature")
283
cert.Signature.Blob[0]++
284
if err := tryAuth(t, clientConfig); err == nil {
285
t.Errorf("cert login passed with corrupted sig")
290
cert.SignCert(rand.Reader, testSigners["ecdsa"])
291
if err := tryAuth(t, clientConfig); err == nil {
292
t.Errorf("revoked cert login succeeded")
296
t.Log("sign with wrong key")
297
cert.SignCert(rand.Reader, testSigners["dsa"])
298
if err := tryAuth(t, clientConfig); err == nil {
299
t.Errorf("cert login passed with non-authoritive key")
303
cert.CertType = HostCert
304
cert.SignCert(rand.Reader, testSigners["ecdsa"])
305
if err := tryAuth(t, clientConfig); err == nil {
306
t.Errorf("cert login passed with wrong type")
308
cert.CertType = UserCert
310
t.Log("principal specified")
311
cert.ValidPrincipals = []string{"user"}
312
cert.SignCert(rand.Reader, testSigners["ecdsa"])
313
if err := tryAuth(t, clientConfig); err != nil {
314
t.Errorf("cert login failed: %v", err)
317
t.Log("wrong principal specified")
318
cert.ValidPrincipals = []string{"fred"}
319
cert.SignCert(rand.Reader, testSigners["ecdsa"])
320
if err := tryAuth(t, clientConfig); err == nil {
321
t.Errorf("cert login passed with wrong principal")
323
cert.ValidPrincipals = nil
325
t.Log("added critical option")
326
cert.CriticalOptions = map[string]string{"root-access": "yes"}
327
cert.SignCert(rand.Reader, testSigners["ecdsa"])
328
if err := tryAuth(t, clientConfig); err == nil {
329
t.Errorf("cert login passed with unrecognized critical option")
332
t.Log("allowed source address")
333
cert.CriticalOptions = map[string]string{"source-address": "127.0.0.42/24"}
334
cert.SignCert(rand.Reader, testSigners["ecdsa"])
335
if err := tryAuth(t, clientConfig); err != nil {
336
t.Errorf("cert login with source-address failed: %v", err)
339
t.Log("disallowed source address")
340
cert.CriticalOptions = map[string]string{"source-address": "127.0.0.42"}
341
cert.SignCert(rand.Reader, testSigners["ecdsa"])
342
if err := tryAuth(t, clientConfig); err == nil {
343
t.Errorf("cert login with source-address succeeded")
347
func testPermissionsPassing(withPermissions bool, t *testing.T) {
348
serverConfig := &ServerConfig{
349
PublicKeyCallback: func(conn ConnMetadata, key PublicKey) (*Permissions, error) {
350
if conn.User() == "nopermissions" {
353
return &Permissions{}, nil
357
serverConfig.AddHostKey(testSigners["rsa"])
359
clientConfig := &ClientConfig{
361
PublicKeys(testSigners["rsa"]),
365
clientConfig.User = "permissions"
367
clientConfig.User = "nopermissions"
370
c1, c2, err := netPipe()
372
t.Fatalf("netPipe: %v", err)
377
go NewClientConn(c2, "", clientConfig)
378
serverConn, err := newServer(c1, serverConfig)
382
if p := serverConn.Permissions; (p != nil) != withPermissions {
383
t.Fatalf("withPermissions is %t, but Permissions object is %#v", withPermissions, p)
387
func TestPermissionsPassing(t *testing.T) {
388
testPermissionsPassing(true, t)
391
func TestNoPermissionsPassing(t *testing.T) {
392
testPermissionsPassing(false, t)