Left: | ||
Right: |
OLD | NEW |
---|---|
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 "bufio" | 8 "bufio" |
9 "crypto/cipher" | 9 "crypto/cipher" |
10 "crypto/subtle" | 10 "crypto/subtle" |
11 "encoding/binary" | 11 "encoding/binary" |
12 "errors" | 12 "errors" |
13 "hash" | 13 "hash" |
14 "io" | 14 "io" |
15 "net" | |
16 "sync" | 15 "sync" |
17 ) | 16 ) |
18 | 17 |
19 const ( | 18 const ( |
20 packetSizeMultiple = 16 // TODO(huin) this should be determined by the c ipher. | 19 packetSizeMultiple = 16 // TODO(huin) this should be determined by the c ipher. |
21 | 20 |
22 // RFC 4253 section 6.1 defines a minimum packet size of 32768 that impl ementations | 21 // RFC 4253 section 6.1 defines a minimum packet size of 32768 that impl ementations |
23 // MUST be able to process (plus a few more kilobytes for padding and ma c). The RFC | 22 // MUST be able to process (plus a few more kilobytes for padding and ma c). The RFC |
24 // indicates implementations SHOULD be able to handle larger packet size s, but then | 23 // indicates implementations SHOULD be able to handle larger packet size s, but then |
25 // waffles on about reasonable limits. | 24 // waffles on about reasonable limits. |
(...skipping 13 matching lines...) Expand all Loading... | |
39 | 38 |
40 // Close closes the write-side of the connection. | 39 // Close closes the write-side of the connection. |
41 Close() error | 40 Close() error |
42 } | 41 } |
43 | 42 |
44 // transport represents the SSH connection to the remote peer. | 43 // transport represents the SSH connection to the remote peer. |
45 type transport struct { | 44 type transport struct { |
46 reader | 45 reader |
47 writer | 46 writer |
48 | 47 |
49 » net.Conn | 48 » io.Closer |
50 | 49 |
51 // Initial H used for the session ID. Once assigned this does | 50 // Initial H used for the session ID. Once assigned this does |
52 // not change, even during subsequent key exchanges. | 51 // not change, even during subsequent key exchanges. |
53 sessionID []byte | 52 sessionID []byte |
54 } | 53 } |
55 | 54 |
55 func (t *transport) SessionID() []byte { | |
dfc
2013/10/22 22:07:02
does this need to return a copy of the sessionID ?
hanwen-google
2013/10/23 00:15:17
not necessarily, but it is safer and cost is negli
| |
56 if t.sessionID == nil { | |
57 panic("session ID not set yet") | |
58 } | |
59 return t.sessionID | |
60 } | |
61 | |
56 // reader represents the incoming connection state. | 62 // reader represents the incoming connection state. |
57 type reader struct { | 63 type reader struct { |
58 io.Reader | 64 io.Reader |
59 common | 65 common |
60 } | 66 } |
61 | 67 |
62 // writer represents the outgoing connection state. | 68 // writer represents the outgoing connection state. |
63 type writer struct { | 69 type writer struct { |
64 sync.Mutex // protects writer.Writer from concurrent writes | 70 sync.Mutex // protects writer.Writer from concurrent writes |
65 *bufio.Writer | 71 *bufio.Writer |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
163 } | 169 } |
164 default: | 170 default: |
165 return nil, errors.New("ssh: got bogus newkeys message." ) | 171 return nil, errors.New("ssh: got bogus newkeys message." ) |
166 } | 172 } |
167 } | 173 } |
168 return packet, nil | 174 return packet, nil |
169 } | 175 } |
170 | 176 |
171 // Read and decrypt next packet discarding debug and noop messages. | 177 // Read and decrypt next packet discarding debug and noop messages. |
172 func (t *transport) readPacket() ([]byte, error) { | 178 func (t *transport) readPacket() ([]byte, error) { |
173 » for { | 179 » packet, err := t.reader.readPacket() |
174 » » packet, err := t.reader.readPacket() | 180 » if err == nil && len(packet) == 0 { |
175 » » if err != nil { | 181 » » err = errors.New("ssh: zero length packet") |
176 » » » return nil, err | 182 » } |
177 » » } | |
178 » » if len(packet) == 0 { | |
179 » » » return nil, errors.New("ssh: zero length packet") | |
180 » » } | |
181 | 183 |
182 » » if packet[0] != msgIgnore && packet[0] != msgDebug { | 184 » return packet, err |
183 » » » return packet, nil | |
184 » » } | |
185 » } | |
186 » panic("unreachable") | |
187 } | 185 } |
188 | 186 |
189 // Encrypt and send a packet of data to the remote peer. | 187 // Encrypt and send a packet of data to the remote peer. |
190 func (w *writer) writePacket(packet []byte) error { | 188 func (w *writer) writePacket(packet []byte) error { |
191 changeKeys := len(packet) > 0 && packet[0] == msgNewKeys | 189 changeKeys := len(packet) > 0 && packet[0] == msgNewKeys |
192 | 190 |
193 if len(packet) > maxPacket { | 191 if len(packet) > maxPacket { |
194 return errors.New("ssh: packet too large") | 192 return errors.New("ssh: packet too large") |
195 } | 193 } |
196 w.Mutex.Lock() | 194 w.Mutex.Lock() |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
260 select { | 258 select { |
261 case k := <-w.pendingKeyChange: | 259 case k := <-w.pendingKeyChange: |
262 err = w.setupKeys(w.dir, k) | 260 err = w.setupKeys(w.dir, k) |
263 default: | 261 default: |
264 panic("ssh: no key material for msgNewKeys") | 262 panic("ssh: no key material for msgNewKeys") |
265 } | 263 } |
266 } | 264 } |
267 return err | 265 return err |
268 } | 266 } |
269 | 267 |
270 func newTransport(conn net.Conn, rand io.Reader, isClient bool) *transport { | 268 func newTransport(conn io.ReadWriteCloser, rand io.Reader, isClient bool) *trans port { |
dfc
2013/10/22 22:07:02
s/conn/rwc/
hanwen-google
2013/10/23 00:15:17
Done.
| |
271 t := &transport{ | 269 t := &transport{ |
272 reader: reader{ | 270 reader: reader{ |
273 Reader: bufio.NewReader(conn), | 271 Reader: bufio.NewReader(conn), |
274 common: common{ | 272 common: common{ |
275 cipher: noneCipher{}, | 273 cipher: noneCipher{}, |
276 pendingKeyChange: make(chan *kexResult, 1), | 274 pendingKeyChange: make(chan *kexResult, 1), |
277 }, | 275 }, |
278 }, | 276 }, |
279 writer: writer{ | 277 writer: writer{ |
280 Writer: bufio.NewWriter(conn), | 278 Writer: bufio.NewWriter(conn), |
281 rand: rand, | 279 rand: rand, |
282 common: common{ | 280 common: common{ |
283 cipher: noneCipher{}, | 281 cipher: noneCipher{}, |
284 pendingKeyChange: make(chan *kexResult, 1), | 282 pendingKeyChange: make(chan *kexResult, 1), |
285 }, | 283 }, |
286 }, | 284 }, |
287 » » Conn: conn, | 285 » » Closer: conn, |
288 } | 286 } |
289 if isClient { | 287 if isClient { |
290 t.reader.dir = serverKeys | 288 t.reader.dir = serverKeys |
291 t.writer.dir = clientKeys | 289 t.writer.dir = clientKeys |
292 } else { | 290 } else { |
293 t.reader.dir = clientKeys | 291 t.reader.dir = clientKeys |
294 t.writer.dir = serverKeys | 292 t.writer.dir = serverKeys |
295 } | 293 } |
296 | 294 |
297 return t | 295 return t |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
417 if !ok { | 415 if !ok { |
418 return nil, errors.New("ssh: overflow reading version string") | 416 return nil, errors.New("ssh: overflow reading version string") |
419 } | 417 } |
420 | 418 |
421 // There might be a '\r' on the end which we should remove. | 419 // There might be a '\r' on the end which we should remove. |
422 if len(versionString) > 0 && versionString[len(versionString)-1] == '\r' { | 420 if len(versionString) > 0 && versionString[len(versionString)-1] == '\r' { |
423 versionString = versionString[:len(versionString)-1] | 421 versionString = versionString[:len(versionString)-1] |
424 } | 422 } |
425 return versionString, nil | 423 return versionString, nil |
426 } | 424 } |
OLD | NEW |