github.com/glycerine/xcryptossh@v7.0.4+incompatible/channel.go (about)

     1  // Copyright 2011 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package ssh
     6  
     7  import (
     8  	"encoding/binary"
     9  	"errors"
    10  	"fmt"
    11  	"io"
    12  	"log"
    13  	"net"
    14  	"sync"
    15  	"sync/atomic"
    16  	"time"
    17  )
    18  
    19  const (
    20  	minPacketLength = 9
    21  	// channelMaxPacket contains the maximum number of bytes that will be
    22  	// sent in a single packet. As per RFC 4253, section 6.1, 32k is also
    23  	// the minimum.
    24  	channelMaxPacket = 1 << 15
    25  	// We follow OpenSSH here.
    26  	channelWindowSize = 64 * channelMaxPacket
    27  )
    28  
    29  // verify interface satisfied.
    30  var _ net.Conn = &channel{}
    31  
    32  type HasTimeout interface {
    33  	timeout()
    34  }
    35  
    36  // NewChannel represents an incoming request to a channel. It must either be
    37  // accepted for use by calling Accept, or rejected by calling Reject.
    38  type NewChannel interface {
    39  	// Accept accepts the channel creation request. It returns the Channel
    40  	// and a Go channel containing SSH requests. The Go channel must be
    41  	// serviced otherwise the Channel will hang.
    42  	Accept() (Channel, <-chan *Request, error)
    43  
    44  	// Reject rejects the channel creation request. After calling
    45  	// this, no other methods on the Channel may be called.
    46  	Reject(reason RejectionReason, message string) error
    47  
    48  	// ChannelType returns the type of the channel, as supplied by the
    49  	// client.
    50  	ChannelType() string
    51  
    52  	// ExtraData returns the arbitrary payload for this channel, as supplied
    53  	// by the client. This data is specific to the channel type.
    54  	ExtraData() []byte
    55  }
    56  
    57  // A Channel is an ordered, reliable, flow-controlled, duplex stream
    58  // that is multiplexed over an SSH connection.
    59  type Channel interface {
    60  	// Read reads up to len(data) bytes from the channel.
    61  	Read(data []byte) (int, error)
    62  
    63  	// Write writes len(data) bytes to the channel.
    64  	Write(data []byte) (int, error)
    65  
    66  	// Close signals end of channel use. No data may be sent after this
    67  	// call.
    68  	Close() error
    69  
    70  	// CloseWrite signals the end of sending in-band
    71  	// data. Requests may still be sent, and the other side may
    72  	// still send data
    73  	CloseWrite() error
    74  
    75  	// SendRequest sends a channel request.  If wantReply is true,
    76  	// it will wait for a reply and return the result as a
    77  	// boolean, otherwise the return value will be false. Channel
    78  	// requests are out-of-band messages so they may be sent even
    79  	// if the data stream is closed or blocked by flow control.
    80  	// If the channel is closed before a reply is returned, io.EOF
    81  	// is returned.
    82  	SendRequest(name string, wantReply bool, payload []byte) (bool, error)
    83  
    84  	// Stderr returns an io.ReadWriter that writes to this channel
    85  	// with the extended data type set to stderr. Stderr may
    86  	// safely be read and written from a different goroutine than
    87  	// Read and Write respectively.
    88  	Stderr() io.ReadWriter
    89  
    90  	// Done can be used to await connection shutdown. The
    91  	// returned channel will be closed when the Channel is closed.
    92  	Done() <-chan struct{}
    93  
    94  	// 	GetHalter returns the Channel specific Halter.
    95  	GetHalter() *Halter
    96  
    97  	// SetReadIdleTimeout starts an idle timer on
    98  	// Reads that will cause them to timeout after dur.
    99  	// A successful Read will bump the idle
   100  	// timeout into the future.
   101  	//
   102  	// Providing dur of 0 will disable the idle timeout.
   103  	// Zero is the default until SetReadIdleTimeout() is called.
   104  	//
   105  	// SetReadIdleTimeout() will always reset and
   106  	// clear any raised timeout left over from prior use.
   107  	// Any new timer (if dur > 0) begins from the return of
   108  	// the SetReadIdleTimeout() invocation.
   109  	//
   110  	// Idle timeouts are easier to use than deadlines,
   111  	// as they don't need to be refreshed after
   112  	// every read and write. Hence routines like io.Copy()
   113  	// that make many calls to Read() and Write()
   114  	// can be leveraged, while still having a timeout in
   115  	// the case of no activity.
   116  	//
   117  	// Moreover idle timeouts are more
   118  	// efficient because we don't guess at a
   119  	// deadline and then interrupt a perfectly
   120  	// good ongoing copy that happens to be
   121  	// taking a few seconds longer than our
   122  	// guesstimate. We avoid the pain of trying
   123  	// to restart long interrupted transfers that
   124  	// were making fine progress.
   125  	//
   126  	SetReadIdleTimeout(dur time.Duration) error
   127  
   128  	// SetWriteIdleTimeout is the same as SetReadIdleTimeout,
   129  	// but applies to writes rather than reads.
   130  	// Note that Write() to
   131  	// a Channel will "succeed" in the sense of
   132  	// returning a nil error long before they
   133  	// reach the remote end (or not). Writes
   134  	// are buffered internally. Hence the write
   135  	// idle timer may be less useful than
   136  	// the read timer.
   137  	SetWriteIdleTimeout(dur time.Duration) error
   138  
   139  	// SetIdleTimeout does both SetReadIdleTimeout
   140  	// and SetWriteIdleTimeout.
   141  	SetIdleTimeout(dur time.Duration) error
   142  
   143  	// GetReadIdleTimer allows monitoring of idle timeout
   144  	// by other parties. It doesn't disturb the
   145  	// timer if it happens to be running.
   146  	GetReadIdleTimer() *IdleTimer
   147  
   148  	// GetWriteIdleTimer allows monitoring of idle timeout
   149  	// by other parties. It doesn't disturb the
   150  	// timer if it happens to be running.
   151  	GetWriteIdleTimer() *IdleTimer
   152  
   153  	// SetReadDeadline sets the deadline for future Read calls
   154  	// and any currently-blocked Read call.
   155  	// A zero value for t means Read will not time out.
   156  	SetReadDeadline(t time.Time) error
   157  
   158  	// SetWriteDeadline sets the deadline for future Write calls
   159  	// and any currently-blocked Write call.
   160  	// A zero value for t means Write will not time out.
   161  	SetWriteDeadline(t time.Time) error
   162  
   163  	// SetDeadline sets the read and write deadlines.
   164  	SetDeadline(t time.Time) error
   165  
   166  	// Status lets clients query this Channel's lifecycle
   167  	// progress.
   168  	Status() *RunStatus
   169  
   170  	LocalAddr() net.Addr
   171  	RemoteAddr() net.Addr
   172  }
   173  
   174  // Request is a request sent outside of the normal stream of
   175  // data. Requests can either be specific to an SSH channel, or they
   176  // can be global.
   177  type Request struct {
   178  	Type      string
   179  	WantReply bool
   180  	Payload   []byte
   181  
   182  	ch  *channel
   183  	mux *mux
   184  }
   185  
   186  // Reply sends a response to a request. It must be called for all requests
   187  // where WantReply is true and is a no-op otherwise. The payload argument is
   188  // ignored for replies to channel-specific requests.
   189  func (r *Request) Reply(ok bool, payload []byte) error {
   190  	if !r.WantReply {
   191  		return nil
   192  	}
   193  
   194  	if r.ch == nil {
   195  		return r.mux.ackRequest(ok, payload)
   196  	}
   197  
   198  	return r.ch.ackRequest(ok)
   199  }
   200  
   201  // RejectionReason is an enumeration used when rejecting channel creation
   202  // requests. See RFC 4254, section 5.1.
   203  type RejectionReason uint32
   204  
   205  const (
   206  	Prohibited RejectionReason = iota + 1
   207  	ConnectionFailed
   208  	UnknownChannelType
   209  	ResourceShortage
   210  )
   211  
   212  // String converts the rejection reason to human readable form.
   213  func (r RejectionReason) String() string {
   214  	switch r {
   215  	case Prohibited:
   216  		return "administratively prohibited"
   217  	case ConnectionFailed:
   218  		return "connect failed"
   219  	case UnknownChannelType:
   220  		return "unknown channel type"
   221  	case ResourceShortage:
   222  		return "resource shortage"
   223  	}
   224  	return fmt.Sprintf("unknown reason %d", int(r))
   225  }
   226  
   227  func min(a uint32, b int) uint32 {
   228  	if a < uint32(b) {
   229  		return a
   230  	}
   231  	return uint32(b)
   232  }
   233  
   234  type channelDirection uint8
   235  
   236  const (
   237  	channelInbound channelDirection = iota
   238  	channelOutbound
   239  )
   240  
   241  // channel is an implementation of the Channel interface that works
   242  // with the mux class.
   243  type channel struct {
   244  	// R/O after creation
   245  	chanType          string
   246  	extraData         []byte
   247  	localId, remoteId uint32
   248  
   249  	// maxIncomingPayload and maxRemotePayload are the maximum
   250  	// payload sizes of normal and extended data packets for
   251  	// receiving and sending, respectively. The wire packet will
   252  	// be 9 or 13 bytes larger (excluding encryption overhead).
   253  	maxIncomingPayload uint32
   254  	maxRemotePayload   uint32
   255  
   256  	mux *mux
   257  
   258  	// decided is set to true if an accept or reject message has been sent
   259  	// (for outbound channels) or received (for inbound channels).
   260  	decided bool
   261  
   262  	// direction contains either channelOutbound, for channels created
   263  	// locally, or channelInbound, for channels created by the peer.
   264  	direction channelDirection
   265  
   266  	// Pending internal channel messages.
   267  	msg chan interface{}
   268  
   269  	// Since requests have no ID, there can be only one request
   270  	// with WantReply=true outstanding.  This lock is held by a
   271  	// goroutine that has such an outgoing request pending.
   272  	sentRequestMu sync.Mutex
   273  
   274  	incomingRequests chan *Request
   275  
   276  	sentEOF bool
   277  
   278  	// thread-safe data
   279  	remoteWin  window
   280  	pending    *buffer
   281  	extPending *buffer
   282  
   283  	// windowMu protects myWindow, the flow-control window.
   284  	windowMu sync.Mutex
   285  	myWindow uint32
   286  
   287  	// writeMu serializes calls to mux.conn.writePacket() and
   288  	// protects sentClose and packetPool. This mutex must be
   289  	// different from windowMu, as writePacket can block if there
   290  	// is a key exchange pending.
   291  	writeMu   sync.Mutex
   292  	sentClose bool
   293  
   294  	// packetPool has a buffer for each extended channel ID to
   295  	// save allocations during writes.
   296  	packetPool map[uint32][]byte
   297  
   298  	// hasClosed makes Close() idempotent. Only
   299  	// the first invocation of Close() has any
   300  	// effect; the result return nil immediately.
   301  	hasClosed int32
   302  
   303  	// idleR provides a means
   304  	// for ssh.Channel users to check how
   305  	// many nanoseconds have elapsed since the last
   306  	// error-free read. It is safe for
   307  	// use by multiple goroutines. Users
   308  	// should call SetIdleDur() and BeginAttempt() on it to before
   309  	// any subsequent calls to TimedOut().
   310  	idleR *IdleTimer
   311  
   312  	// idleW is for writes, idleR is for reads.
   313  	idleW *IdleTimer
   314  
   315  	halt *Halter
   316  }
   317  
   318  // writePacket sends a packet. If the packet is a channel close, it updates
   319  // sentClose. This method takes the lock c.writeMu.
   320  func (c *channel) writePacket(packet []byte) error {
   321  	c.writeMu.Lock()
   322  	if c.sentClose {
   323  		c.writeMu.Unlock()
   324  		return io.EOF // TestClientWriteEOF depends on this being io.EOF
   325  	}
   326  	c.sentClose = (packet[0] == msgChannelClose)
   327  	err := c.mux.conn.writePacket(packet)
   328  	if err == nil {
   329  		c.idleW.AttemptOK()
   330  	}
   331  	c.writeMu.Unlock()
   332  	return err
   333  }
   334  
   335  func (c *channel) sendMessage(msg interface{}) error {
   336  	if debugMux {
   337  		log.Printf("send(%d): %#v", c.mux.chanList.offset, msg)
   338  	}
   339  
   340  	p := Marshal(msg)
   341  	binary.BigEndian.PutUint32(p[1:], c.remoteId)
   342  	return c.writePacket(p)
   343  }
   344  
   345  // WriteExtended writes data to a specific extended stream. These streams are
   346  // used, for example, for stderr.
   347  func (c *channel) WriteExtended(data []byte, extendedCode uint32) (n int, err error) {
   348  	c.idleW.BeginAttempt()
   349  	defer func() {
   350  		if err == nil {
   351  			c.idleW.AttemptOK()
   352  		}
   353  	}()
   354  	if c.sentEOF {
   355  		return 0, io.EOF
   356  	}
   357  	// 1 byte message type, 4 bytes remoteId, 4 bytes data length
   358  	opCode := byte(msgChannelData)
   359  	headerLength := uint32(9)
   360  	if extendedCode > 0 {
   361  		headerLength += 4
   362  		opCode = msgChannelExtendedData
   363  	}
   364  
   365  	c.writeMu.Lock()
   366  	packet := c.packetPool[extendedCode]
   367  	// We don't remove the buffer from packetPool, so
   368  	// WriteExtended calls from different goroutines will be
   369  	// flagged as errors by the race detector.
   370  	c.writeMu.Unlock()
   371  
   372  	for len(data) > 0 {
   373  		space := min(c.maxRemotePayload, len(data))
   374  		if space, err = c.remoteWin.reserve(space); err != nil {
   375  			return n, err
   376  		}
   377  		c.idleW.AttemptOK()
   378  		if want := headerLength + space; uint32(cap(packet)) < want {
   379  			packet = make([]byte, want)
   380  		} else {
   381  			packet = packet[:want]
   382  		}
   383  
   384  		todo := data[:space]
   385  
   386  		packet[0] = opCode
   387  		binary.BigEndian.PutUint32(packet[1:], c.remoteId)
   388  		if extendedCode > 0 {
   389  			binary.BigEndian.PutUint32(packet[5:], uint32(extendedCode))
   390  		}
   391  		binary.BigEndian.PutUint32(packet[headerLength-4:], uint32(len(todo)))
   392  		copy(packet[headerLength:], todo)
   393  		if err = c.writePacket(packet); err != nil {
   394  			return n, err
   395  		}
   396  		c.idleW.AttemptOK()
   397  
   398  		n += len(todo)
   399  		data = data[len(todo):]
   400  	}
   401  
   402  	c.writeMu.Lock()
   403  	c.packetPool[extendedCode] = packet
   404  	c.writeMu.Unlock()
   405  
   406  	return n, err
   407  }
   408  
   409  func (c *channel) handleData(packet []byte) error {
   410  	headerLen := 9
   411  	isExtendedData := packet[0] == msgChannelExtendedData
   412  	if isExtendedData {
   413  		headerLen = 13
   414  	}
   415  	if len(packet) < headerLen {
   416  		// malformed data packet
   417  		return parseError(packet[0])
   418  	}
   419  
   420  	var extended uint32
   421  	if isExtendedData {
   422  		extended = binary.BigEndian.Uint32(packet[5:])
   423  	}
   424  
   425  	length := binary.BigEndian.Uint32(packet[headerLen-4 : headerLen])
   426  	if length == 0 {
   427  		return nil
   428  	}
   429  	if length > c.maxIncomingPayload {
   430  		// TODO(hanwen): should send Disconnect?
   431  		return errors.New("ssh: incoming packet exceeds maximum payload size")
   432  	}
   433  
   434  	data := packet[headerLen:]
   435  	if length != uint32(len(data)) {
   436  		return errors.New("ssh: wrong packet length")
   437  	}
   438  
   439  	c.windowMu.Lock()
   440  	if c.myWindow < length {
   441  		c.windowMu.Unlock()
   442  		// TODO(hanwen): should send Disconnect with reason?
   443  		return errors.New("ssh: remote side wrote too much")
   444  	}
   445  	c.myWindow -= length
   446  	c.windowMu.Unlock()
   447  
   448  	if extended == 1 {
   449  		c.extPending.write(data)
   450  	} else if extended > 0 {
   451  		// discard other extended data.
   452  	} else {
   453  		c.pending.write(data)
   454  	}
   455  	return nil
   456  }
   457  
   458  func (c *channel) adjustWindow(n uint32) error {
   459  	c.windowMu.Lock()
   460  	// Since myWindow is managed on our side, and can never exceed
   461  	// the initial window setting, we don't worry about overflow.
   462  	c.myWindow += uint32(n)
   463  	c.windowMu.Unlock()
   464  	return c.sendMessage(windowAdjustMsg{
   465  		AdditionalBytes: uint32(n),
   466  	})
   467  }
   468  
   469  func (c *channel) ReadExtended(data []byte, extended uint32) (n int, err error) {
   470  	c.idleR.BeginAttempt()
   471  	switch extended {
   472  	case 1:
   473  		n, err = c.extPending.Read(data)
   474  	case 0:
   475  		n, err = c.pending.Read(data)
   476  	default:
   477  		return 0, fmt.Errorf("ssh: extended code %d unimplemented", extended)
   478  	}
   479  	if err == nil {
   480  		c.idleR.AttemptOK()
   481  	}
   482  
   483  	if n > 0 {
   484  		err = c.adjustWindow(uint32(n))
   485  		// sendWindowAdjust can return io.EOF if the remote
   486  		// peer has closed the connection, however we want to
   487  		// defer forwarding io.EOF to the caller of Read until
   488  		// the buffer has been drained.
   489  		if n > 0 && err == io.EOF {
   490  			err = nil
   491  		}
   492  	}
   493  
   494  	return n, err
   495  }
   496  
   497  func (c *channel) close() {
   498  	c.pending.eof()
   499  	c.extPending.eof()
   500  	close(c.msg)
   501  	close(c.incomingRequests)
   502  	c.writeMu.Lock()
   503  	// This is not necessary for a normal channel teardown, but if
   504  	// there was another error, it is.
   505  	c.sentClose = true
   506  	c.writeMu.Unlock()
   507  	// Unblock writers.
   508  	c.remoteWin.close()
   509  	c.halt.RequestStop()
   510  	c.halt.MarkDone()
   511  	c.idleR.Stop()
   512  	c.idleW.Stop()
   513  }
   514  
   515  func (c *channel) timeout() {
   516  	c.pending.timeout()
   517  	c.extPending.timeout()
   518  	// Unblock writers.
   519  	c.remoteWin.timeout()
   520  	mt, ok := c.mux.conn.(HasTimeout)
   521  	if ok {
   522  		mt.timeout() // unblock goroutines stuck in *memTransport
   523  	}
   524  }
   525  
   526  // responseMessageReceived is called when a success or failure message is
   527  // received on a channel to check that such a message is reasonable for the
   528  // given channel.
   529  func (c *channel) responseMessageReceived() error {
   530  	if c.direction == channelInbound {
   531  		return errors.New("ssh: channel response message received on inbound channel")
   532  	}
   533  	if c.decided {
   534  		return errors.New("ssh: duplicate response received for channel")
   535  	}
   536  	c.decided = true
   537  	return nil
   538  }
   539  
   540  func (c *channel) handlePacket(packet []byte) error {
   541  	c.idleR.AttemptOK()
   542  	switch packet[0] {
   543  	case msgChannelData, msgChannelExtendedData:
   544  		return c.handleData(packet)
   545  	case msgChannelClose:
   546  		c.sendMessage(channelCloseMsg{PeersId: c.remoteId})
   547  		c.mux.chanList.remove(c.localId)
   548  		c.close()
   549  		return nil
   550  	case msgChannelEOF:
   551  		// RFC 4254 is mute on how EOF affects dataExt messages but
   552  		// it is logical to signal EOF at the same time.
   553  		c.extPending.eof()
   554  		c.pending.eof()
   555  		return nil
   556  	}
   557  
   558  	decoded, err := decode(packet)
   559  	if err != nil {
   560  		return err
   561  	}
   562  
   563  	reqStopCh := c.halt.ReqStopChan()
   564  	var reqStopMux chan struct{}
   565  	if c.mux.halt != nil {
   566  		reqStopMux = c.mux.halt.ReqStopChan()
   567  	}
   568  
   569  	switch msg := decoded.(type) {
   570  	case *channelOpenFailureMsg:
   571  		if err := c.responseMessageReceived(); err != nil {
   572  			return err
   573  		}
   574  		c.mux.chanList.remove(msg.PeersId)
   575  		select {
   576  		case c.msg <- msg:
   577  		case <-reqStopMux:
   578  			return io.EOF
   579  		case <-reqStopCh:
   580  			return io.EOF
   581  		}
   582  	case *channelOpenConfirmMsg:
   583  		if err := c.responseMessageReceived(); err != nil {
   584  			return err
   585  		}
   586  		if msg.MaxPacketSize < minPacketLength || msg.MaxPacketSize > 1<<31 {
   587  			return fmt.Errorf("ssh: invalid MaxPacketSize %d from peer", msg.MaxPacketSize)
   588  		}
   589  		c.remoteId = msg.MyId
   590  		c.maxRemotePayload = msg.MaxPacketSize
   591  		c.remoteWin.add(msg.MyWindow)
   592  		select {
   593  		case c.msg <- msg:
   594  		case <-reqStopMux:
   595  			return io.EOF
   596  		case <-reqStopCh:
   597  			return io.EOF
   598  		}
   599  	case *windowAdjustMsg:
   600  		if !c.remoteWin.add(msg.AdditionalBytes) {
   601  			return fmt.Errorf("ssh: invalid window update for %d bytes", msg.AdditionalBytes)
   602  		}
   603  	case *channelRequestMsg:
   604  		req := Request{
   605  			Type:      msg.Request,
   606  			WantReply: msg.WantReply,
   607  			Payload:   msg.RequestSpecificData,
   608  			ch:        c,
   609  		}
   610  		select {
   611  		case c.incomingRequests <- &req:
   612  		case <-reqStopMux:
   613  			return io.EOF
   614  		case <-reqStopCh:
   615  			return io.EOF
   616  		}
   617  	default:
   618  		select {
   619  		case c.msg <- msg:
   620  		case <-reqStopMux:
   621  			return io.EOF
   622  		case <-reqStopCh:
   623  			return io.EOF
   624  		}
   625  	}
   626  	return nil
   627  }
   628  
   629  func (m *mux) newChannel(chanType string, direction channelDirection, extraData []byte) *channel {
   630  	idleR, idleW := NewIdleTimer(nil, 0), NewIdleTimer(nil, 0)
   631  	ch := &channel{
   632  		remoteWin:        window{Cond: newCond(), idle: idleR},
   633  		myWindow:         channelWindowSize,
   634  		pending:          newBuffer(idleR),
   635  		extPending:       newBuffer(idleR),
   636  		direction:        direction,
   637  		incomingRequests: make(chan *Request, chanSize),
   638  		msg:              make(chan interface{}, chanSize),
   639  		chanType:         chanType,
   640  		extraData:        extraData,
   641  		mux:              m,
   642  		packetPool:       make(map[uint32][]byte),
   643  		idleR:            idleR,
   644  		idleW:            idleW,
   645  		halt:             NewHalter(),
   646  	}
   647  	idleR.AddTimeoutCallback(ch.timeout)
   648  	idleW.AddTimeoutCallback(ch.timeout)
   649  	ch.localId = m.chanList.add(ch)
   650  	return ch
   651  }
   652  
   653  var errUndecided = errors.New("ssh: must Accept or Reject channel")
   654  var errDecidedAlready = errors.New("ssh: can call Accept or Reject only once")
   655  
   656  type extChannel struct {
   657  	code uint32
   658  	ch   *channel
   659  }
   660  
   661  func (e *extChannel) Write(data []byte) (n int, err error) {
   662  	return e.ch.WriteExtended(data, e.code)
   663  }
   664  
   665  func (e *extChannel) Read(data []byte) (n int, err error) {
   666  	return e.ch.ReadExtended(data, e.code)
   667  }
   668  
   669  func (c *channel) Accept() (Channel, <-chan *Request, error) {
   670  	if c.decided {
   671  		return nil, nil, errDecidedAlready
   672  	}
   673  	c.maxIncomingPayload = channelMaxPacket
   674  	confirm := channelOpenConfirmMsg{
   675  		PeersId:       c.remoteId,
   676  		MyId:          c.localId,
   677  		MyWindow:      c.myWindow,
   678  		MaxPacketSize: c.maxIncomingPayload,
   679  	}
   680  	c.decided = true
   681  	if err := c.sendMessage(confirm); err != nil {
   682  		return nil, nil, err
   683  	}
   684  
   685  	return c, c.incomingRequests, nil
   686  }
   687  
   688  func (ch *channel) Reject(reason RejectionReason, message string) error {
   689  	if ch.decided {
   690  		return errDecidedAlready
   691  	}
   692  	reject := channelOpenFailureMsg{
   693  		PeersId:  ch.remoteId,
   694  		Reason:   reason,
   695  		Message:  message,
   696  		Language: "en",
   697  	}
   698  	ch.decided = true
   699  	ch.idleR.Halt.RequestStop()
   700  	ch.idleW.Halt.RequestStop()
   701  
   702  	return ch.sendMessage(reject)
   703  }
   704  
   705  func (ch *channel) Read(data []byte) (int, error) {
   706  	if !ch.decided {
   707  		return 0, errUndecided
   708  	}
   709  	return ch.ReadExtended(data, 0)
   710  }
   711  
   712  func (ch *channel) Write(data []byte) (int, error) {
   713  	if !ch.decided {
   714  		return 0, errUndecided
   715  	}
   716  	return ch.WriteExtended(data, 0)
   717  }
   718  
   719  func (ch *channel) CloseWrite() error {
   720  	if !ch.decided {
   721  		return errUndecided
   722  	}
   723  	ch.sentEOF = true
   724  	return ch.sendMessage(channelEOFMsg{
   725  		PeersId: ch.remoteId})
   726  }
   727  
   728  func (ch *channel) Close() error {
   729  	if !atomic.CompareAndSwapInt32(&ch.hasClosed, 0, 1) {
   730  		// idempotent Close
   731  		return nil
   732  	}
   733  	ch.idleR.Halt.RequestStop()
   734  	ch.idleW.Halt.RequestStop()
   735  	ch.halt.RequestStop()
   736  	ch.halt.MarkDone()
   737  
   738  	if !ch.decided {
   739  		return errUndecided
   740  	}
   741  
   742  	return ch.sendMessage(channelCloseMsg{
   743  		PeersId: ch.remoteId})
   744  }
   745  
   746  // Extended returns an io.ReadWriter that sends and receives data on the given,
   747  // SSH extended stream. Such streams are used, for example, for stderr.
   748  func (ch *channel) Extended(code uint32) io.ReadWriter {
   749  	if !ch.decided {
   750  		return nil
   751  	}
   752  	return &extChannel{code, ch}
   753  }
   754  
   755  func (ch *channel) Stderr() io.ReadWriter {
   756  	return ch.Extended(1)
   757  }
   758  
   759  // Done returns the mux's halt.ReqStopChan(), so
   760  // it lasts until the connection is lost. Use
   761  // GetHalter() below to get a Channel specific
   762  // done channel.
   763  func (ch *channel) Done() <-chan struct{} {
   764  	if ch.mux.halt != nil {
   765  		return ch.mux.halt.ReqStopChan()
   766  	}
   767  	return nil
   768  }
   769  
   770  // GetHalter returns the channel ch specific Halter.
   771  func (ch *channel) GetHalter() *Halter {
   772  	return ch.halt
   773  }
   774  
   775  func (ch *channel) SendRequest(name string, wantReply bool, payload []byte) (bool, error) {
   776  	if !ch.decided {
   777  		return false, errUndecided
   778  	}
   779  
   780  	if wantReply {
   781  		ch.sentRequestMu.Lock()
   782  		defer ch.sentRequestMu.Unlock()
   783  	}
   784  
   785  	msg := channelRequestMsg{
   786  		PeersId:             ch.remoteId,
   787  		Request:             name,
   788  		WantReply:           wantReply,
   789  		RequestSpecificData: payload,
   790  	}
   791  
   792  	if err := ch.sendMessage(msg); err != nil {
   793  		return false, err
   794  	}
   795  	var reqStopMux chan struct{}
   796  	if ch.mux.halt != nil {
   797  		reqStopMux = ch.mux.halt.ReqStopChan()
   798  	}
   799  	reqStopCh := ch.halt.ReqStopChan()
   800  
   801  	if wantReply {
   802  		select {
   803  		case <-reqStopMux:
   804  			return false, io.EOF
   805  		case <-reqStopCh:
   806  			return false, io.EOF
   807  		case m, ok := (<-ch.msg):
   808  			if !ok {
   809  				return false, io.EOF
   810  			}
   811  			switch m.(type) {
   812  			case *channelRequestFailureMsg:
   813  				return false, nil
   814  			case *channelRequestSuccessMsg:
   815  				return true, nil
   816  			default:
   817  				return false, fmt.Errorf("ssh: unexpected response to channel request: %#v", m)
   818  			}
   819  
   820  		}
   821  
   822  	}
   823  
   824  	return false, nil
   825  }
   826  
   827  // ackRequest either sends an ack or nack to the channel request.
   828  func (ch *channel) ackRequest(ok bool) error {
   829  	if !ch.decided {
   830  		return errUndecided
   831  	}
   832  
   833  	var msg interface{}
   834  	if !ok {
   835  		msg = channelRequestFailureMsg{
   836  			PeersId: ch.remoteId,
   837  		}
   838  	} else {
   839  		msg = channelRequestSuccessMsg{
   840  			PeersId: ch.remoteId,
   841  		}
   842  	}
   843  	return ch.sendMessage(msg)
   844  }
   845  
   846  func (ch *channel) ChannelType() string {
   847  	return ch.chanType
   848  }
   849  
   850  func (ch *channel) ExtraData() []byte {
   851  	return ch.extraData
   852  }
   853  
   854  // net.Conn compat:
   855  
   856  type chanAddr struct {
   857  	name string
   858  }
   859  
   860  // name of the network (for example, "tcp", "udp")
   861  func (c *chanAddr) Network() string {
   862  	return "ssh-channel"
   863  }
   864  
   865  // string form of address (for example, "192.0.2.1:25", "[2001:db8::1]:80")
   866  func (c *chanAddr) String() string {
   867  	return c.name
   868  }
   869  
   870  var sshChanAddr chanAddr
   871  
   872  // LocalAddr returns the local network address.
   873  func (c *channel) LocalAddr() net.Addr {
   874  	return &sshChanAddr
   875  }
   876  
   877  // RemoteAddr returns the remote network address.
   878  func (c *channel) RemoteAddr() net.Addr {
   879  	return &sshChanAddr
   880  }
   881  
   882  // SetReadIdleTimeout establishes a new timeout duration
   883  // and starts the timing machinery off and running.
   884  // A dur of zero will disable timeouts.
   885  //
   886  // SetReadIdleTimeout() will always reset and
   887  // clear any raised timeout left over from prior use.
   888  // Any new timer (if dur > 0) begins from the return of
   889  // the SetReadIdleTimeout() invocation.
   890  //
   891  func (c *channel) SetReadIdleTimeout(dur time.Duration) error {
   892  	c.idleR.SetIdleTimeout(dur)
   893  	return nil
   894  }
   895  
   896  // SetWriteIdleTimeout establishes a new timeout duration
   897  // and starts the timing machinery off and running.
   898  // A dur of zero will disable timeouts.
   899  //
   900  // SetWriteIdleTimeout() will always reset and
   901  // clear any raised timeout left over from prior use.
   902  // Any new timer (if dur > 0) begins from the return of
   903  // the SetWriteIdleTimeout() invocation.
   904  //
   905  func (c *channel) SetWriteIdleTimeout(dur time.Duration) error {
   906  	c.idleW.SetIdleTimeout(dur)
   907  	return nil
   908  }
   909  
   910  // SetIdleTimeout does both SetReadIdleTimeout and SetWriteIdleTimeout.
   911  func (c *channel) SetIdleTimeout(dur time.Duration) error {
   912  	c.idleR.SetIdleTimeout(dur)
   913  	c.idleW.SetIdleTimeout(dur)
   914  	return nil
   915  }
   916  
   917  func (c *channel) SetReadDeadline(t time.Time) error {
   918  	return c.setDeadline(t, true)
   919  }
   920  
   921  func (c *channel) SetWriteDeadline(t time.Time) error {
   922  	return c.setDeadline(t, false)
   923  }
   924  
   925  func (c *channel) SetDeadline(t time.Time) error {
   926  	c.setDeadline(t, false)
   927  	return c.setDeadline(t, true)
   928  }
   929  
   930  func (c *channel) setDeadline(t time.Time, reads bool) error {
   931  	if t.IsZero() {
   932  		if reads {
   933  			c.idleR.SetOneshotIdleTimeout(0)
   934  		} else {
   935  			c.idleW.SetOneshotIdleTimeout(0)
   936  		}
   937  	} else {
   938  		var dur time.Duration
   939  		now := time.Now()
   940  		if !now.Before(t) {
   941  			// they are late, but they don't want to block,
   942  			// or they would have sent us a zero time.
   943  			// So set a minimal timeout that will unblock
   944  			// any reads immediately.
   945  			dur = time.Nanosecond
   946  		} else {
   947  			dur = t.Sub(now)
   948  		}
   949  		if reads {
   950  			c.idleR.SetOneshotIdleTimeout(dur)
   951  		} else {
   952  			c.idleW.SetOneshotIdleTimeout(dur)
   953  		}
   954  	}
   955  	return nil
   956  }
   957  
   958  func (c *channel) GetReadIdleTimer() *IdleTimer {
   959  	return c.idleR
   960  }
   961  
   962  func (c *channel) GetWriteIdleTimer() *IdleTimer {
   963  	return c.idleW
   964  }
   965  
   966  // Status observes the goroutine lifecycle.
   967  func (c *channel) Status() (r *RunStatus) {
   968  	r = &RunStatus{}
   969  	r.Ready = c.idleR.Halt.IsReady()
   970  	r.StopRequested = c.idleR.Halt.IsStopRequested()
   971  	r.Done = c.idleR.Halt.IsDone()
   972  	if r.Done {
   973  		r.Err = c.idleR.Halt.Err()
   974  	}
   975  	r.DoneCh = c.idleR.Halt.DoneChan()
   976  	return
   977  }