github.com/psiphon-labs/psiphon-tunnel-core@v2.0.28+incompatible/psiphon/common/crypto/ssh/connection.go (about)

     1  // Copyright 2013 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  	"fmt"
     9  	"net"
    10  )
    11  
    12  // OpenChannelError is returned if the other side rejects an
    13  // OpenChannel request.
    14  type OpenChannelError struct {
    15  	Reason  RejectionReason
    16  	Message string
    17  }
    18  
    19  func (e *OpenChannelError) Error() string {
    20  	return fmt.Sprintf("ssh: rejected: %s (%s)", e.Reason, e.Message)
    21  }
    22  
    23  // ConnMetadata holds metadata for the connection.
    24  type ConnMetadata interface {
    25  	// User returns the user ID for this connection.
    26  	User() string
    27  
    28  	// SessionID returns the session hash, also denoted by H.
    29  	SessionID() []byte
    30  
    31  	// ClientVersion returns the client's version string as hashed
    32  	// into the session ID.
    33  	ClientVersion() []byte
    34  
    35  	// ServerVersion returns the server's version string as hashed
    36  	// into the session ID.
    37  	ServerVersion() []byte
    38  
    39  	// RemoteAddr returns the remote address for this connection.
    40  	RemoteAddr() net.Addr
    41  
    42  	// LocalAddr returns the local address for this connection.
    43  	LocalAddr() net.Addr
    44  }
    45  
    46  // Conn represents an SSH connection for both server and client roles.
    47  // Conn is the basis for implementing an application layer, such
    48  // as ClientConn, which implements the traditional shell access for
    49  // clients.
    50  type Conn interface {
    51  	ConnMetadata
    52  
    53  	// SendRequest sends a global request, and returns the
    54  	// reply. If wantReply is true, it returns the response status
    55  	// and payload. See also RFC4254, section 4.
    56  	SendRequest(name string, wantReply bool, payload []byte) (bool, []byte, error)
    57  
    58  	// OpenChannel tries to open an channel. If the request is
    59  	// rejected, it returns *OpenChannelError. On success it returns
    60  	// the SSH Channel and a Go channel for incoming, out-of-band
    61  	// requests. The Go channel must be serviced, or the
    62  	// connection will hang.
    63  	OpenChannel(name string, data []byte) (Channel, <-chan *Request, error)
    64  
    65  	// Close closes the underlying network connection
    66  	Close() error
    67  
    68  	// Wait blocks until the connection has shut down, and returns the
    69  	// error causing the shutdown.
    70  	Wait() error
    71  
    72  	// TODO(hanwen): consider exposing:
    73  	//   RequestKeyChange
    74  	//   Disconnect
    75  }
    76  
    77  // DiscardRequests consumes and rejects all requests from the
    78  // passed-in channel.
    79  func DiscardRequests(in <-chan *Request) {
    80  	for req := range in {
    81  		if req.WantReply {
    82  			req.Reply(false, nil)
    83  		}
    84  	}
    85  }
    86  
    87  // A connection represents an incoming connection.
    88  type connection struct {
    89  	transport *handshakeTransport
    90  	sshConn
    91  
    92  	// The connection protocol.
    93  	*mux
    94  }
    95  
    96  func (c *connection) Close() error {
    97  	return c.sshConn.conn.Close()
    98  }
    99  
   100  // sshconn provides net.Conn metadata, but disallows direct reads and
   101  // writes.
   102  type sshConn struct {
   103  	conn net.Conn
   104  
   105  	user          string
   106  	sessionID     []byte
   107  	clientVersion []byte
   108  	serverVersion []byte
   109  }
   110  
   111  func dup(src []byte) []byte {
   112  	dst := make([]byte, len(src))
   113  	copy(dst, src)
   114  	return dst
   115  }
   116  
   117  func (c *sshConn) User() string {
   118  	return c.user
   119  }
   120  
   121  func (c *sshConn) RemoteAddr() net.Addr {
   122  	return c.conn.RemoteAddr()
   123  }
   124  
   125  func (c *sshConn) Close() error {
   126  	return c.conn.Close()
   127  }
   128  
   129  func (c *sshConn) LocalAddr() net.Addr {
   130  	return c.conn.LocalAddr()
   131  }
   132  
   133  func (c *sshConn) SessionID() []byte {
   134  	return dup(c.sessionID)
   135  }
   136  
   137  func (c *sshConn) ClientVersion() []byte {
   138  	return dup(c.clientVersion)
   139  }
   140  
   141  func (c *sshConn) ServerVersion() []byte {
   142  	return dup(c.serverVersion)
   143  }