Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(419)

Side by Side Diff: ssh/client_auth_test.go

Issue 13338044: code review 13338044: go.crypto/ssh: introduce PrivateKey method. (Closed)
Patch Set: diff -r c923f02daf74 https://code.google.com/p/go.crypto Created 10 years, 6 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | ssh/common.go » ('j') | ssh/server.go » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 The Go Authors. All rights reserved. 1 // Copyright 2011 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style 2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file. 3 // license that can be found in the LICENSE file.
4 4
5 package ssh 5 package ssh
6 6
7 import ( 7 import (
8 "bytes" 8 "bytes"
9 "crypto"
10 "crypto/dsa" 9 "crypto/dsa"
11 "crypto/rsa"
12 "crypto/x509"
13 "encoding/pem"
14 "errors"
15 "io" 10 "io"
16 "io/ioutil" 11 "io/ioutil"
17 "math/big" 12 "math/big"
18 "strings" 13 "strings"
19 "testing" 14 "testing"
20 15
21 _ "crypto/sha1" 16 _ "crypto/sha1"
22 ) 17 )
23 18
24 // private key for mock server 19 // private key for mock server
(...skipping 30 matching lines...) Expand all
55 r/ZwVaFzjWzxaf6zQIJbfaSEAhqD5yo72+sCAwEAAQJBAK8PEVU23Wj8mV0QjwcJ 50 r/ZwVaFzjWzxaf6zQIJbfaSEAhqD5yo72+sCAwEAAQJBAK8PEVU23Wj8mV0QjwcJ
56 tZ4GcTUYQL7cF4+ezTCE9a1NrGnCP2RuQkHEKxuTVrxXt+6OF15/1/fuXnxKjmJC 51 tZ4GcTUYQL7cF4+ezTCE9a1NrGnCP2RuQkHEKxuTVrxXt+6OF15/1/fuXnxKjmJC
57 nxkCIQDaXvPPBi0c7vAxGwNY9726x01/dNbHCE0CBtcotobxpwIhANbbQbh3JHVW 52 nxkCIQDaXvPPBi0c7vAxGwNY9726x01/dNbHCE0CBtcotobxpwIhANbbQbh3JHVW
58 2haQh4fAG5mhesZKAGcxTyv4mQ7uMSQdAiAj+4dzMpJWdSzQ+qGHlHMIBvVHLkqB 53 2haQh4fAG5mhesZKAGcxTyv4mQ7uMSQdAiAj+4dzMpJWdSzQ+qGHlHMIBvVHLkqB
59 y2VdEyF7DPCZewIhAI7GOI/6LDIFOvtPo6Bj2nNmyQ1HU6k/LRtNIXi4c9NJAiAr 54 y2VdEyF7DPCZewIhAI7GOI/6LDIFOvtPo6Bj2nNmyQ1HU6k/LRtNIXi4c9NJAiAr
60 rrxx26itVhJmcvoUhOjwuzSlP2bE5VHAvkGB352YBg== 55 rrxx26itVhJmcvoUhOjwuzSlP2bE5VHAvkGB352YBg==
61 -----END RSA PRIVATE KEY-----` 56 -----END RSA PRIVATE KEY-----`
62 57
63 // keychain implements the ClientKeyring interface 58 // keychain implements the ClientKeyring interface
64 type keychain struct { 59 type keychain struct {
65 » keys []interface{} 60 » keys []PrivateKey
66 } 61 }
67 62
68 func (k *keychain) Key(i int) (PublicKey, error) { 63 func (k *keychain) Key(i int) (PublicKey, error) {
69 if i < 0 || i >= len(k.keys) { 64 if i < 0 || i >= len(k.keys) {
70 return nil, nil 65 return nil, nil
71 } 66 }
72 » switch key := k.keys[i].(type) { 67
73 » case *rsa.PrivateKey: 68 » return k.keys[i].PublicKey(), nil
74 » » return NewRSAPublicKey(&key.PublicKey), nil
75 » case *dsa.PrivateKey:
76 » » return NewDSAPublicKey(&key.PublicKey), nil
77 » }
78 » panic("unknown key type")
79 } 69 }
80 70
81 func (k *keychain) Sign(i int, rand io.Reader, data []byte) (sig []byte, err err or) { 71 func (k *keychain) Sign(i int, rand io.Reader, data []byte) (sig []byte, err err or) {
82 » hashFunc := crypto.SHA1 72 » return k.keys[i].Sign(rand, data)
83 » h := hashFunc.New() 73 }
84 » h.Write(data) 74
85 » digest := h.Sum(nil) 75 func (k *keychain) add(key PrivateKey) {
86 » switch key := k.keys[i].(type) { 76 » k.keys = append(k.keys, key)
87 » case *rsa.PrivateKey:
88 » » return rsa.SignPKCS1v15(rand, key, hashFunc, digest)
89 » }
90 » return nil, errors.New("ssh: unknown key type")
91 } 77 }
92 78
93 func (k *keychain) loadPEM(file string) error { 79 func (k *keychain) loadPEM(file string) error {
94 buf, err := ioutil.ReadFile(file) 80 buf, err := ioutil.ReadFile(file)
95 if err != nil { 81 if err != nil {
96 return err 82 return err
97 } 83 }
98 » block, _ := pem.Decode(buf) 84 » key, err := ParsePrivateKey(buf)
99 » if block == nil {
100 » » return errors.New("ssh: no key found")
101 » }
102 » r, err := x509.ParsePKCS1PrivateKey(block.Bytes)
103 if err != nil { 85 if err != nil {
104 return err 86 return err
105 } 87 }
106 » k.keys = append(k.keys, r) 88 » k.add(key)
107 return nil 89 return nil
108 } 90 }
109 91
110 // password implements the ClientPassword interface 92 // password implements the ClientPassword interface
111 type password string 93 type password string
112 94
113 func (p password) Password(user string) (string, error) { 95 func (p password) Password(user string) (string, error) {
114 return string(p), nil 96 return string(p), nil
115 } 97 }
116 98
117 type keyboardInteractive map[string]string 99 type keyboardInteractive map[string]string
118 100
119 func (cr *keyboardInteractive) Challenge(user string, instruction string, questi ons []string, echos []bool) ([]string, error) { 101 func (cr *keyboardInteractive) Challenge(user string, instruction string, questi ons []string, echos []bool) ([]string, error) {
120 var answers []string 102 var answers []string
121 for _, q := range questions { 103 for _, q := range questions {
122 answers = append(answers, (*cr)[q]) 104 answers = append(answers, (*cr)[q])
123 } 105 }
124 return answers, nil 106 return answers, nil
125 } 107 }
126 108
127 // reused internally by tests 109 // reused internally by tests
128 var ( 110 var (
129 » rsakey *rsa.PrivateKey 111 » rsaKey PrivateKey
130 » dsakey *dsa.PrivateKey 112 » dsaKey PrivateKey
131 clientKeychain = new(keychain) 113 clientKeychain = new(keychain)
132 clientPassword = password("tiger") 114 clientPassword = password("tiger")
133 serverConfig = &ServerConfig{ 115 serverConfig = &ServerConfig{
134 PasswordCallback: func(conn *ServerConn, user, pass string) bool { 116 PasswordCallback: func(conn *ServerConn, user, pass string) bool {
135 return user == "testuser" && pass == string(clientPasswo rd) 117 return user == "testuser" && pass == string(clientPasswo rd)
136 }, 118 },
137 PublicKeyCallback: func(conn *ServerConn, user, algo string, pub key []byte) bool { 119 PublicKeyCallback: func(conn *ServerConn, user, algo string, pub key []byte) bool {
138 » » » rsaKey := &clientKeychain.keys[0].(*rsa.PrivateKey).Publ icKey 120 » » » key := clientKeychain.keys[0].PublicKey()
jpsugar 2013/09/17 16:57:21 clientKeychain.Key(0)
139 » » » key := NewRSAPublicKey(rsaKey)
140 expected := MarshalPublicKey(key) 121 expected := MarshalPublicKey(key)
141 algoname := key.PublicKeyAlgo() 122 algoname := key.PublicKeyAlgo()
142 return user == "testuser" && algo == algoname && bytes.E qual(pubkey, expected) 123 return user == "testuser" && algo == algoname && bytes.E qual(pubkey, expected)
143 }, 124 },
144 KeyboardInteractiveCallback: func(conn *ServerConn, user string, client ClientKeyboardInteractive) bool { 125 KeyboardInteractiveCallback: func(conn *ServerConn, user string, client ClientKeyboardInteractive) bool {
145 ans, err := client.Challenge("user", 126 ans, err := client.Challenge("user",
146 "instruction", 127 "instruction",
147 []string{"question1", "question2"}, 128 []string{"question1", "question2"},
148 []bool{true, true}) 129 []bool{true, true})
149 if err != nil { 130 if err != nil {
150 return false 131 return false
151 } 132 }
152 ok := user == "testuser" && ans[0] == "answer1" && ans[1 ] == "answer2" 133 ok := user == "testuser" && ans[0] == "answer1" && ans[1 ] == "answer2"
153 client.Challenge("user", "motd", nil, nil) 134 client.Challenge("user", "motd", nil, nil)
154 return ok 135 return ok
155 }, 136 },
156 } 137 }
157 ) 138 )
158 139
159 func init() { 140 func init() {
160 » if err := serverConfig.SetRSAPrivateKey([]byte(testServerPrivateKey)); e rr != nil { 141 » var err error
142 » rsaKey, err = ParsePrivateKey([]byte(testServerPrivateKey))
143 » if err != nil {
161 panic("unable to set private key: " + err.Error()) 144 panic("unable to set private key: " + err.Error())
162 } 145 }
146 rawDSAKey := new(dsa.PrivateKey)
163 147
164 » block, _ := pem.Decode([]byte(testClientPrivateKey)) 148 » // taken from crypto/dsa/dsa_test.go
165 » rsakey, _ = x509.ParsePKCS1PrivateKey(block.Bytes) 149 » rawDSAKey.P, _ = new(big.Int).SetString("A9B5B793FB4785793D246BAE77E8FF6 3CA52F442DA763C440259919FE1BC1D6065A9350637A04F75A2F039401D49F08E066C4D275A5A65D A5684BC563C14289D7AB8A67163BFBF79D85972619AD2CFF55AB0EE77A9002B0EF96293BDD0F4268 5EBB2C66C327079F6C98000FBCB79AACDE1BC6F9D5C7B1A97E3D9D54ED7951FEF", 16)
150 » rawDSAKey.Q, _ = new(big.Int).SetString("E1D3391245933D68A0714ED34BBCB7A 1F422B9C1", 16)
151 » rawDSAKey.G, _ = new(big.Int).SetString("634364FC25248933D01D1993ECABD06 57CC0CB2CEED7ED2E3E8AECDFCDC4A25C3B15E9E3B163ACA2984B5539181F3EFF1A5E8903D71D5B9 5DA4F27202B77D2C44B430BB53741A8D59A8F86887525C9F2A6A5980A195EAA7F2FF910064301DEF 89D3AA213E1FAC7768D89365318E370AF54A112EFBA9246D9158386BA1B4EEFDA", 16)
152 » rawDSAKey.Y, _ = new(big.Int).SetString("32969E5780CFE1C849A1C276D7AEB4F 38A23B591739AA2FE197349AEEBD31366AEE5EB7E6C6DDB7C57D02432B30DB5AA66D9884299FAA72 568944E4EEDC92EA3FBC6F39F53412FBCC563208F7C15B737AC8910DBC2D9C9B8C001E72FDC40EB6 94AB1F06A5A2DBD18D9E36C66F31F566742F11EC0A52E9F7B89355C02FB5D32D2", 16)
153 » rawDSAKey.X, _ = new(big.Int).SetString("5078D4D29795CBE76D3AACFE48C9AF0 BCDBEE91A", 16)
166 154
167 » clientKeychain.keys = append(clientKeychain.keys, rsakey) 155 » dsaKey, err = NewPrivateKey(rawDSAKey)
168 » dsakey = new(dsa.PrivateKey) 156 » if err != nil {
169 » // taken from crypto/dsa/dsa_test.go 157 » » panic("NewPrivateKey: " + err.Error())
170 » dsakey.P, _ = new(big.Int).SetString("A9B5B793FB4785793D246BAE77E8FF63CA 52F442DA763C440259919FE1BC1D6065A9350637A04F75A2F039401D49F08E066C4D275A5A65DA56 84BC563C14289D7AB8A67163BFBF79D85972619AD2CFF55AB0EE77A9002B0EF96293BDD0F42685EB B2C66C327079F6C98000FBCB79AACDE1BC6F9D5C7B1A97E3D9D54ED7951FEF", 16) 158 » }
171 » dsakey.Q, _ = new(big.Int).SetString("E1D3391245933D68A0714ED34BBCB7A1F4 22B9C1", 16) 159 » clientKeychain.add(rsaKey)
172 » dsakey.G, _ = new(big.Int).SetString("634364FC25248933D01D1993ECABD0657C C0CB2CEED7ED2E3E8AECDFCDC4A25C3B15E9E3B163ACA2984B5539181F3EFF1A5E8903D71D5B95DA 4F27202B77D2C44B430BB53741A8D59A8F86887525C9F2A6A5980A195EAA7F2FF910064301DEF89D 3AA213E1FAC7768D89365318E370AF54A112EFBA9246D9158386BA1B4EEFDA", 16) 160 » serverConfig.AddHostKey(rsaKey)
173 » dsakey.Y, _ = new(big.Int).SetString("32969E5780CFE1C849A1C276D7AEB4F38A 23B591739AA2FE197349AEEBD31366AEE5EB7E6C6DDB7C57D02432B30DB5AA66D9884299FAA72568 944E4EEDC92EA3FBC6F39F53412FBCC563208F7C15B737AC8910DBC2D9C9B8C001E72FDC40EB694A B1F06A5A2DBD18D9E36C66F31F566742F11EC0A52E9F7B89355C02FB5D32D2", 16)
174 » dsakey.X, _ = new(big.Int).SetString("5078D4D29795CBE76D3AACFE48C9AF0BCD BEE91A", 16)
175 } 161 }
176 162
177 // newMockAuthServer creates a new Server bound to 163 // newMockAuthServer creates a new Server bound to
178 // the loopback interface. The server exits after 164 // the loopback interface. The server exits after
179 // processing one handshake. 165 // processing one handshake.
180 func newMockAuthServer(t *testing.T) string { 166 func newMockAuthServer(t *testing.T) string {
181 l, err := Listen("tcp", "127.0.0.1:0", serverConfig) 167 l, err := Listen("tcp", "127.0.0.1:0", serverConfig)
182 if err != nil { 168 if err != nil {
183 t.Fatalf("unable to newMockAuthServer: %s", err) 169 t.Fatalf("unable to newMockAuthServer: %s", err)
184 } 170 }
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
280 c, err := Dial("tcp", newMockAuthServer(t), config) 266 c, err := Dial("tcp", newMockAuthServer(t), config)
281 if err == nil { 267 if err == nil {
282 c.Close() 268 c.Close()
283 t.Fatalf("wrong answers should not have authenticated with Keybo ardInteractive") 269 t.Fatalf("wrong answers should not have authenticated with Keybo ardInteractive")
284 } 270 }
285 } 271 }
286 272
287 // the mock server will only authenticate ssh-rsa keys 273 // the mock server will only authenticate ssh-rsa keys
288 func TestClientAuthInvalidPublicKey(t *testing.T) { 274 func TestClientAuthInvalidPublicKey(t *testing.T) {
289 kc := new(keychain) 275 kc := new(keychain)
290 » kc.keys = append(kc.keys, dsakey) 276
277 » kc.add(dsaKey)
291 config := &ClientConfig{ 278 config := &ClientConfig{
292 User: "testuser", 279 User: "testuser",
293 Auth: []ClientAuth{ 280 Auth: []ClientAuth{
294 ClientAuthKeyring(kc), 281 ClientAuthKeyring(kc),
295 }, 282 },
296 } 283 }
297 284
298 c, err := Dial("tcp", newMockAuthServer(t), config) 285 c, err := Dial("tcp", newMockAuthServer(t), config)
299 if err == nil { 286 if err == nil {
300 c.Close() 287 c.Close()
301 t.Fatalf("dsa private key should not have authenticated with rsa public key") 288 t.Fatalf("dsa private key should not have authenticated with rsa public key")
302 } 289 }
303 } 290 }
304 291
305 // the client should authenticate with the second key 292 // the client should authenticate with the second key
306 func TestClientAuthRSAandDSA(t *testing.T) { 293 func TestClientAuthRSAandDSA(t *testing.T) {
307 kc := new(keychain) 294 kc := new(keychain)
308 » kc.keys = append(kc.keys, dsakey, rsakey) 295 » kc.add(dsaKey)
296 » kc.add(rsaKey)
309 config := &ClientConfig{ 297 config := &ClientConfig{
310 User: "testuser", 298 User: "testuser",
311 Auth: []ClientAuth{ 299 Auth: []ClientAuth{
312 ClientAuthKeyring(kc), 300 ClientAuthKeyring(kc),
313 }, 301 },
314 } 302 }
315 c, err := Dial("tcp", newMockAuthServer(t), config) 303 c, err := Dial("tcp", newMockAuthServer(t), config)
316 if err != nil { 304 if err != nil {
317 t.Fatalf("client could not authenticate with rsa key: %v", err) 305 t.Fatalf("client could not authenticate with rsa key: %v", err)
318 } 306 }
319 c.Close() 307 c.Close()
320 } 308 }
321 309
322 func TestClientHMAC(t *testing.T) { 310 func TestClientHMAC(t *testing.T) {
323 kc := new(keychain) 311 kc := new(keychain)
324 » kc.keys = append(kc.keys, rsakey) 312 » kc.add(rsaKey)
325 for _, mac := range DefaultMACOrder { 313 for _, mac := range DefaultMACOrder {
326 config := &ClientConfig{ 314 config := &ClientConfig{
327 User: "testuser", 315 User: "testuser",
328 Auth: []ClientAuth{ 316 Auth: []ClientAuth{
329 ClientAuthKeyring(kc), 317 ClientAuthKeyring(kc),
330 }, 318 },
331 Crypto: CryptoConfig{ 319 Crypto: CryptoConfig{
332 MACs: []string{mac}, 320 MACs: []string{mac},
333 }, 321 },
334 } 322 }
335 c, err := Dial("tcp", newMockAuthServer(t), config) 323 c, err := Dial("tcp", newMockAuthServer(t), config)
336 if err != nil { 324 if err != nil {
337 t.Fatalf("client could not authenticate with mac algo %s : %v", mac, err) 325 t.Fatalf("client could not authenticate with mac algo %s : %v", mac, err)
338 } 326 }
339 c.Close() 327 c.Close()
340 } 328 }
341 } 329 }
342 330
343 // issue 4285. 331 // issue 4285.
344 func TestClientUnsupportedCipher(t *testing.T) { 332 func TestClientUnsupportedCipher(t *testing.T) {
345 kc := new(keychain) 333 kc := new(keychain)
346 kc.keys = append(kc.keys, rsakey)
347 config := &ClientConfig{ 334 config := &ClientConfig{
348 User: "testuser", 335 User: "testuser",
349 Auth: []ClientAuth{ 336 Auth: []ClientAuth{
350 ClientAuthKeyring(kc), 337 ClientAuthKeyring(kc),
351 }, 338 },
352 Crypto: CryptoConfig{ 339 Crypto: CryptoConfig{
353 Ciphers: []string{"aes128-cbc"}, // not currently suppor ted 340 Ciphers: []string{"aes128-cbc"}, // not currently suppor ted
354 }, 341 },
355 } 342 }
356 c, err := Dial("tcp", newMockAuthServer(t), config) 343 c, err := Dial("tcp", newMockAuthServer(t), config)
357 if err == nil { 344 if err == nil {
358 t.Errorf("expected no ciphers in common") 345 t.Errorf("expected no ciphers in common")
359 c.Close() 346 c.Close()
360 } 347 }
361 } 348 }
362 349
363 func TestClientUnsupportedKex(t *testing.T) { 350 func TestClientUnsupportedKex(t *testing.T) {
364 kc := new(keychain) 351 kc := new(keychain)
365 kc.keys = append(kc.keys, rsakey)
366 config := &ClientConfig{ 352 config := &ClientConfig{
367 User: "testuser", 353 User: "testuser",
368 Auth: []ClientAuth{ 354 Auth: []ClientAuth{
369 ClientAuthKeyring(kc), 355 ClientAuthKeyring(kc),
370 }, 356 },
371 Crypto: CryptoConfig{ 357 Crypto: CryptoConfig{
372 KeyExchanges: []string{"diffie-hellman-group-exchange-sh a256"}, // not currently supported 358 KeyExchanges: []string{"diffie-hellman-group-exchange-sh a256"}, // not currently supported
373 }, 359 },
374 } 360 }
375 c, err := Dial("tcp", newMockAuthServer(t), config) 361 c, err := Dial("tcp", newMockAuthServer(t), config)
376 if err == nil || !strings.Contains(err.Error(), "no common algorithms") { 362 if err == nil || !strings.Contains(err.Error(), "no common algorithms") {
377 t.Errorf("got %v, expected 'no common algorithms'", err) 363 t.Errorf("got %v, expected 'no common algorithms'", err)
378 c.Close() 364 c.Close()
379 } 365 }
380 } 366 }
OLDNEW
« no previous file with comments | « no previous file | ssh/common.go » ('j') | ssh/server.go » ('J')

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b