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
  5package ssh
  6
  7import (
  8	"fmt"
  9	"net"
 10)
 11
 12// OpenChannelError is returned if the other side rejects an
 13// OpenChannel request.
 14type OpenChannelError struct {
 15	Reason  RejectionReason
 16	Message string
 17}
 18
 19func (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.
 24type 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.
 50type 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 RFC 4254, 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// AlgorithmsConnMetadata is a ConnMetadata that can return the algorithms
 78// negotiated between client and server.
 79type AlgorithmsConnMetadata interface {
 80	ConnMetadata
 81	Algorithms() NegotiatedAlgorithms
 82}
 83
 84// DiscardRequests consumes and rejects all requests from the
 85// passed-in channel.
 86func DiscardRequests(in <-chan *Request) {
 87	for req := range in {
 88		if req.WantReply {
 89			req.Reply(false, nil)
 90		}
 91	}
 92}
 93
 94// A connection represents an incoming connection.
 95type connection struct {
 96	transport *handshakeTransport
 97	sshConn
 98
 99	// The connection protocol.
100	*mux
101}
102
103func (c *connection) Close() error {
104	return c.sshConn.conn.Close()
105}
106
107// sshConn provides net.Conn metadata, but disallows direct reads and
108// writes.
109type sshConn struct {
110	conn net.Conn
111
112	user          string
113	sessionID     []byte
114	clientVersion []byte
115	serverVersion []byte
116	algorithms    NegotiatedAlgorithms
117}
118
119func dup(src []byte) []byte {
120	dst := make([]byte, len(src))
121	copy(dst, src)
122	return dst
123}
124
125func (c *sshConn) User() string {
126	return c.user
127}
128
129func (c *sshConn) RemoteAddr() net.Addr {
130	return c.conn.RemoteAddr()
131}
132
133func (c *sshConn) Close() error {
134	return c.conn.Close()
135}
136
137func (c *sshConn) LocalAddr() net.Addr {
138	return c.conn.LocalAddr()
139}
140
141func (c *sshConn) SessionID() []byte {
142	return dup(c.sessionID)
143}
144
145func (c *sshConn) ClientVersion() []byte {
146	return dup(c.clientVersion)
147}
148
149func (c *sshConn) ServerVersion() []byte {
150	return dup(c.serverVersion)
151}
152
153func (c *sshConn) Algorithms() NegotiatedAlgorithms {
154	return c.algorithms
155}