~ubuntu-branches/ubuntu/utopic/hockeypuck/utopic-proposed

« back to all changes in this revision

Viewing changes to build/src/code.google.com/p/go.crypto/ssh/client_auth_test.go

  • Committer: Package Import Robot
  • Author(s): Casey Marshall
  • Date: 2014-04-13 20:06:01 UTC
  • Revision ID: package-import@ubuntu.com-20140413200601-oxdlqn1gy0x8m55u
Tags: 1.0~rel20140413+7a1892a~trusty
Hockeypuck 1.0 release

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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.
 
4
 
 
5
package ssh
 
6
 
 
7
import (
 
8
        "bytes"
 
9
        "crypto/dsa"
 
10
        "io"
 
11
        "io/ioutil"
 
12
        "math/big"
 
13
        "strings"
 
14
        "testing"
 
15
 
 
16
        _ "crypto/sha1"
 
17
)
 
18
 
 
19
// private key for mock server
 
20
const testServerPrivateKey = `-----BEGIN RSA PRIVATE KEY-----
 
21
MIIEpAIBAAKCAQEA19lGVsTqIT5iiNYRgnoY1CwkbETW5cq+Rzk5v/kTlf31XpSU
 
22
70HVWkbTERECjaYdXM2gGcbb+sxpq6GtXf1M3kVomycqhxwhPv4Cr6Xp4WT/jkFx
 
23
9z+FFzpeodGJWjOH6L2H5uX1Cvr9EDdQp9t9/J32/qBFntY8GwoUI/y/1MSTmMiF
 
24
tupdMODN064vd3gyMKTwrlQ8tZM6aYuyOPsutLlUY7M5x5FwMDYvnPDSeyT/Iw0z
 
25
s3B+NCyqeeMd2T7YzQFnRATj0M7rM5LoSs7DVqVriOEABssFyLj31PboaoLhOKgc
 
26
qoM9khkNzr7FHVvi+DhYM2jD0DwvqZLN6NmnLwIDAQABAoIBAQCGVj+kuSFOV1lT
 
27
+IclQYA6bM6uY5mroqcSBNegVxCNhWU03BxlW//BE9tA/+kq53vWylMeN9mpGZea
 
28
riEMIh25KFGWXqXlOOioH8bkMsqA8S7sBmc7jljyv+0toQ9vCCtJ+sueNPhxQQxH
 
29
D2YvUjfzBQ04I9+wn30BByDJ1QA/FoPsunxIOUCcRBE/7jxuLYcpR+JvEF68yYIh
 
30
atXRld4W4in7T65YDR8jK1Uj9XAcNeDYNpT/M6oFLx1aPIlkG86aCWRO19S1jLPT
 
31
b1ZAKHHxPMCVkSYW0RqvIgLXQOR62D0Zne6/2wtzJkk5UCjkSQ2z7ZzJpMkWgDgN
 
32
ifCULFPBAoGBAPoMZ5q1w+zB+knXUD33n1J+niN6TZHJulpf2w5zsW+m2K6Zn62M
 
33
MXndXlVAHtk6p02q9kxHdgov34Uo8VpuNjbS1+abGFTI8NZgFo+bsDxJdItemwC4
 
34
KJ7L1iz39hRN/ZylMRLz5uTYRGddCkeIHhiG2h7zohH/MaYzUacXEEy3AoGBANz8
 
35
e/msleB+iXC0cXKwds26N4hyMdAFE5qAqJXvV3S2W8JZnmU+sS7vPAWMYPlERPk1
 
36
D8Q2eXqdPIkAWBhrx4RxD7rNc5qFNcQWEhCIxC9fccluH1y5g2M+4jpMX2CT8Uv+
 
37
3z+NoJ5uDTXZTnLCfoZzgZ4nCZVZ+6iU5U1+YXFJAoGBANLPpIV920n/nJmmquMj
 
38
orI1R/QXR9Cy56cMC65agezlGOfTYxk5Cfl5Ve+/2IJCfgzwJyjWUsFx7RviEeGw
 
39
64o7JoUom1HX+5xxdHPsyZ96OoTJ5RqtKKoApnhRMamau0fWydH1yeOEJd+TRHhc
 
40
XStGfhz8QNa1dVFvENczja1vAoGABGWhsd4VPVpHMc7lUvrf4kgKQtTC2PjA4xoc
 
41
QJ96hf/642sVE76jl+N6tkGMzGjnVm4P2j+bOy1VvwQavKGoXqJBRd5Apppv727g
 
42
/SM7hBXKFc/zH80xKBBgP/i1DR7kdjakCoeu4ngeGywvu2jTS6mQsqzkK+yWbUxJ
 
43
I7mYBsECgYB/KNXlTEpXtz/kwWCHFSYA8U74l7zZbVD8ul0e56JDK+lLcJ0tJffk
 
44
gqnBycHj6AhEycjda75cs+0zybZvN4x65KZHOGW/O/7OAWEcZP5TPb3zf9ned3Hl
 
45
NsZoFj52ponUM6+99A2CmezFCN16c4mbA//luWF+k3VVqR6BpkrhKw==
 
46
-----END RSA PRIVATE KEY-----`
 
47
 
 
48
const testClientPrivateKey = `-----BEGIN RSA PRIVATE KEY-----
 
49
MIIBOwIBAAJBALdGZxkXDAjsYk10ihwU6Id2KeILz1TAJuoq4tOgDWxEEGeTrcld
 
50
r/ZwVaFzjWzxaf6zQIJbfaSEAhqD5yo72+sCAwEAAQJBAK8PEVU23Wj8mV0QjwcJ
 
51
tZ4GcTUYQL7cF4+ezTCE9a1NrGnCP2RuQkHEKxuTVrxXt+6OF15/1/fuXnxKjmJC
 
52
nxkCIQDaXvPPBi0c7vAxGwNY9726x01/dNbHCE0CBtcotobxpwIhANbbQbh3JHVW
 
53
2haQh4fAG5mhesZKAGcxTyv4mQ7uMSQdAiAj+4dzMpJWdSzQ+qGHlHMIBvVHLkqB
 
54
y2VdEyF7DPCZewIhAI7GOI/6LDIFOvtPo6Bj2nNmyQ1HU6k/LRtNIXi4c9NJAiAr
 
55
rrxx26itVhJmcvoUhOjwuzSlP2bE5VHAvkGB352YBg==
 
56
-----END RSA PRIVATE KEY-----`
 
57
 
 
58
// keychain implements the ClientKeyring interface
 
59
type keychain struct {
 
60
        keys []Signer
 
61
}
 
62
 
 
63
func (k *keychain) Key(i int) (PublicKey, error) {
 
64
        if i < 0 || i >= len(k.keys) {
 
65
                return nil, nil
 
66
        }
 
67
 
 
68
        return k.keys[i].PublicKey(), nil
 
69
}
 
70
 
 
71
func (k *keychain) Sign(i int, rand io.Reader, data []byte) (sig []byte, err error) {
 
72
        return k.keys[i].Sign(rand, data)
 
73
}
 
74
 
 
75
func (k *keychain) add(key Signer) {
 
76
        k.keys = append(k.keys, key)
 
77
}
 
78
 
 
79
func (k *keychain) loadPEM(file string) error {
 
80
        buf, err := ioutil.ReadFile(file)
 
81
        if err != nil {
 
82
                return err
 
83
        }
 
84
        key, err := ParsePrivateKey(buf)
 
85
        if err != nil {
 
86
                return err
 
87
        }
 
88
        k.add(key)
 
89
        return nil
 
90
}
 
91
 
 
92
// password implements the ClientPassword interface
 
93
type password string
 
94
 
 
95
func (p password) Password(user string) (string, error) {
 
96
        return string(p), nil
 
97
}
 
98
 
 
99
type keyboardInteractive map[string]string
 
100
 
 
101
func (cr *keyboardInteractive) Challenge(user string, instruction string, questions []string, echos []bool) ([]string, error) {
 
102
        var answers []string
 
103
        for _, q := range questions {
 
104
                answers = append(answers, (*cr)[q])
 
105
        }
 
106
        return answers, nil
 
107
}
 
108
 
 
109
// reused internally by tests
 
110
var (
 
111
        rsaKey         Signer
 
112
        dsaKey         Signer
 
113
        clientKeychain = new(keychain)
 
114
        clientPassword = password("tiger")
 
115
        serverConfig   = &ServerConfig{
 
116
                PasswordCallback: func(conn *ServerConn, user, pass string) bool {
 
117
                        return user == "testuser" && pass == string(clientPassword)
 
118
                },
 
119
                PublicKeyCallback: func(conn *ServerConn, user, algo string, pubkey []byte) bool {
 
120
                        key, _ := clientKeychain.Key(0)
 
121
                        expected := MarshalPublicKey(key)
 
122
                        algoname := key.PublicKeyAlgo()
 
123
                        return user == "testuser" && algo == algoname && bytes.Equal(pubkey, expected)
 
124
                },
 
125
                KeyboardInteractiveCallback: func(conn *ServerConn, user string, client ClientKeyboardInteractive) bool {
 
126
                        ans, err := client.Challenge("user",
 
127
                                "instruction",
 
128
                                []string{"question1", "question2"},
 
129
                                []bool{true, true})
 
130
                        if err != nil {
 
131
                                return false
 
132
                        }
 
133
                        ok := user == "testuser" && ans[0] == "answer1" && ans[1] == "answer2"
 
134
                        client.Challenge("user", "motd", nil, nil)
 
135
                        return ok
 
136
                },
 
137
        }
 
138
)
 
139
 
 
140
func init() {
 
141
        var err error
 
142
        rsaKey, err = ParsePrivateKey([]byte(testServerPrivateKey))
 
143
        if err != nil {
 
144
                panic("unable to set private key: " + err.Error())
 
145
        }
 
146
        rawDSAKey := new(dsa.PrivateKey)
 
147
 
 
148
        // taken from crypto/dsa/dsa_test.go
 
149
        rawDSAKey.P, _ = new(big.Int).SetString("A9B5B793FB4785793D246BAE77E8FF63CA52F442DA763C440259919FE1BC1D6065A9350637A04F75A2F039401D49F08E066C4D275A5A65DA5684BC563C14289D7AB8A67163BFBF79D85972619AD2CFF55AB0EE77A9002B0EF96293BDD0F42685EBB2C66C327079F6C98000FBCB79AACDE1BC6F9D5C7B1A97E3D9D54ED7951FEF", 16)
 
150
        rawDSAKey.Q, _ = new(big.Int).SetString("E1D3391245933D68A0714ED34BBCB7A1F422B9C1", 16)
 
151
        rawDSAKey.G, _ = new(big.Int).SetString("634364FC25248933D01D1993ECABD0657CC0CB2CEED7ED2E3E8AECDFCDC4A25C3B15E9E3B163ACA2984B5539181F3EFF1A5E8903D71D5B95DA4F27202B77D2C44B430BB53741A8D59A8F86887525C9F2A6A5980A195EAA7F2FF910064301DEF89D3AA213E1FAC7768D89365318E370AF54A112EFBA9246D9158386BA1B4EEFDA", 16)
 
152
        rawDSAKey.Y, _ = new(big.Int).SetString("32969E5780CFE1C849A1C276D7AEB4F38A23B591739AA2FE197349AEEBD31366AEE5EB7E6C6DDB7C57D02432B30DB5AA66D9884299FAA72568944E4EEDC92EA3FBC6F39F53412FBCC563208F7C15B737AC8910DBC2D9C9B8C001E72FDC40EB694AB1F06A5A2DBD18D9E36C66F31F566742F11EC0A52E9F7B89355C02FB5D32D2", 16)
 
153
        rawDSAKey.X, _ = new(big.Int).SetString("5078D4D29795CBE76D3AACFE48C9AF0BCDBEE91A", 16)
 
154
 
 
155
        dsaKey, err = NewSignerFromKey(rawDSAKey)
 
156
        if err != nil {
 
157
                panic("NewSignerFromKey: " + err.Error())
 
158
        }
 
159
        clientKeychain.add(rsaKey)
 
160
        serverConfig.AddHostKey(rsaKey)
 
161
}
 
162
 
 
163
// newMockAuthServer creates a new Server bound to
 
164
// the loopback interface. The server exits after
 
165
// processing one handshake.
 
166
func newMockAuthServer(t *testing.T) string {
 
167
        l, err := Listen("tcp", "127.0.0.1:0", serverConfig)
 
168
        if err != nil {
 
169
                t.Fatalf("unable to newMockAuthServer: %s", err)
 
170
        }
 
171
        go func() {
 
172
                defer l.Close()
 
173
                c, err := l.Accept()
 
174
                if err != nil {
 
175
                        t.Errorf("Unable to accept incoming connection: %v", err)
 
176
                        return
 
177
                }
 
178
                if err := c.Handshake(); err != nil {
 
179
                        // not Errorf because this is expected to
 
180
                        // fail for some tests.
 
181
                        t.Logf("Handshaking error: %v", err)
 
182
                        return
 
183
                }
 
184
                defer c.Close()
 
185
        }()
 
186
        return l.Addr().String()
 
187
}
 
188
 
 
189
func TestClientAuthPublicKey(t *testing.T) {
 
190
        config := &ClientConfig{
 
191
                User: "testuser",
 
192
                Auth: []ClientAuth{
 
193
                        ClientAuthKeyring(clientKeychain),
 
194
                },
 
195
        }
 
196
        c, err := Dial("tcp", newMockAuthServer(t), config)
 
197
        if err != nil {
 
198
                t.Fatalf("unable to dial remote side: %s", err)
 
199
        }
 
200
        c.Close()
 
201
}
 
202
 
 
203
func TestClientAuthPassword(t *testing.T) {
 
204
        config := &ClientConfig{
 
205
                User: "testuser",
 
206
                Auth: []ClientAuth{
 
207
                        ClientAuthPassword(clientPassword),
 
208
                },
 
209
        }
 
210
 
 
211
        c, err := Dial("tcp", newMockAuthServer(t), config)
 
212
        if err != nil {
 
213
                t.Fatalf("unable to dial remote side: %s", err)
 
214
        }
 
215
        c.Close()
 
216
}
 
217
 
 
218
func TestClientAuthWrongPassword(t *testing.T) {
 
219
        wrongPw := password("wrong")
 
220
        config := &ClientConfig{
 
221
                User: "testuser",
 
222
                Auth: []ClientAuth{
 
223
                        ClientAuthPassword(wrongPw),
 
224
                        ClientAuthKeyring(clientKeychain),
 
225
                },
 
226
        }
 
227
 
 
228
        c, err := Dial("tcp", newMockAuthServer(t), config)
 
229
        if err != nil {
 
230
                t.Fatalf("unable to dial remote side: %s", err)
 
231
        }
 
232
        c.Close()
 
233
}
 
234
 
 
235
func TestClientAuthKeyboardInteractive(t *testing.T) {
 
236
        answers := keyboardInteractive(map[string]string{
 
237
                "question1": "answer1",
 
238
                "question2": "answer2",
 
239
        })
 
240
        config := &ClientConfig{
 
241
                User: "testuser",
 
242
                Auth: []ClientAuth{
 
243
                        ClientAuthKeyboardInteractive(&answers),
 
244
                },
 
245
        }
 
246
 
 
247
        c, err := Dial("tcp", newMockAuthServer(t), config)
 
248
        if err != nil {
 
249
                t.Fatalf("unable to dial remote side: %s", err)
 
250
        }
 
251
        c.Close()
 
252
}
 
253
 
 
254
func TestClientAuthWrongKeyboardInteractive(t *testing.T) {
 
255
        answers := keyboardInteractive(map[string]string{
 
256
                "question1": "answer1",
 
257
                "question2": "WRONG",
 
258
        })
 
259
        config := &ClientConfig{
 
260
                User: "testuser",
 
261
                Auth: []ClientAuth{
 
262
                        ClientAuthKeyboardInteractive(&answers),
 
263
                },
 
264
        }
 
265
 
 
266
        c, err := Dial("tcp", newMockAuthServer(t), config)
 
267
        if err == nil {
 
268
                c.Close()
 
269
                t.Fatalf("wrong answers should not have authenticated with KeyboardInteractive")
 
270
        }
 
271
}
 
272
 
 
273
// the mock server will only authenticate ssh-rsa keys
 
274
func TestClientAuthInvalidPublicKey(t *testing.T) {
 
275
        kc := new(keychain)
 
276
 
 
277
        kc.add(dsaKey)
 
278
        config := &ClientConfig{
 
279
                User: "testuser",
 
280
                Auth: []ClientAuth{
 
281
                        ClientAuthKeyring(kc),
 
282
                },
 
283
        }
 
284
 
 
285
        c, err := Dial("tcp", newMockAuthServer(t), config)
 
286
        if err == nil {
 
287
                c.Close()
 
288
                t.Fatalf("dsa private key should not have authenticated with rsa public key")
 
289
        }
 
290
}
 
291
 
 
292
// the client should authenticate with the second key
 
293
func TestClientAuthRSAandDSA(t *testing.T) {
 
294
        kc := new(keychain)
 
295
        kc.add(dsaKey)
 
296
        kc.add(rsaKey)
 
297
        config := &ClientConfig{
 
298
                User: "testuser",
 
299
                Auth: []ClientAuth{
 
300
                        ClientAuthKeyring(kc),
 
301
                },
 
302
        }
 
303
        c, err := Dial("tcp", newMockAuthServer(t), config)
 
304
        if err != nil {
 
305
                t.Fatalf("client could not authenticate with rsa key: %v", err)
 
306
        }
 
307
        c.Close()
 
308
}
 
309
 
 
310
func TestClientHMAC(t *testing.T) {
 
311
        kc := new(keychain)
 
312
        kc.add(rsaKey)
 
313
        for _, mac := range DefaultMACOrder {
 
314
                config := &ClientConfig{
 
315
                        User: "testuser",
 
316
                        Auth: []ClientAuth{
 
317
                                ClientAuthKeyring(kc),
 
318
                        },
 
319
                        Crypto: CryptoConfig{
 
320
                                MACs: []string{mac},
 
321
                        },
 
322
                }
 
323
                c, err := Dial("tcp", newMockAuthServer(t), config)
 
324
                if err != nil {
 
325
                        t.Fatalf("client could not authenticate with mac algo %s: %v", mac, err)
 
326
                }
 
327
                c.Close()
 
328
        }
 
329
}
 
330
 
 
331
// issue 4285.
 
332
func TestClientUnsupportedCipher(t *testing.T) {
 
333
        kc := new(keychain)
 
334
        config := &ClientConfig{
 
335
                User: "testuser",
 
336
                Auth: []ClientAuth{
 
337
                        ClientAuthKeyring(kc),
 
338
                },
 
339
                Crypto: CryptoConfig{
 
340
                        Ciphers: []string{"aes128-cbc"}, // not currently supported
 
341
                },
 
342
        }
 
343
        c, err := Dial("tcp", newMockAuthServer(t), config)
 
344
        if err == nil {
 
345
                t.Errorf("expected no ciphers in common")
 
346
                c.Close()
 
347
        }
 
348
}
 
349
 
 
350
func TestClientUnsupportedKex(t *testing.T) {
 
351
        kc := new(keychain)
 
352
        config := &ClientConfig{
 
353
                User: "testuser",
 
354
                Auth: []ClientAuth{
 
355
                        ClientAuthKeyring(kc),
 
356
                },
 
357
                Crypto: CryptoConfig{
 
358
                        KeyExchanges: []string{"diffie-hellman-group-exchange-sha256"}, // not currently supported
 
359
                },
 
360
        }
 
361
        c, err := Dial("tcp", newMockAuthServer(t), config)
 
362
        if err == nil || !strings.Contains(err.Error(), "no common algorithms") {
 
363
                t.Errorf("got %v, expected 'no common algorithms'", err)
 
364
        }
 
365
        if c != nil {
 
366
                c.Close()
 
367
        }
 
368
}