ssh

package
v7.0.3+incompatible Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 11, 2017 License: MIT Imports: 48 Imported by: 16

README

xcryptossh

This is an evolution of golang.org/x/crypto/ssh to fix memory leaks, provide for graceful shutdown, and implement idle timeouts. It is not API backwards compatible, as it provides context.Context based cancellation.

New feature: idle timeouts

a) We would like to recognize when there has been no communication for some time on an ssh.Channel. So that reads and writes can timeout.

b) We would like to timeout reads and writes so that they don't hang forever, blocking and leaking a goroutine.

c) We would like to be able to send large files and only have these timeout when there is no activity, rather than continuous acitivity of long duration. A simple deadline estimate does not allow us to readily anticipate the work and time needed to send a big file.

d) We found that the net.Conn approach of providing deadlines does not serve case (c) above, and prohibits the implimentation of idle times while simultaneously using facilities such as io.Copy() on the stream, since the io.Copy will do multiple Reads/Writes. Each Read/Write may need a deadline adjustment, but io.Copy cannot do that for us. Therefore a more general means of establishing an idle timeout is required.

To answer these needs, a new API method on the ssh.Channel interface has been implemented, the SetIdleTimeout method. See the channel.go file. https://github.com/glycerine/xcryptossh/blob/master/channel.go#L91

package ssh

// A Channel is an ordered, reliable, flow-controlled, duplex stream
// that is multiplexed over an SSH connection.
type Channel interface {

    ...
	// SetIdleTimeout starts an idle timer on
	// that will cause them to timeout after dur.
	// A successful Read will bump the idle
	// timeout into the future. Successful writes
	// don't bump the timer because Write() to
	// a Channel will "succeed" in the sense of
	// returning a nil error long before they
	// reach the remote end (or not). Writes
	// are buffered internally. Hence write success
	// has no impact on idle timeout.
	//
	// Providing dur of 0 will disable the idle timeout.
	// Zero is the default until SetIdleTimeout() is called.
	//
	// SetIdleTimeout() will always reset and
	// clear any raised timeout left over from prior use.
	// Any new timer (if dur > 0) begins from the return of
	// the SetIdleTimeout() invocation.
	//
	// Idle timeouts are easier to use than deadlines,
	// as they don't need to be refreshed after
	// every read and write. Hence routines like io.Copy()
	// that makes many calls to Read() and Write()
	// can be leveraged, while still having a timeout in
	// the case of no activity.
	//
	// Moreover idle timeouts are more
	// efficient because we don't guess at a
	// deadline and then interrupt a perfectly
	// good ongoing copy that happens to be
	// taking a few seconds longer than our
	// guesstimate. We avoid the pain of trying
	// to restart long interrupted transfers that
	// were making fine progress.
	//
	SetIdleTimeout(dur time.Duration) error
}

See the tests in timeout_test.go for example use.

install

$ go get -t -u -v github.com/glycerine/xcryptossh/...

author

Jason E. Aten, Ph.D.

license

Licensed under the same BSD style license as the x/crypto/ssh code. See the LICENSE file.

current status

All functionality is working, but I still consider it experimental until I've gotten more feedback and experience with it. Please try it out and give feedback.

As of 2017 Aug 29:

Excellent. Tested on OSX and Linux.

All tests pass under -race. The tests no longer leak goroutines.

net.Conn limitations

ssh.Channel now impliments net.Conn, but there is a caveat that you should be aware of. Write() calls will return a nil error before data reaches the remote end.

Documentation

Overview

Package ssh implements an SSH client and server.

SSH is a transport security protocol, an authentication protocol and a family of application protocols. The most typical application level protocol is a remote shell and this is specifically implemented. However, the multiplexed nature of SSH is exposed to users that wish to support others.

References:

[PROTOCOL.certkeys]: http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.certkeys?rev=HEAD
[SSH-PARAMETERS]:    http://www.iana.org/assignments/ssh-parameters/ssh-parameters.xml#ssh-parameters-1

This package does not fall under the stability promise of the Go language itself, so its API may be changed when pressing needs arise.

Index

Examples

Constants

View Source
const (
	CertAlgoRSAv01      = "ssh-rsa-cert-v01@openssh.com"
	CertAlgoDSAv01      = "ssh-dss-cert-v01@openssh.com"
	CertAlgoECDSA256v01 = "ecdsa-sha2-nistp256-cert-v01@openssh.com"
	CertAlgoECDSA384v01 = "ecdsa-sha2-nistp384-cert-v01@openssh.com"
	CertAlgoECDSA521v01 = "ecdsa-sha2-nistp521-cert-v01@openssh.com"
	CertAlgoED25519v01  = "ssh-ed25519-cert-v01@openssh.com"
)

These constants from [PROTOCOL.certkeys] represent the algorithm names for certificate types supported by this package.

View Source
const (
	UserCert = 1
	HostCert = 2
)

Certificate types distinguish between host and user certificates. The values can be set in the CertType field of Certificate.

View Source
const (
	KeyAlgoRSA      = "ssh-rsa"
	KeyAlgoDSA      = "ssh-dss"
	KeyAlgoECDSA256 = "ecdsa-sha2-nistp256"
	KeyAlgoECDSA384 = "ecdsa-sha2-nistp384"
	KeyAlgoECDSA521 = "ecdsa-sha2-nistp521"
	KeyAlgoED25519  = "ssh-ed25519"
)

These constants represent the algorithm names for key types supported by this package.

View Source
const (
	VINTR         = 1
	VQUIT         = 2
	VERASE        = 3
	VKILL         = 4
	VEOF          = 5
	VEOL          = 6
	VEOL2         = 7
	VSTART        = 8
	VSTOP         = 9
	VSUSP         = 10
	VDSUSP        = 11
	VREPRINT      = 12
	VWERASE       = 13
	VLNEXT        = 14
	VFLUSH        = 15
	VSWTCH        = 16
	VSTATUS       = 17
	VDISCARD      = 18
	IGNPAR        = 30
	PARMRK        = 31
	INPCK         = 32
	ISTRIP        = 33
	INLCR         = 34
	IGNCR         = 35
	ICRNL         = 36
	IUCLC         = 37
	IXON          = 38
	IXANY         = 39
	IXOFF         = 40
	IMAXBEL       = 41
	ISIG          = 50
	ICANON        = 51
	XCASE         = 52
	ECHO          = 53
	ECHOE         = 54
	ECHOK         = 55
	ECHONL        = 56
	NOFLSH        = 57
	TOSTOP        = 58
	IEXTEN        = 59
	ECHOCTL       = 60
	ECHOKE        = 61
	PENDIN        = 62
	OPOST         = 70
	OLCUC         = 71
	ONLCR         = 72
	OCRNL         = 73
	ONOCR         = 74
	ONLRET        = 75
	CS7           = 90
	CS8           = 91
	PARENB        = 92
	PARODD        = 93
	TTY_OP_ISPEED = 128
	TTY_OP_OSPEED = 129
)

POSIX terminal mode flags as listed in RFC 4254 Section 8.

View Source
const CertTimeInfinity = 1<<64 - 1

CertTimeInfinity can be used for OpenSSHCertV01.ValidBefore to indicate that a certificate does not expire.

Variables

View Source
var ErrAlreadyClosed = fmt.Errorf("Chan already closed")
View Source
var ErrShutDown = fmt.Errorf("ssh: shutting down.")

Functions

func DiscardRequests

func DiscardRequests(ctx context.Context, in <-chan *Request, halt *Halter)

DiscardRequests consumes and rejects all requests from the passed-in channel.

func FingerprintLegacyMD5

func FingerprintLegacyMD5(pubKey PublicKey) string

FingerprintLegacyMD5 returns the user presentation of the key's fingerprint as described by RFC 4716 section 4.

func FingerprintSHA256

func FingerprintSHA256(pubKey PublicKey) string

FingerprintSHA256 returns the user presentation of the key's fingerprint as unpadded base64 encoded sha256 hash. This format was introduced from OpenSSH 6.8. https://www.openssh.com/txt/release-6.8 https://tools.ietf.org/html/rfc4648#section-3.2 (unpadded base64 encoding)

func MAD

func MAD(ctx context.Context, cancelctx context.CancelFunc, halt *Halter)

MAD provides a link between context.Context

and Halter.

MAD stands for mutual assured destruction. When ctx is cancelled, then halt will be too. When halt is done, then cancelctx will be called.

func Marshal

func Marshal(msg interface{}) []byte

Marshal serializes the message in msg to SSH wire format. The msg argument should be a struct or pointer to struct. If the first member has the "sshtype" tag set to a number in decimal, that number is prepended to the result. If the last of member has the "ssh" tag set to "rest", its contents are appended to the output.

func MarshalAuthorizedKey

func MarshalAuthorizedKey(key PublicKey) []byte

MarshalAuthorizedKey serializes key for inclusion in an OpenSSH authorized_keys file. The return value ends with newline.

func ParseDSAPrivateKey

func ParseDSAPrivateKey(der []byte) (*dsa.PrivateKey, error)

ParseDSAPrivateKey returns a DSA private key from its ASN.1 DER encoding, as specified by the OpenSSL DSA man page.

func ParseRawPrivateKey

func ParseRawPrivateKey(pemBytes []byte) (interface{}, error)

ParseRawPrivateKey returns a private key from a PEM encoded private key. It supports RSA (PKCS#1), DSA (OpenSSL), and ECDSA private keys.

func ParseRawPrivateKeyWithPassphrase

func ParseRawPrivateKeyWithPassphrase(pemBytes, passPhrase []byte) (interface{}, error)

ParseRawPrivateKeyWithPassphrase returns a private key decrypted with passphrase from a PEM encoded private key. If wrong passphrase, return x509.IncorrectPasswordError.

func Unmarshal

func Unmarshal(data []byte, out interface{}) error

Unmarshal parses data in SSH wire format into a structure. The out argument should be a pointer to struct. If the first member of the struct has the "sshtype" tag set to a '|'-separated set of numbers in decimal, the packet must start with one of those numbers. In case of error, Unmarshal returns a ParseError or UnexpectedMessageError.

Types

type AuthMethod

type AuthMethod interface {
	// contains filtered or unexported methods
}

An AuthMethod represents an instance of an RFC 4252 authentication method.

func KeyboardInteractive

func KeyboardInteractive(challenge KeyboardInteractiveChallenge) AuthMethod

KeyboardInteractive returns a AuthMethod using a prompt/response sequence controlled by the server.

func Password

func Password(secret string) AuthMethod

Password returns an AuthMethod using the given password.

func PasswordCallback

func PasswordCallback(prompt func() (secret string, err error)) AuthMethod

PasswordCallback returns an AuthMethod that uses a callback for fetching a password.

func PublicKeys

func PublicKeys(signers ...Signer) AuthMethod

PublicKeys returns an AuthMethod that uses the given key pairs.

Example
var hostKey ssh.PublicKey
// A public key may be used to authenticate against the remote
// server by using an unencrypted PEM-encoded private key file.
//
// If you have an encrypted private key, the crypto/x509 package
// can be used to decrypt it.
key, err := ioutil.ReadFile("/home/user/.ssh/id_rsa")
if err != nil {
	log.Fatalf("unable to read private key: %v", err)
}

// Create the Signer for this private key.
signer, err := ssh.ParsePrivateKey(key)
if err != nil {
	log.Fatalf("unable to parse private key: %v", err)
}

config := &ssh.ClientConfig{
	User: "user",
	Auth: []ssh.AuthMethod{
		// Use the PublicKeys method for remote authentication.
		ssh.PublicKeys(signer),
	},
	HostKeyCallback: ssh.FixedHostKey(hostKey),
}

// Connect to the remote server and perform the SSH handshake.
ctx := context.Background()
client, err := ssh.Dial(ctx, "tcp", "host.com:22", config)
if err != nil {
	log.Fatalf("unable to connect: %v", err)
}
defer client.Close()
Output:

func PublicKeysCallback

func PublicKeysCallback(getSigners func() (signers []Signer, err error)) AuthMethod

PublicKeysCallback returns an AuthMethod that runs the given function to obtain a list of key pairs.

func RetryableAuthMethod

func RetryableAuthMethod(auth AuthMethod, maxTries int) AuthMethod

RetryableAuthMethod is a decorator for other auth methods enabling them to be retried up to maxTries before considering that AuthMethod itself failed. If maxTries is <= 0, will retry indefinitely

This is useful for interactive clients using challenge/response type authentication (e.g. Keyboard-Interactive, Password, etc) where the user could mistype their response resulting in the server issuing a SSH_MSG_USERAUTH_FAILURE (rfc4252 #8 [password] and rfc4256 #3.4 [keyboard-interactive]); Without this decorator, the non-retryable AuthMethod would be removed from future consideration, and never tried again (and so the user would never be able to retry their entry).

type CertChecker

type CertChecker struct {
	// SupportedCriticalOptions lists the CriticalOptions that the
	// server application layer understands. These are only used
	// for user certificates.
	SupportedCriticalOptions []string

	// IsUserAuthority should return true if the key is recognized as an
	// authority for the given user certificate. This allows for
	// certificates to be signed by other certificates. This must be set
	// if this CertChecker will be checking user certificates.
	IsUserAuthority func(auth PublicKey) bool

	// IsHostAuthority should report whether the key is recognized as
	// an authority for this host. This allows for certificates to be
	// signed by other keys, and for those other keys to only be valid
	// signers for particular hostnames. This must be set if this
	// CertChecker will be checking host certificates.
	IsHostAuthority func(auth PublicKey, address string) bool

	// Clock is used for verifying time stamps. If nil, time.Now
	// is used.
	Clock func() time.Time

	// UserKeyFallback is called when CertChecker.Authenticate encounters a
	// public key that is not a certificate. It must implement validation
	// of user keys or else, if nil, all such keys are rejected.
	UserKeyFallback func(conn ConnMetadata, key PublicKey) (*Permissions, error)

	// HostKeyFallback is called when CertChecker.CheckHostKey encounters a
	// public key that is not a certificate. It must implement host key
	// validation or else, if nil, all such keys are rejected.
	HostKeyFallback HostKeyCallback

	// IsRevoked is called for each certificate so that revocation checking
	// can be implemented. It should return true if the given certificate
	// is revoked and false otherwise. If nil, no certificates are
	// considered to have been revoked.
	IsRevoked func(cert *Certificate) bool
}

CertChecker does the work of verifying a certificate. Its methods can be plugged into ClientConfig.HostKeyCallback and ServerConfig.PublicKeyCallback. For the CertChecker to work, minimally, the IsAuthority callback should be set.

func (*CertChecker) Authenticate

func (c *CertChecker) Authenticate(conn ConnMetadata, pubKey PublicKey) (*Permissions, error)

Authenticate checks a user certificate. Authenticate can be used as a value for ServerConfig.PublicKeyCallback.

func (*CertChecker) CheckCert

func (c *CertChecker) CheckCert(principal string, cert *Certificate) error

CheckCert checks CriticalOptions, ValidPrincipals, revocation, timestamp and the signature of the certificate.

func (*CertChecker) CheckHostKey

func (c *CertChecker) CheckHostKey(addr string, remote net.Addr, key PublicKey) error

CheckHostKey checks a host key certificate. This method can be plugged into ClientConfig.HostKeyCallback.

type Certificate

type Certificate struct {
	Nonce           []byte
	Key             PublicKey
	Serial          uint64
	CertType        uint32
	KeyId           string
	ValidPrincipals []string
	ValidAfter      uint64
	ValidBefore     uint64
	Permissions
	Reserved     []byte
	SignatureKey PublicKey
	Signature    *Signature
}

An Certificate represents an OpenSSH certificate as defined in [PROTOCOL.certkeys]?rev=1.8.

func (*Certificate) Marshal

func (c *Certificate) Marshal() []byte

Marshal serializes c into OpenSSH's wire format. It is part of the PublicKey interface.

func (*Certificate) SignCert

func (c *Certificate) SignCert(rand io.Reader, authority Signer) error

SignCert sets c.SignatureKey to the authority's public key and stores a Signature, by authority, in the certificate.

func (*Certificate) Type

func (c *Certificate) Type() string

Type returns the key name. It is part of the PublicKey interface.

func (*Certificate) Verify

func (c *Certificate) Verify(data []byte, sig *Signature) error

Verify verifies a signature against the certificate's public key. It is part of the PublicKey interface.

type Channel

type Channel interface {
	// Read reads up to len(data) bytes from the channel.
	Read(data []byte) (int, error)

	// Write writes len(data) bytes to the channel.
	Write(data []byte) (int, error)

	// Close signals end of channel use. No data may be sent after this
	// call.
	Close() error

	// CloseWrite signals the end of sending in-band
	// data. Requests may still be sent, and the other side may
	// still send data
	CloseWrite() error

	// SendRequest sends a channel request.  If wantReply is true,
	// it will wait for a reply and return the result as a
	// boolean, otherwise the return value will be false. Channel
	// requests are out-of-band messages so they may be sent even
	// if the data stream is closed or blocked by flow control.
	// If the channel is closed before a reply is returned, io.EOF
	// is returned.
	SendRequest(name string, wantReply bool, payload []byte) (bool, error)

	// Stderr returns an io.ReadWriter that writes to this channel
	// with the extended data type set to stderr. Stderr may
	// safely be read and written from a different goroutine than
	// Read and Write respectively.
	Stderr() io.ReadWriter

	// Done can be used to await connection shutdown. The
	// returned channel will be closed when the Channel is closed.
	Done() <-chan struct{}

	// 	GetHalter returns the Channel specific Halter.
	GetHalter() *Halter

	// SetReadIdleTimeout starts an idle timer on
	// Reads that will cause them to timeout after dur.
	// A successful Read will bump the idle
	// timeout into the future.
	//
	// Providing dur of 0 will disable the idle timeout.
	// Zero is the default until SetReadIdleTimeout() is called.
	//
	// SetReadIdleTimeout() will always reset and
	// clear any raised timeout left over from prior use.
	// Any new timer (if dur > 0) begins from the return of
	// the SetReadIdleTimeout() invocation.
	//
	// Idle timeouts are easier to use than deadlines,
	// as they don't need to be refreshed after
	// every read and write. Hence routines like io.Copy()
	// that make many calls to Read() and Write()
	// can be leveraged, while still having a timeout in
	// the case of no activity.
	//
	// Moreover idle timeouts are more
	// efficient because we don't guess at a
	// deadline and then interrupt a perfectly
	// good ongoing copy that happens to be
	// taking a few seconds longer than our
	// guesstimate. We avoid the pain of trying
	// to restart long interrupted transfers that
	// were making fine progress.
	//
	SetReadIdleTimeout(dur time.Duration) error

	// SetWriteIdleTimeout is the same as SetReadIdleTimeout,
	// but applies to writes rather than reads.
	// Note that Write() to
	// a Channel will "succeed" in the sense of
	// returning a nil error long before they
	// reach the remote end (or not). Writes
	// are buffered internally. Hence the write
	// idle timer may be less useful than
	// the read timer.
	SetWriteIdleTimeout(dur time.Duration) error

	// SetIdleTimeout does both SetReadIdleTimeout
	// and SetWriteIdleTimeout.
	SetIdleTimeout(dur time.Duration) error

	// GetReadIdleTimer allows monitoring of idle timeout
	// by other parties. It doesn't disturb the
	// timer if it happens to be running.
	GetReadIdleTimer() *IdleTimer

	// GetWriteIdleTimer allows monitoring of idle timeout
	// by other parties. It doesn't disturb the
	// timer if it happens to be running.
	GetWriteIdleTimer() *IdleTimer

	// SetReadDeadline sets the deadline for future Read calls
	// and any currently-blocked Read call.
	// A zero value for t means Read will not time out.
	SetReadDeadline(t time.Time) error

	// SetWriteDeadline sets the deadline for future Write calls
	// and any currently-blocked Write call.
	// A zero value for t means Write will not time out.
	SetWriteDeadline(t time.Time) error

	// SetDeadline sets the read and write deadlines.
	SetDeadline(t time.Time) error

	// Status lets clients query this Channel's lifecycle
	// progress.
	Status() *RunStatus

	LocalAddr() net.Addr
	RemoteAddr() net.Addr
}

A Channel is an ordered, reliable, flow-controlled, duplex stream that is multiplexed over an SSH connection.

type Client

type Client struct {
	Conn
	Halt *Halter

	Forwards        ForwardList // forwarded tcpip connections from the remote side
	Mu              sync.Mutex
	ChannelHandlers map[string]chan NewChannel

	TmpCtx context.Context
}

Client implements a traditional SSH client that supports shells, subprocesses, TCP port/streamlocal forwarding and tunneled dialing.

func Dial

func Dial(ctx context.Context, network, addr string, config *ClientConfig) (*Client, error)

Dial starts a client connection to the given SSH server. It is a convenience function that connects to the given network address, initiates the SSH handshake, and then sets up a Client. For access to incoming channels and requests, use net.Dial with NewClientConn instead.

Example
var hostKey ssh.PublicKey
// An SSH client is represented with a ClientConn.
//
// To authenticate with the remote server you must pass at least one
// implementation of AuthMethod via the Auth field in ClientConfig,
// and provide a HostKeyCallback.
config := &ssh.ClientConfig{
	User: "username",
	Auth: []ssh.AuthMethod{
		ssh.Password("yourpassword"),
	},
	HostKeyCallback: ssh.FixedHostKey(hostKey),
}
ctx := context.Background()
client, err := ssh.Dial(ctx, "tcp", "yourserver.com:22", config)
if err != nil {
	log.Fatal("Failed to dial: ", err)
}

// Each ClientConn can support multiple interactive sessions,
// represented by a Session.
session, err := client.NewSession(ctx)
if err != nil {
	log.Fatal("Failed to create session: ", err)
}
defer session.Close()

// Once a Session is created, you can execute a single command on
// the remote side using the Run method.
var b bytes.Buffer
session.Stdout = &b
if err := session.Run("/usr/bin/whoami"); err != nil {
	log.Fatal("Failed to run: " + err.Error())
}
fmt.Println(b.String())
Output:

func NewClient

func NewClient(ctx context.Context, c Conn, chans <-chan NewChannel, reqs <-chan *Request, halt *Halter) *Client

NewClient creates a Client on top of the given connection.

func (*Client) Dial

func (c *Client) Dial(n, addr string) (Channel, error)

Dial initiates a connection to the addr from the remote host. The n argument is the network: "tcp", "tcp4", "tcp6", "unix". The resulting connection has a zero LocalAddr() and RemoteAddr().

func (*Client) DialTCP

func (c *Client) DialTCP(n string, laddr, raddr *net.TCPAddr) (net.Conn, error)

DialTCP connects to the remote address raddr on the network net, which must be "tcp", "tcp4", or "tcp6". If laddr is not nil, it is used as the local address for the connection.

func (*Client) DialWithContext

func (c *Client) DialWithContext(ctx context.Context, n, addr string) (Channel, error)

DialWithContext is the same as Dial, but with ctx. The resulting connection has a zero LocalAddr() and RemoteAddr().

func (*Client) HandleChannelOpen

func (c *Client) HandleChannelOpen(channelType string) <-chan NewChannel

HandleChannelOpen returns a channel on which NewChannel requests for the given type are sent. If the type already is being handled, nil is returned. The channel is closed when the connection is closed.

func (*Client) HandleChannelOpens

func (c *Client) HandleChannelOpens(ctx context.Context, in <-chan NewChannel)

handleChannelOpens channel open messages from the remote side.

func (*Client) HandleGlobalRequests

func (c *Client) HandleGlobalRequests(ctx context.Context, incoming <-chan *Request)

func (*Client) Listen

func (c *Client) Listen(n, addr string) (net.Listener, error)

Listen requests the remote peer open a listening socket on addr. Incoming connections will be available by calling Accept on the returned net.Listener. The listener must be serviced, or the SSH connection may hang. N must be "tcp", "tcp4", "tcp6", or "unix".

Example
var hostKey ssh.PublicKey
config := &ssh.ClientConfig{
	User: "username",
	Auth: []ssh.AuthMethod{
		ssh.Password("password"),
	},
	HostKeyCallback: ssh.FixedHostKey(hostKey),
}
// Dial your ssh server.
ctx := context.Background()
conn, err := ssh.Dial(ctx, "tcp", "localhost:22", config)
if err != nil {
	log.Fatal("unable to connect: ", err)
}
defer conn.Close()

// Request the remote side to open port 8080 on all interfaces.
l, err := conn.Listen("tcp", "0.0.0.0:8080")
if err != nil {
	log.Fatal("unable to register tcp forward: ", err)
}
defer l.Close()

// Serve HTTP with your SSH server acting as a reverse proxy.
http.Serve(l, http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
	fmt.Fprintf(resp, "Hello world!\n")
}))
Output:

func (*Client) ListenTCP

func (c *Client) ListenTCP(ctx context.Context, laddr *net.TCPAddr) (*tcpListener, error)

ListenTCP requests the remote peer open a listening socket on laddr. Incoming connections will be available by calling Accept on the returned net.Listener.

func (*Client) ListenUnix

func (c *Client) ListenUnix(ctx context.Context, socketPath string) (net.Listener, error)

ListenUnix is similar to ListenTCP but uses a Unix domain socket.

func (*Client) NewSession

func (c *Client) NewSession(ctx context.Context) (*Session, error)

NewSession opens a new Session for this client. (A session is a remote execution of a program.)

type ClientConfig

type ClientConfig struct {
	// Config contains configuration that is shared between clients and
	// servers.
	Config

	// User contains the username to authenticate as.
	User string

	// HostPort has the IP:port in string form.
	HostPort string

	// Auth contains possible authentication methods to use with the
	// server. Only the first instance of a particular RFC 4252 method will
	// be used during authentication.
	Auth []AuthMethod

	// HostKeyCallback is called during the cryptographic
	// handshake to validate the server's host key. The client
	// configuration must supply this callback for the connection
	// to succeed. The functions InsecureIgnoreHostKey or
	// FixedHostKey can be used for simplistic host key checks.
	HostKeyCallback HostKeyCallback

	// ClientVersion contains the version identification string that will
	// be used for the connection. If empty, a reasonable default is used.
	ClientVersion string

	// HostKeyAlgorithms lists the key types that the client will
	// accept from the server as host key, in order of
	// preference. If empty, a reasonable default is used. Any
	// string returned from PublicKey.Type method may be used, or
	// any of the CertAlgoXxxx and KeyAlgoXxxx constants.
	HostKeyAlgorithms []string

	// Timeout is the maximum amount of time for the TCP connection to establish.
	//
	// A Timeout of zero means no timeout.
	Timeout time.Duration
}

A ClientConfig structure is used to configure a Client. It must not be modified after having been passed to an SSH function.

type Config

type Config struct {
	// Rand provides the source of entropy for cryptographic
	// primitives. If Rand is nil, the cryptographic random reader
	// in package crypto/rand will be used.
	Rand io.Reader

	// The maximum number of bytes sent or received after which a
	// new key is negotiated. It must be at least 256. If
	// unspecified, a size suitable for the chosen cipher is used.
	RekeyThreshold uint64

	// The allowed key exchanges algorithms. If unspecified then a
	// default set of algorithms is used.
	KeyExchanges []string

	// The allowed cipher algorithms. If unspecified then a sensible
	// default is used.
	Ciphers []string

	// The allowed MAC algorithms. If unspecified then a sensible default
	// is used.
	MACs []string

	// Halt is for shutdown
	Halt *Halter
}

Config contains configuration data common to both ServerConfig and ClientConfig.

func (*Config) SetDefaults

func (c *Config) SetDefaults()

SetDefaults sets sensible values for unset fields in config. This is exported for testing: Configs passed to SSH functions are copied and have default values set automatically.

type Conn

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(ctx context.Context, 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(ctx context.Context, name string, data []byte, parHalt *Halter) (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

	// Done can be used to await connection shutdown. The
	// returned channel will be closed when the Conn is
	// shutting down.
	Done() <-chan struct{}

	// NcCloser retreives the underlying net.Conn so
	// that it can be closed.
	NcCloser() io.Closer
}

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.

func NewClientConn

func NewClientConn(ctx context.Context, c net.Conn, addr string, config *ClientConfig) (Conn, <-chan NewChannel, <-chan *Request, error)

NewClientConn establishes an authenticated SSH connection using c as the underlying transport. The Request and NewChannel channels must be serviced or the connection will hang.

type ConnMetadata

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
}

ConnMetadata holds metadata for the connection.

type CryptoPublicKey

type CryptoPublicKey interface {
	CryptoPublicKey() crypto.PublicKey
}

CryptoPublicKey, if implemented by a PublicKey, returns the underlying crypto.PublicKey form of the key.

type ExitError

type ExitError struct {
	Waitmsg
}

An ExitError reports unsuccessful completion of a remote command.

func (*ExitError) Error

func (e *ExitError) Error() string

type ExitMissingError

type ExitMissingError struct{}

ExitMissingError is returned if a session is torn down cleanly, but the server sends no confirmation of the exit status.

func (*ExitMissingError) Error

func (e *ExitMissingError) Error() string

type ForwardList

type ForwardList struct {
	sync.Mutex
	// contains filtered or unexported fields
}

forwardList stores a mapping between remote forward requests and the tcpListeners.

func (*ForwardList) CloseAll

func (l *ForwardList) CloseAll()

closeAll closes and clears all forwards.

func (*ForwardList) Forward

func (l *ForwardList) Forward(ctx context.Context, laddr, raddr net.Addr, ch NewChannel, conn Conn) (bool, error)

func (*ForwardList) HandleChannels

func (l *ForwardList) HandleChannels(ctx context.Context, in <-chan NewChannel, conn Conn)

func (*ForwardList) Remove

func (l *ForwardList) Remove(addr net.Addr)

remove removes the forward entry, and the channel feeding its listener.

type Halter

type Halter struct {
	// contains filtered or unexported fields
}

Halter helps shutdown a goroutine, and manage overall lifecycle of a resource.

func NewHalter

func NewHalter() *Halter

func (*Halter) AddDownstream

func (h *Halter) AddDownstream(d *Halter)

AddDownstream is the public API. To prevent infinite loops, always use AddDownstream: it will automatically inform the d that h is now upstream. There is no need to call d.addUpstream(h), as AddDownstream will do that automatically.

func (*Halter) DoneChan

func (h *Halter) DoneChan() chan struct{}

func (*Halter) Err

func (h *Halter) Err() (err error)

func (*Halter) IsDone

func (h *Halter) IsDone() bool

IsDone returns true iff h.Done has been Closed().

func (*Halter) IsReady

func (h *Halter) IsReady() bool

func (*Halter) IsStopRequested

func (h *Halter) IsStopRequested() bool

IsStopRequested returns true iff h.ReqStop has been Closed().

func (*Halter) MarkDone

func (h *Halter) MarkDone()

MarkDone closes the h.DoneChan() channel if it has not already done so. Safe for multiple goroutine access. MarkDone returns only once all downstream Halters have called MarkDone. See MarkDoneNoBlock for an alternative.

func (*Halter) MarkDoneNoBlock

func (h *Halter) MarkDoneNoBlock()

MarkDoneNoBlock doesn't wait for downstream goroutines to be done before it returns.

func (*Halter) MarkReady

func (h *Halter) MarkReady()

MarkReady closes the h.ready channel if it has not already done so. Safe for multiple goroutine access.

func (*Halter) ReadyChan

func (h *Halter) ReadyChan() chan struct{}

func (*Halter) RemoveDownstream

func (h *Halter) RemoveDownstream(d *Halter)

func (*Halter) ReqStopChan

func (h *Halter) ReqStopChan() chan struct{}

func (*Halter) RequestStop

func (h *Halter) RequestStop()

RequestStop closes the h.ReqStop channel if it has not already done so. Safe for multiple goroutine access.

func (*Halter) SetErr

func (h *Halter) SetErr(err error)

func (*Halter) Status

func (h *Halter) Status() (r *RunStatus)

type HasTimeout

type HasTimeout interface {
	// contains filtered or unexported methods
}

type HostKeyCallback

type HostKeyCallback func(hostname string, remote net.Addr, key PublicKey) error

HostKeyCallback is the function type used for verifying server keys. A HostKeyCallback must return nil if the host key is OK, or an error to reject it. It receives the hostname as passed to Dial or NewClientConn. The remote address is the RemoteAddr of the net.Conn underlying the the SSH connection.

func FixedHostKey

func FixedHostKey(key PublicKey) HostKeyCallback

FixedHostKey returns a function for use in ClientConfig.HostKeyCallback to accept only a specific host key.

func InsecureIgnoreHostKey

func InsecureIgnoreHostKey() HostKeyCallback

InsecureIgnoreHostKey returns a function that can be used for ClientConfig.HostKeyCallback to accept any host key. It should not be used for production code.

type IdemCloseChan

type IdemCloseChan struct {
	Chan chan struct{}
	// contains filtered or unexported fields
}

IdemCloseChan can have Close() called on it multiple times, and it will only close Chan once.

func NewIdemCloseChan

func NewIdemCloseChan() *IdemCloseChan

NewIdemCloseChan makes a new IdemCloseChan.

func (*IdemCloseChan) Close

func (c *IdemCloseChan) Close() error

Close returns ErrAlreadyClosed if it has been called before. It never closes IdemClose.Chan more than once, so it is safe to ignore the returned error value. Close() is safe for concurrent access by multiple goroutines. Close returns nil after the first time it is called.

func (*IdemCloseChan) IsClosed

func (c *IdemCloseChan) IsClosed() bool

IsClosed tells you if Chan is already closed or not.

func (*IdemCloseChan) Reinit

func (c *IdemCloseChan) Reinit()

Reinit re-allocates the Chan, assinging a new channel and reseting the state as if brand new.

type IdleTimer

type IdleTimer struct {
	// TimedOut sends empty string if no timeout, else details.
	TimedOut chan string

	// Halt is the standard means of requesting
	// stop and waiting for that stop to be done.
	Halt *Halter
	// contains filtered or unexported fields
}

IdleTimer allows a client of the ssh library to notice if there has been a stall in i/o activity. This enables clients to impliment timeout logic that works and doesn't timeout under long-duration-but-still-successful reads/writes.

It is simpler to use the SetIdleTimeout(dur time.Duration) method on the channel, but methods like LastAndMonoNow() are also occassionally required.

func NewIdleTimer

func NewIdleTimer(callback func(), dur time.Duration) *IdleTimer

NewIdleTimer creates a new IdleTimer which will call the `callback` function provided after `dur` inactivity. If callback is nil, you must use setTimeoutCallback() to establish the callback before activating the timer with SetIdleTimeout. The `dur` can be 0 to begin with no timeout, in which case the timer will be inactive until SetIdleTimeout is called.

func (*IdleTimer) AddTimeoutCallback

func (t *IdleTimer) AddTimeoutCallback(timeoutFunc func())

AddTimeoutCallback adds another callback, without removing exiting callbacks

func (*IdleTimer) AttemptOK

func (t *IdleTimer) AttemptOK()

Reset stores the current monotonic timestamp internally, effectively reseting to zero the value returned from an immediate next call to NanosecSince().

AttemptOK() only ever applies to reads now. Writes lie: they return nil errors when the connection is down.

func (*IdleTimer) BeginAttempt

func (t *IdleTimer) BeginAttempt()

func (*IdleTimer) GetIdleTimeout

func (t *IdleTimer) GetIdleTimeout() (dur time.Duration)

GetIdleTimeout returns the current idle timeout duration in use. It will return 0 if timeouts are disabled.

func (*IdleTimer) IdleStatus

func (t *IdleTimer) IdleStatus() (lastStart, lastOK, mnow, todur int64, timedout bool)

IdleStatus returns three monotonic timestamps.

  • lastStart is the last time BeginAttempt() was called.

  • lastOK is the last time AttemptOK() was called.

  • mnow is the current monotonic timestamp.

Note that lastStart == -1 means there has been no BeginAttempt() call started since we set the idle timeout. In this case an idle timeout determination may not be appropriate because has been no Read attempted since then.

  • todur returns the duration in nanoseconds of any timeout that has been set.
  • timedout returns true if it appears a Read attempt has timed out before finishing successfully. Note that the Read may have returned with an error and may not be currently active.

func (*IdleTimer) LastOKLastStartAndMonoNow

func (t *IdleTimer) LastOKLastStartAndMonoNow() (lastOK, lastStart, mnow int64)

func (*IdleTimer) SetIdleTimeout

func (t *IdleTimer) SetIdleTimeout(dur time.Duration) error

SetIdleTimeout stores a new idle timeout duration. This activates the IdleTimer if dur > 0. Set dur of 0 to disable the IdleTimer. A disabled IdleTimer always returns false from TimedOut().

This is the main API for IdleTimer. Most users will only need to use this call.

func (*IdleTimer) SetOneshotIdleTimeout

func (t *IdleTimer) SetOneshotIdleTimeout(dur time.Duration)

func (*IdleTimer) Stop

func (t *IdleTimer) Stop()

type KeyboardInteractiveChallenge

type KeyboardInteractiveChallenge func(ctx context.Context, user, instruction string, questions []string, echos []bool) (answers []string, err error)

KeyboardInteractiveChallenge should print questions, optionally disabling echoing (e.g. for passwords), and return all the answers. Challenge may be called multiple times in a single session. After successful authentication, the server may send a challenge with no questions, for which the user and instruction messages should be printed. RFC 4256 section 3.3 details how the UI should behave for both CLI and GUI environments.

type NewChannel

type NewChannel interface {
	// Accept accepts the channel creation request. It returns the Channel
	// and a Go channel containing SSH requests. The Go channel must be
	// serviced otherwise the Channel will hang.
	Accept() (Channel, <-chan *Request, error)

	// Reject rejects the channel creation request. After calling
	// this, no other methods on the Channel may be called.
	Reject(reason RejectionReason, message string) error

	// ChannelType returns the type of the channel, as supplied by the
	// client.
	ChannelType() string

	// ExtraData returns the arbitrary payload for this channel, as supplied
	// by the client. This data is specific to the channel type.
	ExtraData() []byte
}

NewChannel represents an incoming request to a channel. It must either be accepted for use by calling Accept, or rejected by calling Reject.

type OpenChannelError

type OpenChannelError struct {
	Reason  RejectionReason
	Message string
}

OpenChannelError is returned if the other side rejects an OpenChannel request.

func (*OpenChannelError) Error

func (e *OpenChannelError) Error() string

type Permissions

type Permissions struct {
	// CriticalOptions indicate restrictions to the default
	// permissions, and are typically used in conjunction with
	// user certificates. The standard for SSH certificates
	// defines "force-command" (only allow the given command to
	// execute) and "source-address" (only allow connections from
	// the given address). The SSH package currently only enforces
	// the "source-address" critical option. It is up to server
	// implementations to enforce other critical options, such as
	// "force-command", by checking them after the SSH handshake
	// is successful. In general, SSH servers should reject
	// connections that specify critical options that are unknown
	// or not supported.
	CriticalOptions map[string]string

	// Extensions are extra functionality that the server may
	// offer on authenticated connections. Lack of support for an
	// extension does not preclude authenticating a user. Common
	// extensions are "permit-agent-forwarding",
	// "permit-X11-forwarding". The Go SSH library currently does
	// not act on any extension, and it is up to server
	// implementations to honor them. Extensions can be used to
	// pass data from the authentication callbacks to the server
	// application layer.
	Extensions map[string]string
}

The Permissions type holds fine-grained permissions that are specific to a user or a specific authentication method for a user. The Permissions value for a successful authentication attempt is available in ServerConn, so it can be used to pass information from the user-authentication phase to the application layer.

type PublicKey

type PublicKey interface {
	// Type returns the key's type, e.g. "ssh-rsa".
	Type() string

	// Marshal returns the serialized key data in SSH wire format,
	// with the name prefix.
	Marshal() []byte

	// Verify that sig is a signature on the given data using this
	// key. This function will hash the data appropriately first.
	Verify(data []byte, sig *Signature) error
}

PublicKey is an abstraction of different types of public keys.

func NewPublicKey

func NewPublicKey(key interface{}) (PublicKey, error)

NewPublicKey takes an *rsa.PublicKey, *dsa.PublicKey, *ecdsa.PublicKey, or ed25519.PublicKey returns a corresponding PublicKey instance. ECDSA keys must use P-256, P-384 or P-521.

func ParseAuthorizedKey

func ParseAuthorizedKey(in []byte) (out PublicKey, comment string, options []string, rest []byte, err error)

ParseAuthorizedKeys parses a public key from an authorized_keys file used in OpenSSH according to the sshd(8) manual page.

func ParseKnownHosts

func ParseKnownHosts(in []byte) (marker string, hosts []string, pubKey PublicKey, comment string, rest []byte, err error)

ParseKnownHosts parses an entry in the format of the known_hosts file.

The known_hosts format is documented in the sshd(8) manual page. This function will parse a single entry from in. On successful return, marker will contain the optional marker value (i.e. "cert-authority" or "revoked") or else be empty, hosts will contain the hosts that this entry matches, pubKey will contain the public key and comment will contain any trailing comment at the end of the line. See the sshd(8) manual page for the various forms that a host string can take.

The unparsed remainder of the input will be returned in rest. This function can be called repeatedly to parse multiple entries.

If no entries were found in the input then err will be io.EOF. Otherwise a non-nil err value indicates a parse error.

func ParsePublicKey

func ParsePublicKey(in []byte) (out PublicKey, err error)

ParsePublicKey parses an SSH public key formatted for use in the SSH wire protocol according to RFC 4253, section 6.6.

type RejectionReason

type RejectionReason uint32

RejectionReason is an enumeration used when rejecting channel creation requests. See RFC 4254, section 5.1.

const (
	Prohibited RejectionReason = iota + 1
	ConnectionFailed
	UnknownChannelType
	ResourceShortage
)

func (RejectionReason) String

func (r RejectionReason) String() string

String converts the rejection reason to human readable form.

type Request

type Request struct {
	Type      string
	WantReply bool
	Payload   []byte
	// contains filtered or unexported fields
}

Request is a request sent outside of the normal stream of data. Requests can either be specific to an SSH channel, or they can be global.

func (*Request) Reply

func (r *Request) Reply(ok bool, payload []byte) error

Reply sends a response to a request. It must be called for all requests where WantReply is true and is a no-op otherwise. The payload argument is ignored for replies to channel-specific requests.

type RunStatus

type RunStatus struct {

	// lifecycle
	Ready         bool
	StopRequested bool
	Done          bool

	// can be waited on for finish.
	// Once closed, call Status()
	// again to get any Err that
	// was the cause/leftover.
	DoneCh <-chan struct{}

	// final error if any.
	Err error
}

RunStatus provides lifecycle snapshots.

type ServerAuthError

type ServerAuthError struct {
	// Errors contains authentication errors returned by the authentication
	// callback methods.
	Errors []error
}

ServerAuthError implements the error interface. It appends any authentication errors that may occur, and is returned if all of the authentication methods provided by the user failed to authenticate.

func (ServerAuthError) Error

func (l ServerAuthError) Error() string

type ServerConfig

type ServerConfig struct {
	// Config contains configuration shared between client and server.
	Config

	// NoClientAuth is true if clients are allowed to connect without
	// authenticating.
	NoClientAuth bool

	// MaxAuthTries specifies the maximum number of authentication attempts
	// permitted per connection. If set to a negative number, the number of
	// attempts are unlimited. If set to zero, the number of attempts are limited
	// to 6.
	MaxAuthTries int

	// PasswordCallback, if non-nil, is called when a user
	// attempts to authenticate using a password.
	PasswordCallback func(conn ConnMetadata, password []byte) (*Permissions, error)

	// PublicKeyCallback, if non-nil, is called when a client
	// offers a public key for authentication. It must return a nil error
	// if the given public key can be used to authenticate the
	// given user. For example, see CertChecker.Authenticate. A
	// call to this function does not guarantee that the key
	// offered is in fact used to authenticate. To record any data
	// depending on the public key, store it inside a
	// Permissions.Extensions entry.
	PublicKeyCallback func(conn ConnMetadata, key PublicKey) (*Permissions, error)

	// KeyboardInteractiveCallback, if non-nil, is called when
	// keyboard-interactive authentication is selected (RFC
	// 4256). The client object's Challenge function should be
	// used to query the user. The callback may offer multiple
	// Challenge rounds. To avoid information leaks, the client
	// should be presented a challenge even if the user is
	// unknown.
	KeyboardInteractiveCallback func(ctx context.Context, conn ConnMetadata, client KeyboardInteractiveChallenge) (*Permissions, error)

	// AuthLogCallback, if non-nil, is called to log all authentication
	// attempts.
	AuthLogCallback func(conn ConnMetadata, method string, err error)

	// ServerVersion is the version identification string to announce in
	// the public handshake.
	// If empty, a reasonable default is used.
	// Note that RFC 4253 section 4.2 requires that this string start with
	// "SSH-2.0-".
	ServerVersion string
	// contains filtered or unexported fields
}

ServerConfig holds server specific configuration data.

func (*ServerConfig) AddHostKey

func (s *ServerConfig) AddHostKey(key Signer)

AddHostKey adds a private key as a host key. If an existing host key exists with the same algorithm, it is overwritten. Each server config must have at least one host key.

type ServerConn

type ServerConn struct {
	Conn

	// If the succeeding authentication callback returned a
	// non-nil Permissions pointer, it is stored here.
	Permissions *Permissions
}

ServerConn is an authenticated SSH connection, as seen from the server

func NewServerConn

func NewServerConn(ctx context.Context, c net.Conn, config *ServerConfig) (*ServerConn, <-chan NewChannel, <-chan *Request, error)

NewServerConn starts a new SSH server with c as the underlying transport. It starts with a handshake and, if the handshake is unsuccessful, it closes the connection and returns an error. The Request and NewChannel channels must be serviced, or the connection will hang.

Example
// Public key authentication is done by comparing
// the public key of a received connection
// with the entries in the authorized_keys file.
authorizedKeysBytes, err := ioutil.ReadFile("authorized_keys")
if err != nil {
	log.Fatalf("Failed to load authorized_keys, err: %v", err)
}

authorizedKeysMap := map[string]bool{}
for len(authorizedKeysBytes) > 0 {
	pubKey, _, _, rest, err := ssh.ParseAuthorizedKey(authorizedKeysBytes)
	if err != nil {
		log.Fatal(err)
	}

	authorizedKeysMap[string(pubKey.Marshal())] = true
	authorizedKeysBytes = rest
}

// An SSH server is represented by a ServerConfig, which holds
// certificate details and handles authentication of ServerConns.
config := &ssh.ServerConfig{
	// Remove to disable password auth.
	PasswordCallback: func(c ssh.ConnMetadata, pass []byte) (*ssh.Permissions, error) {
		// Should use constant-time compare (or better, salt+hash) in
		// a production setting.
		if c.User() == "testuser" && string(pass) == "tiger" {
			return nil, nil
		}
		return nil, fmt.Errorf("password rejected for %q", c.User())
	},

	// Remove to disable public key auth.
	PublicKeyCallback: func(c ssh.ConnMetadata, pubKey ssh.PublicKey) (*ssh.Permissions, error) {
		if authorizedKeysMap[string(pubKey.Marshal())] {
			return &ssh.Permissions{
				// Record the public key used for authentication.
				Extensions: map[string]string{
					"pubkey-fp": ssh.FingerprintSHA256(pubKey),
				},
			}, nil
		}
		return nil, fmt.Errorf("unknown public key for %q", c.User())
	},
}

privateBytes, err := ioutil.ReadFile("id_rsa")
if err != nil {
	log.Fatal("Failed to load private key: ", err)
}

private, err := ssh.ParsePrivateKey(privateBytes)
if err != nil {
	log.Fatal("Failed to parse private key: ", err)
}

config.AddHostKey(private)

// Once a ServerConfig has been configured, connections can be
// accepted.
listener, err := net.Listen("tcp", "0.0.0.0:2022")
if err != nil {
	log.Fatal("failed to listen for connection: ", err)
}
nConn, err := listener.Accept()
if err != nil {
	log.Fatal("failed to accept incoming connection: ", err)
}

// Before use, a handshake must be performed on the incoming
// net.Conn.
ctx := context.Background()

conn, chans, reqs, err := ssh.NewServerConn(ctx, nConn, config)
if err != nil {
	log.Fatal("failed to handshake: ", err)
}
log.Printf("logged in with key %s", conn.Permissions.Extensions["pubkey-fp"])

// The incoming Request channel must be serviced.
go ssh.DiscardRequests(ctx, reqs, config.Halt)

// Service the incoming Channel channel.
for newChannel := range chans {
	// Channels have a type, depending on the application level
	// protocol intended. In the case of a shell, the type is
	// "session" and ServerShell may be used to present a simple
	// terminal interface.
	if newChannel.ChannelType() != "session" {
		newChannel.Reject(ssh.UnknownChannelType, "unknown channel type")
		continue
	}
	channel, requests, err := newChannel.Accept()
	if err != nil {
		log.Fatalf("Could not accept channel: %v", err)
	}

	// Sessions have out-of-band requests such as "shell",
	// "pty-req" and "env".  Here we handle only the
	// "shell" request.
	go func(in <-chan *ssh.Request) {
		for req := range in {
			req.Reply(req.Type == "shell", nil)
		}
	}(requests)

	term := terminal.NewTerminal(channel, "> ")

	go func() {
		defer channel.Close()
		for {
			line, err := term.ReadLine()
			if err != nil {
				break
			}
			fmt.Println(line)
		}
	}()
}
Output:

type Session

type Session struct {
	// Stdin specifies the remote process's standard input.
	// If Stdin is nil, the remote process reads from an empty
	// bytes.Buffer.
	Stdin io.Reader

	// Stdout and Stderr specify the remote process's standard
	// output and error.
	//
	// If either is nil, Run connects the corresponding file
	// descriptor to an instance of ioutil.Discard. There is a
	// fixed amount of buffering that is shared for the two streams.
	// If either blocks it may eventually cause the remote
	// command to block.
	Stdout io.Writer
	Stderr io.Writer
	// contains filtered or unexported fields
}

A Session represents a connection to a remote command or shell.

func (*Session) Close

func (s *Session) Close() error

func (*Session) CombinedOutput

func (s *Session) CombinedOutput(cmd string) ([]byte, error)

CombinedOutput runs cmd on the remote host and returns its combined standard output and standard error.

func (*Session) Output

func (s *Session) Output(cmd string) ([]byte, error)

Output runs cmd on the remote host and returns its standard output.

func (*Session) RequestPty

func (s *Session) RequestPty(term string, h, w int, termmodes TerminalModes) error

RequestPty requests the association of a pty with the session on the remote host.

Example
var hostKey ssh.PublicKey
// Create client config
config := &ssh.ClientConfig{
	User: "username",
	Auth: []ssh.AuthMethod{
		ssh.Password("password"),
	},
	HostKeyCallback: ssh.FixedHostKey(hostKey),
}
// Connect to ssh server
ctx := context.Background()
conn, err := ssh.Dial(ctx, "tcp", "localhost:22", config)
if err != nil {
	log.Fatal("unable to connect: ", err)
}
defer conn.Close()
// Create a session
session, err := conn.NewSession(ctx)
if err != nil {
	log.Fatal("unable to create session: ", err)
}
defer session.Close()
// Set up terminal modes
modes := ssh.TerminalModes{
	ssh.ECHO:          0,     // disable echoing
	ssh.TTY_OP_ISPEED: 14400, // input speed = 14.4kbaud
	ssh.TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud
}
// Request pseudo terminal
if err := session.RequestPty("xterm", 40, 80, modes); err != nil {
	log.Fatal("request for pseudo terminal failed: ", err)
}
// Start remote shell
if err := session.Shell(); err != nil {
	log.Fatal("failed to start shell: ", err)
}
Output:

func (*Session) RequestSubsystem

func (s *Session) RequestSubsystem(subsystem string) error

RequestSubsystem requests the association of a subsystem with the session on the remote host. A subsystem is a predefined command that runs in the background when the ssh session is initiated

func (*Session) Run

func (s *Session) Run(cmd string) error

Run runs cmd on the remote host. Typically, the remote server passes cmd to the shell for interpretation. A Session only accepts one call to Run, Start, Shell, Output, or CombinedOutput.

The returned error is nil if the command runs, has no problems copying stdin, stdout, and stderr, and exits with a zero exit status.

If the remote server does not send an exit status, an error of type *ExitMissingError is returned. If the command completes unsuccessfully or is interrupted by a signal, the error is of type *ExitError. Other error types may be returned for I/O problems.

func (*Session) SendRequest

func (s *Session) SendRequest(name string, wantReply bool, payload []byte) (bool, error)

SendRequest sends an out-of-band channel request on the SSH channel underlying the session.

func (*Session) Setenv

func (s *Session) Setenv(name, value string) error

Setenv sets an environment variable that will be applied to any command executed by Shell or Run.

func (*Session) Shell

func (s *Session) Shell() error

Shell starts a login shell on the remote host. A Session only accepts one call to Run, Start, Shell, Output, or CombinedOutput.

func (*Session) Signal

func (s *Session) Signal(sig Signal) error

Signal sends the given signal to the remote process. sig is one of the SIG* constants.

func (*Session) Start

func (s *Session) Start(cmd string) error

Start runs cmd on the remote host. Typically, the remote server passes cmd to the shell for interpretation. A Session only accepts one call to Run, Start or Shell.

func (*Session) StderrPipe

func (s *Session) StderrPipe() (io.Reader, error)

StderrPipe returns a pipe that will be connected to the remote command's standard error when the command starts. There is a fixed amount of buffering that is shared between stdout and stderr streams. If the StderrPipe reader is not serviced fast enough it may eventually cause the remote command to block.

func (*Session) StdinPipe

func (s *Session) StdinPipe() (io.WriteCloser, error)

StdinPipe returns a pipe that will be connected to the remote command's standard input when the command starts.

func (*Session) StdoutPipe

func (s *Session) StdoutPipe() (io.Reader, error)

StdoutPipe returns a pipe that will be connected to the remote command's standard output when the command starts. There is a fixed amount of buffering that is shared between stdout and stderr streams. If the StdoutPipe reader is not serviced fast enough it may eventually cause the remote command to block.

func (*Session) Wait

func (s *Session) Wait() error

Wait waits for the remote command to exit.

The returned error is nil if the command runs, has no problems copying stdin, stdout, and stderr, and exits with a zero exit status.

If the remote server does not send an exit status, an error of type *ExitMissingError is returned. If the command completes unsuccessfully or is interrupted by a signal, the error is of type *ExitError. Other error types may be returned for I/O problems.

func (*Session) WindowChange

func (s *Session) WindowChange(h, w int) error

WindowChange informs the remote host about a terminal window dimension change to h rows and w columns.

type Signal

type Signal string
const (
	SIGABRT Signal = "ABRT"
	SIGALRM Signal = "ALRM"
	SIGFPE  Signal = "FPE"
	SIGHUP  Signal = "HUP"
	SIGILL  Signal = "ILL"
	SIGINT  Signal = "INT"
	SIGKILL Signal = "KILL"
	SIGPIPE Signal = "PIPE"
	SIGQUIT Signal = "QUIT"
	SIGSEGV Signal = "SEGV"
	SIGTERM Signal = "TERM"
	SIGUSR1 Signal = "USR1"
	SIGUSR2 Signal = "USR2"
)

POSIX signals as listed in RFC 4254 Section 6.10.

type Signature

type Signature struct {
	Format string
	Blob   []byte
}

Signature represents a cryptographic signature.

type Signer

type Signer interface {
	// PublicKey returns an associated PublicKey instance.
	PublicKey() PublicKey

	// Sign returns raw signature for the given data. This method
	// will apply the hash specified for the keytype to the data.
	Sign(rand io.Reader, data []byte) (*Signature, error)
}

A Signer can create signatures that verify against a public key.

func NewCertSigner

func NewCertSigner(cert *Certificate, signer Signer) (Signer, error)

NewCertSigner returns a Signer that signs with the given Certificate, whose private key is held by signer. It returns an error if the public key in cert doesn't match the key used by signer.

func NewSignerFromKey

func NewSignerFromKey(key interface{}) (Signer, error)

NewSignerFromKey takes an *rsa.PrivateKey, *dsa.PrivateKey, *ecdsa.PrivateKey or any other crypto.Signer and returns a corresponding Signer instance. ECDSA keys must use P-256, P-384 or P-521.

func NewSignerFromSigner

func NewSignerFromSigner(signer crypto.Signer) (Signer, error)

NewSignerFromSigner takes any crypto.Signer implementation and returns a corresponding Signer interface. This can be used, for example, with keys kept in hardware modules.

func ParsePrivateKey

func ParsePrivateKey(pemBytes []byte) (Signer, error)

ParsePrivateKey returns a Signer from a PEM encoded private key. It supports the same keys as ParseRawPrivateKey.

func ParsePrivateKeyWithPassphrase

func ParsePrivateKeyWithPassphrase(pemBytes, passPhrase []byte) (Signer, error)

ParsePrivateKeyWithPassphrase returns a Signer from a PEM encoded private key and passphrase. It supports the same keys as ParseRawPrivateKeyWithPassphrase.

type TerminalModes

type TerminalModes map[uint8]uint32

type Waitmsg

type Waitmsg struct {
	// contains filtered or unexported fields
}

Waitmsg stores the information about an exited remote command as reported by Wait.

func (Waitmsg) ExitStatus

func (w Waitmsg) ExitStatus() int

ExitStatus returns the exit status of the remote command.

func (Waitmsg) Lang

func (w Waitmsg) Lang() string

Lang returns the language tag. See RFC 3066

func (Waitmsg) Msg

func (w Waitmsg) Msg() string

Msg returns the exit message given by the remote command

func (Waitmsg) Signal

func (w Waitmsg) Signal() string

Signal returns the exit signal of the remote command if it was terminated violently.

func (Waitmsg) String

func (w Waitmsg) String() string

Directories

Path Synopsis
Package agent implements the ssh-agent protocol, and provides both a client and a server.
Package agent implements the ssh-agent protocol, and provides both a client and a server.
Package knownhosts implements a parser for the OpenSSH known_hosts host key database.
Package knownhosts implements a parser for the OpenSSH known_hosts host key database.
Package terminal provides support functions for dealing with terminals, as commonly found on UNIX systems.
Package terminal provides support functions for dealing with terminals, as commonly found on UNIX systems.
This package contains integration tests for the github.com/glycerine/sshego/xendor/github.com/glycerine/xcryptossh package.
This package contains integration tests for the github.com/glycerine/sshego/xendor/github.com/glycerine/xcryptossh package.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL