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 "encoding/binary" | 8 "encoding/binary" |
9 "errors" | 9 "errors" |
10 "fmt" | 10 "fmt" |
11 "io" | 11 "io" |
12 "log" | 12 "log" |
13 "sync" | 13 "sync" |
14 ) | 14 ) |
15 | 15 |
16 type ChannelCreationRequest interface { | 16 // A Channel is an ordered, reliable, duplex stream that is |
| 17 // multiplexed over an SSH connection. |
| 18 type Channel interface { |
17 // Accept accepts the channel creation request. | 19 // Accept accepts the channel creation request. |
18 » Accept() (Channel, error) | 20 » Accept() error |
19 | 21 |
20 // Reject rejects the channel creation request. After calling | 22 // Reject rejects the channel creation request. After calling |
21 // this, no other methods on the Channel may be called. | 23 // this, no other methods on the Channel may be called. |
22 Reject(reason RejectionReason, message string) error | 24 Reject(reason RejectionReason, message string) error |
23 | 25 |
24 » // ChannelType returns the type of the channel, as supplied by the | 26 » // Read may return a ChannelRequest as an error. |
25 » // client. | |
26 » ChannelType() string | |
27 | |
28 » // ExtraData returns the arbitrary payload for this channel, as supplied | |
29 » // by the client. This data is specific to the channel type. | |
30 » ExtraData() []byte | |
31 } | |
32 | |
33 // A Channel is an ordered, reliable, duplex stream that is | |
34 // multiplexed over an SSH connection. | |
35 type Channel interface { | |
36 » // NOSUBMIT - should add ReadExtended/WriteExtended here? | |
37 | |
38 Read(data []byte) (int, error) | 27 Read(data []byte) (int, error) |
39 Write(data []byte) (int, error) | 28 Write(data []byte) (int, error) |
40 | |
41 // Sends EOF to the other side. | |
42 CloseWrite() error | |
43 | 29 |
44 // Signals end of channel use. No data may be sent after this | 30 // Signals end of channel use. No data may be sent after this |
45 // call. | 31 // call. |
46 Close() error | 32 Close() error |
47 | 33 |
48 » // Stderr returns an io.ReadWriter to write to (server) or | 34 » // Stderr returns an io.Writer that writes to this channel with the |
49 » // read from (client) stderr. | 35 » // extended data type set to stderr. |
50 » Stderr() io.ReadWriter | 36 » Stderr() io.Writer |
51 | |
52 » // SendRequest sends a channel request. | |
53 » SendRequest(name string, wantReply bool, payload []byte) (bool, error) | |
54 | |
55 » // IncomingRequests returns the channel for out-of-band | |
56 » // requests. For all requests received that have WantReply, a | |
57 » // call of AckRequest should follow. | |
58 » IncomingRequests() chan *ChannelRequest | |
59 | 37 |
60 // AckRequest either sends an ack or nack to the channel | 38 // AckRequest either sends an ack or nack to the channel |
61 // request. It should only be called if the last | 39 // request. It should only be called if the last |
62 // ChannelRequest had a WantReply | 40 // ChannelRequest had a WantReply |
63 AckRequest(ok bool) error | 41 AckRequest(ok bool) error |
64 | 42 |
65 // ChannelType returns the type of the channel, as supplied by the | 43 // ChannelType returns the type of the channel, as supplied by the |
66 // client. | 44 // client. |
67 ChannelType() string | 45 ChannelType() string |
68 | 46 |
69 // ExtraData returns the arbitrary payload for this channel, as supplied | 47 // ExtraData returns the arbitrary payload for this channel, as supplied |
70 // by the client. This data is specific to the channel type. | 48 // by the client. This data is specific to the channel type. |
71 ExtraData() []byte | 49 ExtraData() []byte |
72 } | 50 } |
73 | 51 |
74 // ChannelRequest represents a request sent, outside of the normal | 52 // ChannelRequest represents a request sent, outside of the normal |
75 // stream of bytes. Requests may either be channel specific, or global | 53 // stream of bytes. |
76 type ChannelRequest struct { | 54 type ChannelRequest struct { |
77 Request string | 55 Request string |
78 WantReply bool | 56 WantReply bool |
79 Payload []byte | 57 Payload []byte |
| 58 } |
| 59 |
| 60 func (c ChannelRequest) Error() string { |
| 61 return "ssh: channel request received" |
80 } | 62 } |
81 | 63 |
82 // RejectionReason is an enumeration used when rejecting channel creation | 64 // RejectionReason is an enumeration used when rejecting channel creation |
83 // requests. See RFC 4254, section 5.1. | 65 // requests. See RFC 4254, section 5.1. |
84 type RejectionReason uint32 | 66 type RejectionReason uint32 |
85 | 67 |
86 const ( | 68 const ( |
87 Prohibited RejectionReason = iota + 1 | 69 Prohibited RejectionReason = iota + 1 |
88 ConnectionFailed | 70 ConnectionFailed |
89 UnknownChannelType | 71 UnknownChannelType |
(...skipping 24 matching lines...) Expand all Loading... |
114 maxPacket uint32 | 96 maxPacket uint32 |
115 mux *mux | 97 mux *mux |
116 | 98 |
117 // If set, we have called Accept or Reject on this channel | 99 // If set, we have called Accept or Reject on this channel |
118 decided bool | 100 decided bool |
119 | 101 |
120 // Pending internal channel messages. | 102 // Pending internal channel messages. |
121 msg chan interface{} | 103 msg chan interface{} |
122 | 104 |
123 // Pending user-serviceable messages. | 105 // Pending user-serviceable messages. |
124 » sentRequestMu sync.Mutex | 106 » sentRequestMu sync.Mutex |
125 » pendingRequests chan *ChannelRequest | 107 |
| 108 » incomingRequests chan *ChannelRequest |
126 | 109 |
127 sentEOF bool | 110 sentEOF bool |
128 | 111 |
129 // thread-safe data | 112 // thread-safe data |
130 remoteWin window | 113 remoteWin window |
131 pending *buffer | 114 pending *buffer |
132 extPending *buffer | 115 extPending *buffer |
133 | 116 |
134 // Protects all of the below. | 117 // Protects all of the below. |
135 mu sync.Mutex | 118 mu sync.Mutex |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
269 return c.sendMessage(msgChannelWindowAdjust, windowAdjustMsg{ | 252 return c.sendMessage(msgChannelWindowAdjust, windowAdjustMsg{ |
270 AdditionalBytes: uint32(n), | 253 AdditionalBytes: uint32(n), |
271 }) | 254 }) |
272 } | 255 } |
273 | 256 |
274 func (c *channel) ReadExtended(data []byte, extended uint32) (n int, err error)
{ | 257 func (c *channel) ReadExtended(data []byte, extended uint32) (n int, err error)
{ |
275 if extended == 1 { | 258 if extended == 1 { |
276 n, err = c.extPending.Read(data) | 259 n, err = c.extPending.Read(data) |
277 } else if extended == 0 { | 260 } else if extended == 0 { |
278 n, err = c.pending.Read(data) | 261 n, err = c.pending.Read(data) |
| 262 } else { |
| 263 return 0, fmt.Errorf("ssh: extended code %d implemented", extend
ed) |
279 } | 264 } |
280 | 265 |
281 if n > 0 { | 266 if n > 0 { |
282 err = c.adjustWindow(uint32(n)) | 267 err = c.adjustWindow(uint32(n)) |
283 // sendWindowAdjust can return io.EOF if the remote | 268 // sendWindowAdjust can return io.EOF if the remote |
284 // peer has closed the connection, however we want to | 269 // peer has closed the connection, however we want to |
285 // defer forwarding io.EOF to the caller of Read until | 270 // defer forwarding io.EOF to the caller of Read until |
286 // the buffer has been drained. | 271 // the buffer has been drained. |
287 if n > 0 && err == io.EOF { | 272 if n > 0 && err == io.EOF { |
288 err = nil | 273 err = nil |
(...skipping 13 matching lines...) Expand all Loading... |
302 case msgChannelData, msgChannelExtendedData: | 287 case msgChannelData, msgChannelExtendedData: |
303 return c.handleData(packet) | 288 return c.handleData(packet) |
304 case msgChannelClose: | 289 case msgChannelClose: |
305 // Ack the close. | 290 // Ack the close. |
306 c.sendMessage(msgChannelClose, channelCloseMsg{ | 291 c.sendMessage(msgChannelClose, channelCloseMsg{ |
307 PeersId: c.remoteId}) | 292 PeersId: c.remoteId}) |
308 | 293 |
309 c.pending.eof() | 294 c.pending.eof() |
310 c.extPending.eof() | 295 c.extPending.eof() |
311 close(c.msg) | 296 close(c.msg) |
312 » » close(c.pendingRequests) | 297 » » close(c.incomingRequests) |
313 c.mux.chanList.remove(c.localId) | 298 c.mux.chanList.remove(c.localId) |
314 | 299 |
315 return nil | 300 return nil |
316 case msgChannelEOF: | 301 case msgChannelEOF: |
317 c.pending.eof() | |
318 // RFC 4254 is mute on how EOF affects dataExt messages but | 302 // RFC 4254 is mute on how EOF affects dataExt messages but |
319 // it is logical to signal EOF at the same time. | 303 // it is logical to signal EOF at the same time. |
320 c.extPending.eof() | 304 c.extPending.eof() |
| 305 |
| 306 // For ServerConn, ChannelRequests are actually output |
| 307 // as Read error. This means that no requests can be |
| 308 // processed after EOF is sent, which is a bug |
| 309 c.pending.eof() |
321 return nil | 310 return nil |
322 } | 311 } |
323 | 312 |
324 decoded, err := decode(packet) | 313 decoded, err := decode(packet) |
325 if err != nil { | 314 if err != nil { |
326 return err | 315 return err |
327 } | 316 } |
328 | 317 |
329 switch msg := decoded.(type) { | 318 switch msg := decoded.(type) { |
330 case *windowAdjustMsg: | 319 case *windowAdjustMsg: |
331 if !c.remoteWin.add(msg.AdditionalBytes) { | 320 if !c.remoteWin.add(msg.AdditionalBytes) { |
332 return fmt.Errorf("invalid window update %d", msg.Additi
onalBytes) | 321 return fmt.Errorf("invalid window update %d", msg.Additi
onalBytes) |
333 } | 322 } |
334 | 323 |
335 case *channelRequestMsg: | 324 case *channelRequestMsg: |
336 req := ChannelRequest{ | 325 req := ChannelRequest{ |
337 Request: msg.Request, | 326 Request: msg.Request, |
338 WantReply: msg.WantReply, | 327 WantReply: msg.WantReply, |
339 Payload: msg.RequestSpecificData, | 328 Payload: msg.RequestSpecificData, |
340 } | 329 } |
341 | 330 |
342 » » c.pendingRequests <- &req | 331 » » c.incomingRequests <- &req |
343 default: | 332 default: |
344 c.msg <- msg | 333 c.msg <- msg |
345 } | 334 } |
346 return nil | 335 return nil |
347 } | 336 } |
348 | 337 |
349 func newChannel(chanType string, extraData []byte) *channel { | 338 func newChannel(chanType string, extraData []byte) *channel { |
350 return &channel{ | 339 return &channel{ |
351 » » remoteWin: window{Cond: newCond()}, | 340 » » remoteWin: window{Cond: newCond()}, |
352 » » myWindow: defaultWindowSize, | 341 » » myWindow: defaultWindowSize, |
353 » » pending: newBuffer(), | 342 » » pending: newBuffer(), |
354 » » extPending: newBuffer(), | 343 » » extPending: newBuffer(), |
355 » » pendingRequests: make(chan *ChannelRequest, 16), | 344 » » incomingRequests: make(chan *ChannelRequest, 16), |
356 » » msg: make(chan interface{}, 16), | 345 » » msg: make(chan interface{}, 16), |
357 » » chanType: chanType, | 346 » » chanType: chanType, |
358 » » extraData: extraData, | 347 » » extraData: extraData, |
359 } | 348 } |
360 } | 349 } |
361 | 350 |
362 var errUndecided = errors.New("ssh: must Accept or Reject channel") | 351 var errUndecided = errors.New("ssh: must Accept or Reject channel") |
363 var errDecidedAlready = errors.New("ssh: can call Accept or Reject only once") | 352 var errDecidedAlready = errors.New("ssh: can call Accept or Reject only once") |
364 | 353 |
365 type extChannel channel | 354 type extChannel struct { |
| 355 » code uint32 |
| 356 » ch *channel |
| 357 } |
366 | 358 |
367 func (e *extChannel) Write(data []byte) (n int, err error) { | 359 func (e *extChannel) Write(data []byte) (n int, err error) { |
368 » return ((*channel)(e)).WriteExtended(data, 1) | 360 » return e.ch.WriteExtended(data, e.code) |
369 } | 361 } |
370 func (e *extChannel) Read(data []byte) (n int, err error) { | 362 func (e *extChannel) Read(data []byte) (n int, err error) { |
371 » return ((*channel)(e)).ReadExtended(data, 1) | 363 » return e.ch.ReadExtended(data, e.code) |
372 } | 364 } |
373 | 365 |
374 func (c *channel) Accept() (Channel, error) { | 366 func (c *channel) Accept() error { |
375 if c.decided { | 367 if c.decided { |
376 » » return nil, errDecidedAlready | 368 » » return errDecidedAlready |
377 } | 369 } |
378 confirm := channelOpenConfirmMsg{ | 370 confirm := channelOpenConfirmMsg{ |
379 PeersId: c.remoteId, | 371 PeersId: c.remoteId, |
380 MyId: c.localId, | 372 MyId: c.localId, |
381 MyWindow: c.myWindow, | 373 MyWindow: c.myWindow, |
382 MaxPacketSize: c.maxPacket, | 374 MaxPacketSize: c.maxPacket, |
383 } | 375 } |
384 c.decided = true | 376 c.decided = true |
385 if err := c.sendMessage(msgChannelOpenConfirm, confirm); err != nil { | 377 if err := c.sendMessage(msgChannelOpenConfirm, confirm); err != nil { |
386 » » return nil, err | 378 » » return err |
387 » } | 379 » } |
388 | 380 |
389 » return c, nil | 381 » return nil |
390 } | 382 } |
391 | 383 |
392 func (ch *channel) Reject(reason RejectionReason, message string) error { | 384 func (ch *channel) Reject(reason RejectionReason, message string) error { |
393 if ch.decided { | 385 if ch.decided { |
394 return errDecidedAlready | 386 return errDecidedAlready |
395 } | 387 } |
396 reject := channelOpenFailureMsg{ | 388 reject := channelOpenFailureMsg{ |
397 PeersId: ch.remoteId, | 389 PeersId: ch.remoteId, |
398 Reason: reason, | 390 Reason: reason, |
399 Message: message, | 391 Message: message, |
400 Language: "en", | 392 Language: "en", |
401 } | 393 } |
402 ch.decided = true | 394 ch.decided = true |
403 return ch.sendMessage(msgChannelOpenFailure, reject) | 395 return ch.sendMessage(msgChannelOpenFailure, reject) |
404 } | 396 } |
405 | 397 |
406 func (ch *channel) Read(data []byte) (int, error) { | 398 func (ch *channel) Read(data []byte) (int, error) { |
407 if !ch.decided { | 399 if !ch.decided { |
408 return 0, errUndecided | 400 return 0, errUndecided |
409 } | 401 } |
410 | 402 |
411 return ch.ReadExtended(data, 0) | 403 return ch.ReadExtended(data, 0) |
412 } | 404 } |
413 | 405 |
414 func (ch *channel) IncomingRequests() chan *ChannelRequest { | |
415 return ch.pendingRequests | |
416 } | |
417 | |
418 func (ch *channel) Write(data []byte) (int, error) { | 406 func (ch *channel) Write(data []byte) (int, error) { |
419 if !ch.decided { | 407 if !ch.decided { |
420 return 0, errUndecided | 408 return 0, errUndecided |
421 } | 409 } |
422 return ch.WriteExtended(data, 0) | 410 return ch.WriteExtended(data, 0) |
423 } | 411 } |
424 | 412 |
425 func (ch *channel) CloseWrite() error { | 413 func (ch *channel) CloseWrite() error { |
426 if !ch.decided { | 414 if !ch.decided { |
427 return errUndecided | 415 return errUndecided |
428 } | 416 } |
429 ch.sentEOF = true | 417 ch.sentEOF = true |
430 return ch.sendMessage(msgChannelEOF, channelEOFMsg{ | 418 return ch.sendMessage(msgChannelEOF, channelEOFMsg{ |
431 PeersId: ch.remoteId}) | 419 PeersId: ch.remoteId}) |
432 } | 420 } |
433 | 421 |
434 func (ch *channel) Close() error { | 422 func (ch *channel) Close() error { |
435 if !ch.decided { | 423 if !ch.decided { |
436 return errUndecided | 424 return errUndecided |
437 } | 425 } |
438 | 426 |
439 return ch.sendMessage(msgChannelClose, channelCloseMsg{ | 427 return ch.sendMessage(msgChannelClose, channelCloseMsg{ |
440 PeersId: ch.remoteId}) | 428 PeersId: ch.remoteId}) |
441 } | 429 } |
442 | 430 |
443 func (ch *channel) Stderr() io.ReadWriter { | 431 func (ch *channel) Extended(code uint32) io.ReadWriter { |
444 if !ch.decided { | 432 if !ch.decided { |
445 return nil | 433 return nil |
446 } | 434 } |
447 » return (*extChannel)(ch) | 435 » return &extChannel{code, ch} |
448 } | 436 } |
449 | 437 |
450 // SendRequest sends a channel request. If wantReply is set, it will | 438 // SendRequest sends a channel request. If wantReply is set, it will |
451 // wait for a reply and return the result as a boolean. | 439 // wait for a reply and return the result as a boolean. |
452 func (ch *channel) SendRequest(name string, wantReply bool, payload []byte) (boo
l, error) { | 440 func (ch *channel) SendRequest(name string, wantReply bool, payload []byte) (boo
l, error) { |
453 if !ch.decided { | 441 if !ch.decided { |
454 return false, errUndecided | 442 return false, errUndecided |
455 } | 443 } |
456 | 444 |
457 if wantReply { | 445 if wantReply { |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
510 return ch.sendMessage(code, msg) | 498 return ch.sendMessage(code, msg) |
511 } | 499 } |
512 | 500 |
513 func (ch *channel) ChannelType() string { | 501 func (ch *channel) ChannelType() string { |
514 return ch.chanType | 502 return ch.chanType |
515 } | 503 } |
516 | 504 |
517 func (ch *channel) ExtraData() []byte { | 505 func (ch *channel) ExtraData() []byte { |
518 return ch.extraData | 506 return ch.extraData |
519 } | 507 } |
| 508 |
| 509 // compatChannel is a hack to implement Channel's |
| 510 // handing of channel requests. |
| 511 type compatChannel struct { |
| 512 *channel |
| 513 } |
| 514 |
| 515 func newCompatChannel(ch *channel) *compatChannel { |
| 516 c := &compatChannel{ch} |
| 517 go c.loop() |
| 518 return c |
| 519 } |
| 520 |
| 521 func (c *compatChannel) loop() { |
| 522 for r := range c.channel.incomingRequests { |
| 523 c.channel.pending.addRequest(r) |
| 524 } |
| 525 } |
| 526 |
| 527 func (c *compatChannel) Stderr() io.Writer { |
| 528 return c.Extended(1) |
| 529 } |
LEFT | RIGHT |