LEFT | RIGHT |
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" | 9 "crypto" |
10 "crypto/ecdsa" | 10 "crypto/ecdsa" |
11 "crypto/elliptic" | 11 "crypto/elliptic" |
12 "crypto/rand" | 12 "crypto/rand" |
13 "encoding/binary" | 13 "encoding/binary" |
14 "errors" | 14 "errors" |
15 "io" | 15 "io" |
16 "math/big" | 16 "math/big" |
17 "net" | 17 "net" |
18 "sync" | 18 "sync" |
19 | 19 |
20 _ "crypto/sha1" | 20 _ "crypto/sha1" |
21 ) | 21 ) |
22 | 22 |
23 type ServerConfig struct { | 23 type ServerConfig struct { |
24 » hostKeys []PrivateKey | 24 » hostKeys []Signer |
25 | 25 |
26 // Rand provides the source of entropy for key exchange. If Rand is | 26 // Rand provides the source of entropy for key exchange. If Rand is |
27 // nil, the cryptographic random reader in package crypto/rand will | 27 // nil, the cryptographic random reader in package crypto/rand will |
28 // be used. | 28 // be used. |
29 Rand io.Reader | 29 Rand io.Reader |
30 | 30 |
31 // NoClientAuth is true if clients are allowed to connect without | 31 // NoClientAuth is true if clients are allowed to connect without |
32 // authenticating. | 32 // authenticating. |
33 NoClientAuth bool | 33 NoClientAuth bool |
34 | 34 |
(...skipping 22 matching lines...) Expand all Loading... |
57 | 57 |
58 func (c *ServerConfig) rand() io.Reader { | 58 func (c *ServerConfig) rand() io.Reader { |
59 if c.Rand == nil { | 59 if c.Rand == nil { |
60 return rand.Reader | 60 return rand.Reader |
61 } | 61 } |
62 return c.Rand | 62 return c.Rand |
63 } | 63 } |
64 | 64 |
65 // AddHostKey adds a private key as a host key. If an existing host | 65 // AddHostKey adds a private key as a host key. If an existing host |
66 // key exists with the same algorithm, it is overwritten. | 66 // key exists with the same algorithm, it is overwritten. |
67 func (s *ServerConfig) AddHostKey(key PrivateKey) { | 67 func (s *ServerConfig) AddHostKey(key Signer) { |
68 for i, k := range s.hostKeys { | 68 for i, k := range s.hostKeys { |
69 » » if k.PublicKey().PrivateKeyAlgo() == key.PublicKey().PrivateKeyA
lgo() { | 69 » » if k.PublicKey().PublicKeyAlgo() == key.PublicKey().PublicKeyAlg
o() { |
70 s.hostKeys[i] = key | 70 s.hostKeys[i] = key |
71 return | 71 return |
72 } | 72 } |
73 } | 73 } |
74 | 74 |
75 s.hostKeys = append(s.hostKeys, key) | 75 s.hostKeys = append(s.hostKeys, key) |
76 } | 76 } |
77 | 77 |
78 // SetRSAPrivateKey sets the private key for a Server. A Server must have a | 78 // SetRSAPrivateKey sets the private key for a Server. A Server must have a |
79 // private key configured in order to accept connections. The private key must | 79 // private key configured in order to accept connections. The private key must |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
135 func Server(c net.Conn, config *ServerConfig) *ServerConn { | 135 func Server(c net.Conn, config *ServerConfig) *ServerConn { |
136 return &ServerConn{ | 136 return &ServerConn{ |
137 transport: newTransport(c, config.rand()), | 137 transport: newTransport(c, config.rand()), |
138 channels: make(map[uint32]*serverChan), | 138 channels: make(map[uint32]*serverChan), |
139 config: config, | 139 config: config, |
140 } | 140 } |
141 } | 141 } |
142 | 142 |
143 // kexECDH performs Elliptic Curve Diffie-Hellman key agreement on a | 143 // kexECDH performs Elliptic Curve Diffie-Hellman key agreement on a |
144 // ServerConnection, as documented in RFC 5656, section 4. | 144 // ServerConnection, as documented in RFC 5656, section 4. |
145 func (s *ServerConn) kexECDH(curve elliptic.Curve, magics *handshakeMagics, priv
PrivateKey) (result *kexResult, err error) { | 145 func (s *ServerConn) kexECDH(curve elliptic.Curve, magics *handshakeMagics, priv
Signer) (result *kexResult, err error) { |
146 packet, err := s.readPacket() | 146 packet, err := s.readPacket() |
147 if err != nil { | 147 if err != nil { |
148 return | 148 return |
149 } | 149 } |
150 | 150 |
151 var kexECDHInit kexECDHInitMsg | 151 var kexECDHInit kexECDHInitMsg |
152 if err = unmarshal(&kexECDHInit, packet, msgKexECDHInit); err != nil { | 152 if err = unmarshal(&kexECDHInit, packet, msgKexECDHInit); err != nil { |
153 return | 153 return |
154 } | 154 } |
155 | 155 |
(...skipping 30 matching lines...) Expand all Loading... |
186 writeString(h, hostKeyBytes) | 186 writeString(h, hostKeyBytes) |
187 writeString(h, kexECDHInit.ClientPubKey) | 187 writeString(h, kexECDHInit.ClientPubKey) |
188 writeString(h, serializedEphKey) | 188 writeString(h, serializedEphKey) |
189 | 189 |
190 K := make([]byte, intLength(secret)) | 190 K := make([]byte, intLength(secret)) |
191 marshalInt(K, secret) | 191 marshalInt(K, secret) |
192 h.Write(K) | 192 h.Write(K) |
193 | 193 |
194 H := h.Sum(nil) | 194 H := h.Sum(nil) |
195 | 195 |
196 » // H is already a dash, but the hostkey signing will apply its | 196 » // H is already a hash, but the hostkey signing will apply its |
197 // own key specific hash algorithm. | 197 // own key specific hash algorithm. |
198 » sig, err := MarshaledSignature(priv, s.config.rand(), H) | 198 » sig, err := signAndMarshal(priv, s.config.rand(), H) |
199 if err != nil { | 199 if err != nil { |
200 return nil, err | 200 return nil, err |
201 } | 201 } |
202 | 202 |
203 reply := kexECDHReplyMsg{ | 203 reply := kexECDHReplyMsg{ |
204 EphemeralPubKey: serializedEphKey, | 204 EphemeralPubKey: serializedEphKey, |
205 HostKey: hostKeyBytes, | 205 HostKey: hostKeyBytes, |
206 Signature: sig, | 206 Signature: sig, |
207 } | 207 } |
208 | 208 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
243 // - the NIST curves have cofactor = 1, so this is implicit. | 243 // - the NIST curves have cofactor = 1, so this is implicit. |
244 // (We don't forsee an implementation that supports non NIST | 244 // (We don't forsee an implementation that supports non NIST |
245 // curves) | 245 // curves) |
246 // | 246 // |
247 // - for ephemeral keys, we don't need to worry about small | 247 // - for ephemeral keys, we don't need to worry about small |
248 // subgroup attacks. | 248 // subgroup attacks. |
249 return true | 249 return true |
250 } | 250 } |
251 | 251 |
252 // kexDH performs Diffie-Hellman key agreement on a ServerConnection. | 252 // kexDH performs Diffie-Hellman key agreement on a ServerConnection. |
253 func (s *ServerConn) kexDH(group *dhGroup, hashFunc crypto.Hash, magics *handsha
keMagics, priv PrivateKey) (result *kexResult, err error) { | 253 func (s *ServerConn) kexDH(group *dhGroup, hashFunc crypto.Hash, magics *handsha
keMagics, priv Signer) (result *kexResult, err error) { |
254 packet, err := s.readPacket() | 254 packet, err := s.readPacket() |
255 if err != nil { | 255 if err != nil { |
256 return | 256 return |
257 } | 257 } |
258 var kexDHInit kexDHInitMsg | 258 var kexDHInit kexDHInitMsg |
259 if err = unmarshal(&kexDHInit, packet, msgKexDHInit); err != nil { | 259 if err = unmarshal(&kexDHInit, packet, msgKexDHInit); err != nil { |
260 return | 260 return |
261 } | 261 } |
262 | 262 |
263 y, err := rand.Int(s.config.rand(), group.p) | 263 y, err := rand.Int(s.config.rand(), group.p) |
(...skipping 17 matching lines...) Expand all Loading... |
281 writeString(h, hostKeyBytes) | 281 writeString(h, hostKeyBytes) |
282 writeInt(h, kexDHInit.X) | 282 writeInt(h, kexDHInit.X) |
283 writeInt(h, Y) | 283 writeInt(h, Y) |
284 | 284 |
285 K := make([]byte, intLength(kInt)) | 285 K := make([]byte, intLength(kInt)) |
286 marshalInt(K, kInt) | 286 marshalInt(K, kInt) |
287 h.Write(K) | 287 h.Write(K) |
288 | 288 |
289 H := h.Sum(nil) | 289 H := h.Sum(nil) |
290 | 290 |
291 » // H is already a dash, but the hostkey signing will apply its | 291 » // H is already a hash, but the hostkey signing will apply its |
292 // own key specific hash algorithm. | 292 // own key specific hash algorithm. |
293 » sig, err := MarshaledSignature(priv, s.config.rand(), H) | 293 » sig, err := signAndMarshal(priv, s.config.rand(), H) |
294 if err != nil { | 294 if err != nil { |
295 return nil, err | 295 return nil, err |
296 } | 296 } |
297 | 297 |
298 kexDHReply := kexDHReplyMsg{ | 298 kexDHReply := kexDHReplyMsg{ |
299 HostKey: hostKeyBytes, | 299 HostKey: hostKeyBytes, |
300 Y: Y, | 300 Y: Y, |
301 Signature: sig, | 301 Signature: sig, |
302 } | 302 } |
303 packet = marshal(msgKexDHReply, kexDHReply) | 303 packet = marshal(msgKexDHReply, kexDHReply) |
304 | 304 |
305 err = s.writePacket(packet) | 305 err = s.writePacket(packet) |
306 return &kexResult{ | 306 return &kexResult{ |
307 H: H, | 307 H: H, |
308 K: K, | 308 K: K, |
309 HostKey: hostKeyBytes, | 309 HostKey: hostKeyBytes, |
310 Hash: hashFunc, | 310 Hash: hashFunc, |
311 }, nil | 311 }, nil |
312 } | 312 } |
313 | 313 |
314 // MarshaledSignature signs the data with the appropriate algorithm, | 314 // signAndMarshal signs the data with the appropriate algorithm, |
315 // and serializes the result in SSH wire format. | 315 // and serializes the result in SSH wire format. |
316 func MarshaledSignature(k PrivateKey, rand io.Reader, data []byte) ([]byte, erro
r) { | 316 func signAndMarshal(k Signer, rand io.Reader, data []byte) ([]byte, error) { |
317 sig, err := k.Sign(rand, data) | 317 sig, err := k.Sign(rand, data) |
318 if err != nil { | 318 if err != nil { |
319 return nil, err | 319 return nil, err |
320 } | 320 } |
321 | 321 |
322 return serializeSignature(k.PublicKey().PrivateKeyAlgo(), sig), nil | 322 return serializeSignature(k.PublicKey().PrivateKeyAlgo(), sig), nil |
323 } | 323 } |
324 | 324 |
325 // serverVersion is the fixed identification string that Server will use. | 325 // serverVersion is the fixed identification string that Server will use. |
326 var serverVersion = []byte("SSH-2.0-Go\r\n") | 326 var serverVersion = []byte("SSH-2.0-Go\r\n") |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
369 func (s *ServerConn) clientInitHandshake(clientKexInit *kexInitMsg, clientKexIni
tPacket []byte) (err error) { | 369 func (s *ServerConn) clientInitHandshake(clientKexInit *kexInitMsg, clientKexIni
tPacket []byte) (err error) { |
370 serverKexInit := kexInitMsg{ | 370 serverKexInit := kexInitMsg{ |
371 KexAlgos: s.config.Crypto.kexes(), | 371 KexAlgos: s.config.Crypto.kexes(), |
372 CiphersClientServer: s.config.Crypto.ciphers(), | 372 CiphersClientServer: s.config.Crypto.ciphers(), |
373 CiphersServerClient: s.config.Crypto.ciphers(), | 373 CiphersServerClient: s.config.Crypto.ciphers(), |
374 MACsClientServer: s.config.Crypto.macs(), | 374 MACsClientServer: s.config.Crypto.macs(), |
375 MACsServerClient: s.config.Crypto.macs(), | 375 MACsServerClient: s.config.Crypto.macs(), |
376 CompressionClientServer: supportedCompressions, | 376 CompressionClientServer: supportedCompressions, |
377 CompressionServerClient: supportedCompressions, | 377 CompressionServerClient: supportedCompressions, |
378 } | 378 } |
379 // algo => key. | |
380 hostKeys := map[string]PrivateKey{} | |
381 for _, k := range s.config.hostKeys { | 379 for _, k := range s.config.hostKeys { |
382 serverKexInit.ServerHostKeyAlgos = append( | 380 serverKexInit.ServerHostKeyAlgos = append( |
383 » » » serverKexInit.ServerHostKeyAlgos, k.PublicKey().PrivateK
eyAlgo()) | 381 » » » serverKexInit.ServerHostKeyAlgos, k.PublicKey().PublicKe
yAlgo()) |
384 » » hostKeys[k.PublicKey().PrivateKeyAlgo()] = k | |
385 } | 382 } |
386 | 383 |
387 serverKexInitPacket := marshal(msgKexInit, serverKexInit) | 384 serverKexInitPacket := marshal(msgKexInit, serverKexInit) |
388 if err = s.writePacket(serverKexInitPacket); err != nil { | 385 if err = s.writePacket(serverKexInitPacket); err != nil { |
389 return | 386 return |
390 } | 387 } |
391 | 388 |
392 if clientKexInitPacket == nil { | 389 if clientKexInitPacket == nil { |
393 clientKexInit = new(kexInitMsg) | 390 clientKexInit = new(kexInitMsg) |
394 if clientKexInitPacket, err = s.readPacket(); err != nil { | 391 if clientKexInitPacket, err = s.readPacket(); err != nil { |
395 return | 392 return |
396 } | 393 } |
397 if err = unmarshal(clientKexInit, clientKexInitPacket, msgKexIni
t); err != nil { | 394 if err = unmarshal(clientKexInit, clientKexInitPacket, msgKexIni
t); err != nil { |
398 return | 395 return |
399 } | 396 } |
400 } | 397 } |
401 | 398 |
402 kexAlgo, hostKeyAlgo, ok := findAgreedAlgorithms(s.transport, clientKexI
nit, &serverKexInit) | 399 kexAlgo, hostKeyAlgo, ok := findAgreedAlgorithms(s.transport, clientKexI
nit, &serverKexInit) |
403 if !ok { | 400 if !ok { |
404 return errors.New("ssh: no common algorithms") | 401 return errors.New("ssh: no common algorithms") |
405 } | 402 } |
406 if clientKexInit.FirstKexFollows && kexAlgo != clientKexInit.KexAlgos[0]
{ | 403 if clientKexInit.FirstKexFollows && kexAlgo != clientKexInit.KexAlgos[0]
{ |
407 // The client sent a Kex message for the wrong algorithm, | 404 // The client sent a Kex message for the wrong algorithm, |
408 // which we have to ignore. | 405 // which we have to ignore. |
409 if _, err = s.readPacket(); err != nil { | 406 if _, err = s.readPacket(); err != nil { |
410 return | 407 return |
411 } | 408 } |
412 } | 409 } |
413 | 410 |
414 » hostKey := hostKeys[hostKeyAlgo] | 411 » var hostKey Signer |
| 412 » for _, k := range s.config.hostKeys { |
| 413 » » if hostKeyAlgo == k.PublicKey().PublicKeyAlgo() { |
| 414 » » » hostKey = k |
| 415 » » } |
| 416 » } |
415 | 417 |
416 var magics handshakeMagics | 418 var magics handshakeMagics |
417 magics.serverVersion = serverVersion[:len(serverVersion)-2] | 419 magics.serverVersion = serverVersion[:len(serverVersion)-2] |
418 magics.clientVersion = s.ClientVersion | 420 magics.clientVersion = s.ClientVersion |
419 magics.serverKexInit = marshal(msgKexInit, serverKexInit) | 421 magics.serverKexInit = marshal(msgKexInit, serverKexInit) |
420 magics.clientKexInit = clientKexInitPacket | 422 magics.clientKexInit = clientKexInitPacket |
421 | 423 |
422 var result *kexResult | 424 var result *kexResult |
423 switch kexAlgo { | 425 switch kexAlgo { |
424 case kexAlgoECDH256: | 426 case kexAlgoECDH256: |
(...skipping 450 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
875 func Listen(network, addr string, config *ServerConfig) (*Listener, error) { | 877 func Listen(network, addr string, config *ServerConfig) (*Listener, error) { |
876 l, err := net.Listen(network, addr) | 878 l, err := net.Listen(network, addr) |
877 if err != nil { | 879 if err != nil { |
878 return nil, err | 880 return nil, err |
879 } | 881 } |
880 return &Listener{ | 882 return &Listener{ |
881 l, | 883 l, |
882 config, | 884 config, |
883 }, nil | 885 }, nil |
884 } | 886 } |
LEFT | RIGHT |