mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2024-12-27 18:19:17 +00:00
144 lines
3.3 KiB
Go
144 lines
3.3 KiB
Go
// Copyright 2013 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package ssh
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
)
|
|
|
|
// OpenChannelError is returned if the other side rejects an
|
|
// OpenChannel request.
|
|
type OpenChannelError struct {
|
|
Reason RejectionReason
|
|
Message string
|
|
}
|
|
|
|
func (e *OpenChannelError) Error() string {
|
|
return fmt.Sprintf("ssh: rejected: %s (%s)", e.Reason, e.Message)
|
|
}
|
|
|
|
// ConnMetadata holds metadata for the connection.
|
|
type ConnMetadata interface {
|
|
// User returns the user ID for this connection.
|
|
User() string
|
|
|
|
// SessionID returns the session hash, also denoted by H.
|
|
SessionID() []byte
|
|
|
|
// ClientVersion returns the client's version string as hashed
|
|
// into the session ID.
|
|
ClientVersion() []byte
|
|
|
|
// ServerVersion returns the server's version string as hashed
|
|
// into the session ID.
|
|
ServerVersion() []byte
|
|
|
|
// RemoteAddr returns the remote address for this connection.
|
|
RemoteAddr() net.Addr
|
|
|
|
// LocalAddr returns the local address for this connection.
|
|
LocalAddr() net.Addr
|
|
}
|
|
|
|
// Conn represents an SSH connection for both server and client roles.
|
|
// Conn is the basis for implementing an application layer, such
|
|
// as ClientConn, which implements the traditional shell access for
|
|
// clients.
|
|
type Conn interface {
|
|
ConnMetadata
|
|
|
|
// SendRequest sends a global request, and returns the
|
|
// reply. If wantReply is true, it returns the response status
|
|
// and payload. See also RFC4254, section 4.
|
|
SendRequest(name string, wantReply bool, payload []byte) (bool, []byte, error)
|
|
|
|
// OpenChannel tries to open an channel. If the request is
|
|
// rejected, it returns *OpenChannelError. On success it returns
|
|
// the SSH Channel and a Go channel for incoming, out-of-band
|
|
// requests. The Go channel must be serviced, or the
|
|
// connection will hang.
|
|
OpenChannel(name string, data []byte) (Channel, <-chan *Request, error)
|
|
|
|
// Close closes the underlying network connection
|
|
Close() error
|
|
|
|
// Wait blocks until the connection has shut down, and returns the
|
|
// error causing the shutdown.
|
|
Wait() error
|
|
|
|
// TODO(hanwen): consider exposing:
|
|
// RequestKeyChange
|
|
// Disconnect
|
|
}
|
|
|
|
// DiscardRequests consumes and rejects all requests from the
|
|
// passed-in channel.
|
|
func DiscardRequests(in <-chan *Request) {
|
|
for req := range in {
|
|
if req.WantReply {
|
|
req.Reply(false, nil)
|
|
}
|
|
}
|
|
}
|
|
|
|
// A connection represents an incoming connection.
|
|
type connection struct {
|
|
transport *handshakeTransport
|
|
sshConn
|
|
|
|
// The connection protocol.
|
|
*mux
|
|
}
|
|
|
|
func (c *connection) Close() error {
|
|
return c.sshConn.conn.Close()
|
|
}
|
|
|
|
// sshconn provides net.Conn metadata, but disallows direct reads and
|
|
// writes.
|
|
type sshConn struct {
|
|
conn net.Conn
|
|
|
|
user string
|
|
sessionID []byte
|
|
clientVersion []byte
|
|
serverVersion []byte
|
|
}
|
|
|
|
func dup(src []byte) []byte {
|
|
dst := make([]byte, len(src))
|
|
copy(dst, src)
|
|
return dst
|
|
}
|
|
|
|
func (c *sshConn) User() string {
|
|
return c.user
|
|
}
|
|
|
|
func (c *sshConn) RemoteAddr() net.Addr {
|
|
return c.conn.RemoteAddr()
|
|
}
|
|
|
|
func (c *sshConn) Close() error {
|
|
return c.conn.Close()
|
|
}
|
|
|
|
func (c *sshConn) LocalAddr() net.Addr {
|
|
return c.conn.LocalAddr()
|
|
}
|
|
|
|
func (c *sshConn) SessionID() []byte {
|
|
return dup(c.sessionID)
|
|
}
|
|
|
|
func (c *sshConn) ClientVersion() []byte {
|
|
return dup(c.clientVersion)
|
|
}
|
|
|
|
func (c *sshConn) ServerVersion() []byte {
|
|
return dup(c.serverVersion)
|
|
}
|