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 // PartialSuccessMethods returns the ordered list of 46 // authentication methods that returned ErrPartialSuccess. 47 // It can be used inside callbacks to find if a multi-step 48 // authentication is done using the correct sequence and to 49 // return the authentication methods that can continue 50 PartialSuccessMethods() []string 51} 52 53// Conn represents an SSH connection for both server and client roles. 54// Conn is the basis for implementing an application layer, such 55// as ClientConn, which implements the traditional shell access for 56// clients. 57type Conn interface { 58 ConnMetadata 59 60 // SendRequest sends a global request, and returns the 61 // reply. If wantReply is true, it returns the response status 62 // and payload. See also RFC4254, section 4. 63 SendRequest(name string, wantReply bool, payload []byte) (bool, []byte, error) 64 65 // OpenChannel tries to open an channel. If the request is 66 // rejected, it returns *OpenChannelError. On success it returns 67 // the SSH Channel and a Go channel for incoming, out-of-band 68 // requests. The Go channel must be serviced, or the 69 // connection will hang. 70 OpenChannel(name string, data []byte) (Channel, <-chan *Request, error) 71 72 // Close closes the underlying network connection 73 Close() error 74 75 // Wait blocks until the connection has shut down, and returns the 76 // error causing the shutdown. 77 Wait() error 78 79 // TODO(hanwen): consider exposing: 80 // RequestKeyChange 81 // Disconnect 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 partialSuccessMethods []string 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) PartialSuccessMethods() []string { 126 return c.partialSuccessMethods 127} 128 129func (c *sshConn) User() string { 130 return c.user 131} 132 133func (c *sshConn) RemoteAddr() net.Addr { 134 return c.conn.RemoteAddr() 135} 136 137func (c *sshConn) Close() error { 138 return c.conn.Close() 139} 140 141func (c *sshConn) LocalAddr() net.Addr { 142 return c.conn.LocalAddr() 143} 144 145func (c *sshConn) SessionID() []byte { 146 return dup(c.sessionID) 147} 148 149func (c *sshConn) ClientVersion() []byte { 150 return dup(c.clientVersion) 151} 152 153func (c *sshConn) ServerVersion() []byte { 154 return dup(c.serverVersion) 155} 156