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

Side by Side Diff: ssh/server.go

Issue 14494058: code review 14494058: go.crypto/ssh: support rekeying in both directions. (Closed)
Patch Set: diff -r cd1eea1eb828 https://code.google.com/p/go.crypto Created 10 years, 5 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
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/rand" 9 "crypto/rand"
10 "encoding/binary" 10 "encoding/binary"
11 "errors" 11 "errors"
12 "fmt"
13 "io" 12 "io"
14 "net" 13 "net"
15 "sync" 14 "sync"
16 15
17 _ "crypto/sha1" 16 _ "crypto/sha1"
18 ) 17 )
19 18
20 type ServerConfig struct { 19 type ServerConfig struct {
21 hostKeys []Signer 20 hostKeys []Signer
22 21
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
90 type cachedPubKey struct { 89 type cachedPubKey struct {
91 user, algo string 90 user, algo string
92 pubKey []byte 91 pubKey []byte
93 result bool 92 result bool
94 } 93 }
95 94
96 const maxCachedPubKeys = 16 95 const maxCachedPubKeys = 16
97 96
98 // A ServerConn represents an incoming connection. 97 // A ServerConn represents an incoming connection.
99 type ServerConn struct { 98 type ServerConn struct {
100 » transport *transport 99 » transport *handshakeTransport
101 config *ServerConfig 100 config *ServerConfig
101 sshConn
102 102
103 channels map[uint32]*serverChan 103 channels map[uint32]*serverChan
104 nextChanId uint32 104 nextChanId uint32
105 105
106 // lock protects err and channels. 106 // lock protects err and channels.
107 lock sync.Mutex 107 lock sync.Mutex
108 err error 108 err error
109 109
110 // cachedPubKeys contains the cache results of tests for public keys. 110 // cachedPubKeys contains the cache results of tests for public keys.
111 // Since SSH clients will query whether a public key is acceptable 111 // Since SSH clients will query whether a public key is acceptable
(...skipping 11 matching lines...) Expand all
123 ClientVersion []byte 123 ClientVersion []byte
124 124
125 // Our version. 125 // Our version.
126 serverVersion []byte 126 serverVersion []byte
127 } 127 }
128 128
129 // Server returns a new SSH server connection 129 // Server returns a new SSH server connection
130 // using c as the underlying transport. 130 // using c as the underlying transport.
131 func Server(c net.Conn, config *ServerConfig) *ServerConn { 131 func Server(c net.Conn, config *ServerConfig) *ServerConn {
132 return &ServerConn{ 132 return &ServerConn{
133 » » transport: newTransport(c, config.rand(), false /* not client */ ), 133 » » sshConn: sshConn{c, c},
134 » » channels: make(map[uint32]*serverChan), 134 » » channels: make(map[uint32]*serverChan),
135 » » config: config, 135 » » config: config,
136 } 136 }
137 } 137 }
138 138
139 // signAndMarshal signs the data with the appropriate algorithm, 139 // signAndMarshal signs the data with the appropriate algorithm,
140 // and serializes the result in SSH wire format. 140 // and serializes the result in SSH wire format.
141 func signAndMarshal(k Signer, rand io.Reader, data []byte) ([]byte, error) { 141 func signAndMarshal(k Signer, rand io.Reader, data []byte) ([]byte, error) {
142 sig, err := k.Sign(rand, data) 142 sig, err := k.Sign(rand, data)
143 if err != nil { 143 if err != nil {
144 return nil, err 144 return nil, err
145 } 145 }
146 146
147 return serializeSignature(k.PublicKey().PrivateKeyAlgo(), sig), nil 147 return serializeSignature(k.PublicKey().PrivateKeyAlgo(), sig), nil
148 } 148 }
149 149
150 // Close closes the connection.
151 func (s *ServerConn) Close() error { return s.transport.Close() }
152
153 // LocalAddr returns the local network address.
154 func (c *ServerConn) LocalAddr() net.Addr { return c.transport.LocalAddr() }
155
156 // RemoteAddr returns the remote network address.
157 func (c *ServerConn) RemoteAddr() net.Addr { return c.transport.RemoteAddr() }
158
159 // Handshake performs an SSH transport and client authentication on the given Se rverConn. 150 // Handshake performs an SSH transport and client authentication on the given Se rverConn.
160 func (s *ServerConn) Handshake() error { 151 func (s *ServerConn) Handshake() error {
161 var err error 152 var err error
162 s.serverVersion = []byte(packageVersion) 153 s.serverVersion = []byte(packageVersion)
163 » s.ClientVersion, err = exchangeVersions(s.transport.Conn, s.serverVersio n) 154 » s.ClientVersion, err = exchangeVersions(s.sshConn.conn, s.serverVersion)
164 if err != nil { 155 if err != nil {
165 return err 156 return err
166 } 157 }
167 » if err := s.clientInitHandshake(nil, nil); err != nil { 158
159 » tr := newTransport(s.sshConn.conn, s.config.rand(), false /* not client */)
160 » s.transport = newServerTransport(tr, s.ClientVersion, s.serverVersion, s .config)
161
162 » if err := s.transport.requestKeyChange(); err != nil {
168 return err 163 return err
169 } 164 }
170 165
166 if packet, err := s.transport.readPacket(); err != nil {
167 return err
168 } else if packet[0] != msgNewKeys {
169 return UnexpectedMessageError{msgNewKeys, packet[0]}
170 }
171
171 var packet []byte 172 var packet []byte
172 if packet, err = s.transport.readPacket(); err != nil { 173 if packet, err = s.transport.readPacket(); err != nil {
173 return err 174 return err
174 } 175 }
176
175 var serviceRequest serviceRequestMsg 177 var serviceRequest serviceRequestMsg
176 » if err := unmarshal(&serviceRequest, packet, msgServiceRequest); err != nil { 178 » if err = unmarshal(&serviceRequest, packet, msgServiceRequest); err != n il {
177 return err 179 return err
178 } 180 }
179 if serviceRequest.Service != serviceUserAuth { 181 if serviceRequest.Service != serviceUserAuth {
180 return errors.New("ssh: requested service '" + serviceRequest.Se rvice + "' before authenticating") 182 return errors.New("ssh: requested service '" + serviceRequest.Se rvice + "' before authenticating")
181 } 183 }
182 serviceAccept := serviceAcceptMsg{ 184 serviceAccept := serviceAcceptMsg{
183 Service: serviceUserAuth, 185 Service: serviceUserAuth,
184 } 186 }
185 if err := s.transport.writePacket(marshal(msgServiceAccept, serviceAccep t)); err != nil { 187 if err := s.transport.writePacket(marshal(msgServiceAccept, serviceAccep t)); err != nil {
186 return err 188 return err
187 } 189 }
188 190
189 if err := s.authenticate(); err != nil { 191 if err := s.authenticate(); err != nil {
190 return err 192 return err
191 } 193 }
192 return err 194 return err
193 } 195 }
194 196
195 func (s *ServerConn) clientInitHandshake(clientKexInit *kexInitMsg, clientKexIni tPacket []byte) (err error) {
196 serverKexInit := kexInitMsg{
197 KexAlgos: s.config.Crypto.kexes(),
198 CiphersClientServer: s.config.Crypto.ciphers(),
199 CiphersServerClient: s.config.Crypto.ciphers(),
200 MACsClientServer: s.config.Crypto.macs(),
201 MACsServerClient: s.config.Crypto.macs(),
202 CompressionClientServer: supportedCompressions,
203 CompressionServerClient: supportedCompressions,
204 }
205 for _, k := range s.config.hostKeys {
206 serverKexInit.ServerHostKeyAlgos = append(
207 serverKexInit.ServerHostKeyAlgos, k.PublicKey().PublicKe yAlgo())
208 }
209
210 serverKexInitPacket := marshal(msgKexInit, serverKexInit)
211 if err = s.transport.writePacket(serverKexInitPacket); err != nil {
212 return
213 }
214
215 if clientKexInitPacket == nil {
216 clientKexInit = new(kexInitMsg)
217 if clientKexInitPacket, err = s.transport.readPacket(); err != n il {
218 return
219 }
220 if err = unmarshal(clientKexInit, clientKexInitPacket, msgKexIni t); err != nil {
221 return
222 }
223 }
224
225 algs := findAgreedAlgorithms(clientKexInit, &serverKexInit)
226 if algs == nil {
227 return errors.New("ssh: no common algorithms")
228 }
229
230 if clientKexInit.FirstKexFollows && algs.kex != clientKexInit.KexAlgos[0 ] {
231 // The client sent a Kex message for the wrong algorithm,
232 // which we have to ignore.
233 if _, err = s.transport.readPacket(); err != nil {
234 return
235 }
236 }
237
238 var hostKey Signer
239 for _, k := range s.config.hostKeys {
240 if algs.hostKey == k.PublicKey().PublicKeyAlgo() {
241 hostKey = k
242 }
243 }
244
245 kex, ok := kexAlgoMap[algs.kex]
246 if !ok {
247 return fmt.Errorf("ssh: unexpected key exchange algorithm %v", a lgs.kex)
248 }
249
250 magics := handshakeMagics{
251 serverVersion: s.serverVersion,
252 clientVersion: s.ClientVersion,
253 serverKexInit: marshal(msgKexInit, serverKexInit),
254 clientKexInit: clientKexInitPacket,
255 }
256 result, err := kex.Server(s.transport, s.config.rand(), &magics, hostKey )
257 if err != nil {
258 return err
259 }
260
261 if err = s.transport.prepareKeyChange(algs, result); err != nil {
262 return err
263 }
264
265 if err = s.transport.writePacket([]byte{msgNewKeys}); err != nil {
266 return
267 }
268 if packet, err := s.transport.readPacket(); err != nil {
269 return err
270 } else if packet[0] != msgNewKeys {
271 return UnexpectedMessageError{msgNewKeys, packet[0]}
272 }
273
274 return
275 }
276
277 func isAcceptableAlgo(algo string) bool { 197 func isAcceptableAlgo(algo string) bool {
278 switch algo { 198 switch algo {
279 case KeyAlgoRSA, KeyAlgoDSA, KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoEC DSA521, 199 case KeyAlgoRSA, KeyAlgoDSA, KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoEC DSA521,
280 CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECD SA384v01, CertAlgoECDSA521v01: 200 CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01, CertAlgoECD SA384v01, CertAlgoECDSA521v01:
281 return true 201 return true
282 } 202 }
283 return false 203 return false
284 } 204 }
285 205
286 // testPubKey returns true if the given public key is acceptable for the user. 206 // testPubKey returns true if the given public key is acceptable for the user.
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
402 return ParseError{msgUserAuthRequest} 322 return ParseError{msgUserAuthRequest}
403 } 323 }
404 // Ensure the public key algo and signature algo 324 // Ensure the public key algo and signature algo
405 // are supported. Compare the private key 325 // are supported. Compare the private key
406 // algorithm name that corresponds to algo with 326 // algorithm name that corresponds to algo with
407 // sig.Format. This is usually the same, but 327 // sig.Format. This is usually the same, but
408 // for certs, the names differ. 328 // for certs, the names differ.
409 if !isAcceptableAlgo(algo) || !isAcceptableAlgo( sig.Format) || pubAlgoToPrivAlgo(algo) != sig.Format { 329 if !isAcceptableAlgo(algo) || !isAcceptableAlgo( sig.Format) || pubAlgoToPrivAlgo(algo) != sig.Format {
410 break 330 break
411 } 331 }
412 » » » » signedData := buildDataSignedForAuth(s.transport .sessionID, userAuthReq, algoBytes, pubKey) 332 » » » » signedData := buildDataSignedForAuth(s.transport .getSessionID(), userAuthReq, algoBytes, pubKey)
413 key, _, ok := ParsePublicKey(pubKey) 333 key, _, ok := ParsePublicKey(pubKey)
414 if !ok { 334 if !ok {
415 return ParseError{msgUserAuthRequest} 335 return ParseError{msgUserAuthRequest}
416 } 336 }
417 337
418 if !key.Verify(signedData, sig.Blob) { 338 if !key.Verify(signedData, sig.Blob) {
339 // TODO(hanwen): fix this
340 // message. It's not a parse
341 // error
419 return ParseError{msgUserAuthRequest} 342 return ParseError{msgUserAuthRequest}
420 } 343 }
421 // TODO(jmpittman): Implement full validation fo r certificates. 344 // TODO(jmpittman): Implement full validation fo r certificates.
422 s.User = userAuthReq.User 345 s.User = userAuthReq.User
423 if s.testPubKey(userAuthReq.User, algo, pubKey) { 346 if s.testPubKey(userAuthReq.User, algo, pubKey) {
424 break userAuthLoop 347 break userAuthLoop
425 } 348 }
426 } 349 }
427 } 350 }
428 351
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
515 // in order to demultiplex messages to any resulting Channels. 438 // in order to demultiplex messages to any resulting Channels.
516 func (s *ServerConn) Accept() (Channel, error) { 439 func (s *ServerConn) Accept() (Channel, error) {
517 // TODO(dfc) s.lock is not held here so visibility of s.err is not guara nteed. 440 // TODO(dfc) s.lock is not held here so visibility of s.err is not guara nteed.
518 if s.err != nil { 441 if s.err != nil {
519 return nil, s.err 442 return nil, s.err
520 } 443 }
521 444
522 for { 445 for {
523 packet, err := s.transport.readPacket() 446 packet, err := s.transport.readPacket()
524 if err != nil { 447 if err != nil {
525
526 s.lock.Lock() 448 s.lock.Lock()
527 s.err = err 449 s.err = err
528 s.lock.Unlock() 450 s.lock.Unlock()
529 451
530 // TODO(dfc) s.lock protects s.channels but isn't being held here. 452 // TODO(dfc) s.lock protects s.channels but isn't being held here.
531 for _, c := range s.channels { 453 for _, c := range s.channels {
532 c.setDead() 454 c.setDead()
533 c.handleData(nil) 455 c.handleData(nil)
534 } 456 }
535 457
536 return nil, err 458 return nil, err
537 } 459 }
538 460
539 switch packet[0] { 461 switch packet[0] {
462 case msgNewKeys:
463 // Lower level changed keys. Do nothing.
464
540 case msgChannelData: 465 case msgChannelData:
541 if len(packet) < 9 { 466 if len(packet) < 9 {
542 // malformed data packet 467 // malformed data packet
543 return nil, ParseError{msgChannelData} 468 return nil, ParseError{msgChannelData}
544 } 469 }
545 remoteId := binary.BigEndian.Uint32(packet[1:5]) 470 remoteId := binary.BigEndian.Uint32(packet[1:5])
546 s.lock.Lock() 471 s.lock.Lock()
547 c, ok := s.channels[remoteId] 472 c, ok := s.channels[remoteId]
548 if !ok { 473 if !ok {
549 s.lock.Unlock() 474 s.lock.Unlock()
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
626 c.handlePacket(msg) 551 c.handlePacket(msg)
627 s.lock.Unlock() 552 s.lock.Unlock()
628 553
629 case *globalRequestMsg: 554 case *globalRequestMsg:
630 if msg.WantReply { 555 if msg.WantReply {
631 if err := s.transport.writePacket([]byte {msgRequestFailure}); err != nil { 556 if err := s.transport.writePacket([]byte {msgRequestFailure}); err != nil {
632 return nil, err 557 return nil, err
633 } 558 }
634 } 559 }
635 560
636 case *kexInitMsg:
637 s.lock.Lock()
638 if err := s.clientInitHandshake(msg, packet); er r != nil {
639 s.lock.Unlock()
640 return nil, err
641 }
642 s.lock.Unlock()
643 case *disconnectMsg: 561 case *disconnectMsg:
644 return nil, io.EOF 562 return nil, io.EOF
645 default: 563 default:
646 // Unknown message. Ignore. 564 // Unknown message. Ignore.
647 } 565 }
648 } 566 }
649 } 567 }
650 568
651 panic("unreachable") 569 panic("unreachable")
652 } 570 }
(...skipping 30 matching lines...) Expand all
683 func Listen(network, addr string, config *ServerConfig) (*Listener, error) { 601 func Listen(network, addr string, config *ServerConfig) (*Listener, error) {
684 l, err := net.Listen(network, addr) 602 l, err := net.Listen(network, addr)
685 if err != nil { 603 if err != nil {
686 return nil, err 604 return nil, err
687 } 605 }
688 return &Listener{ 606 return &Listener{
689 l, 607 l,
690 config, 608 config,
691 }, nil 609 }, nil
692 } 610 }
OLDNEW

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