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 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.
79 type AlgorithmsConnMetadata interface {
80 ConnMetadata
81 Algorithms() NegotiatedAlgorithms
82 }
83 84 // DiscardRequests consumes and rejects all requests from the
85 // passed-in channel.
86 func 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.
95 type connection struct {
96 transport *handshakeTransport
97 sshConn
98 99 // The connection protocol.
100 *mux
101 }
102 103 func (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.
109 type sshConn struct {
110 conn net.Conn
111 112 user string
113 sessionID []byte
114 clientVersion []byte
115 serverVersion []byte
116 algorithms NegotiatedAlgorithms
117 }
118 119 func dup(src []byte) []byte {
120 dst := make([]byte, len(src))
121 copy(dst, src)
122 return dst
123 }
124 125 func (c *sshConn) User() string {
126 return c.user
127 }
128 129 func (c *sshConn) RemoteAddr() net.Addr {
130 return c.conn.RemoteAddr()
131 }
132 133 func (c *sshConn) Close() error {
134 return c.conn.Close()
135 }
136 137 func (c *sshConn) LocalAddr() net.Addr {
138 return c.conn.LocalAddr()
139 }
140 141 func (c *sshConn) SessionID() []byte {
142 return dup(c.sessionID)
143 }
144 145 func (c *sshConn) ClientVersion() []byte {
146 return dup(c.clientVersion)
147 }
148 149 func (c *sshConn) ServerVersion() []byte {
150 return dup(c.serverVersion)
151 }
152 153 func (c *sshConn) Algorithms() NegotiatedAlgorithms {
154 return c.algorithms
155 }
156