ssh package - golang.org/x/crypto/ssh - Go Packages (original) (raw)

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:

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

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" CertAlgoSKECDSA256v01 = "sk-ecdsa-sha2-nistp256-cert-v01@openssh.com" CertAlgoED25519v01 = "ssh-ed25519-cert-v01@openssh.com" CertAlgoSKED25519v01 = "sk-ssh-ed25519-cert-v01@openssh.com"

CertAlgoRSASHA256v01 = "rsa-sha2-256-cert-v01@openssh.com"
CertAlgoRSASHA512v01 = "rsa-sha2-512-cert-v01@openssh.com"

)

Certificate algorithm names from [PROTOCOL.certkeys]. These values can appear in Certificate.Type, PublicKey.Type, and ClientConfig.HostKeyAlgorithms. Unlike key algorithm names, these are not passed to AlgorithmSigner nor returned by MultiAlgorithmSigner and don't appear in the Signature.Format field.

View Source

const (

CertSigAlgoRSAv01 = [CertAlgoRSAv01](#CertAlgoRSAv01)

CertSigAlgoRSASHA2256v01 = [CertAlgoRSASHA256v01](#CertAlgoRSASHA256v01)

CertSigAlgoRSASHA2512v01 = [CertAlgoRSASHA512v01](#CertAlgoRSASHA512v01)

)

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" KeyAlgoSKECDSA256 = "sk-ecdsa-sha2-nistp256@openssh.com" KeyAlgoECDSA384 = "ecdsa-sha2-nistp384" KeyAlgoECDSA521 = "ecdsa-sha2-nistp521" KeyAlgoED25519 = "ssh-ed25519" KeyAlgoSKED25519 = "sk-ssh-ed25519@openssh.com"

KeyAlgoRSASHA256 = "rsa-sha2-256"
KeyAlgoRSASHA512 = "rsa-sha2-512"

)

Public key algorithms names. These values can appear in PublicKey.Type, ClientConfig.HostKeyAlgorithms, Signature.Format, or as AlgorithmSigner arguments.

View Source

const (

SigAlgoRSA = [KeyAlgoRSA](#KeyAlgoRSA)

SigAlgoRSASHA2256 = [KeyAlgoRSASHA256](#KeyAlgoRSASHA256)

SigAlgoRSASHA2512 = [KeyAlgoRSASHA512](#KeyAlgoRSASHA512)

)

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 IUTF8 = 42 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.

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

ErrNoAuth is the error value returned if no authentication method has been passed yet. This happens as a normal part of the authentication loop, since the client first tries 'none' authentication to discover available methods. It is returned in ServerAuthError.Errors from NewServerConn.

func DiscardRequests(in <-chan *Request)

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

func FingerprintLegacyMD5(pubKey PublicKey) string

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

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(key PublicKey) []byte

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

MarshalPrivateKey returns a PEM block with the private key serialized in the OpenSSH format.

MarshalPrivateKeyWithPassphrase returns a PEM block holding the encrypted private key serialized in the OpenSSH format.

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

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

ParseRawPrivateKey returns a private key from a PEM encoded private key. It supports RSA, DSA, ECDSA, and Ed25519 private keys in PKCS#1, PKCS#8, OpenSSL, and OpenSSH formats. If the private key is encrypted, it will return a PassphraseMissingError.

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

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

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.

An AlgorithmSigner is a Signer that also supports specifying an algorithm to use for signing.

An AlgorithmSigner can't advertise the algorithms it supports, unless it also implements MultiAlgorithmSigner, so it should be prepared to be invoked with every algorithm supported by the public key format.

type AuthMethod interface {

}

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

func GSSAPIWithMICAuthMethod(gssAPIClient GSSAPIClient, target string) AuthMethod

GSSAPIWithMICAuthMethod is an AuthMethod with "gssapi-with-mic" authentication. See RFC 4462 section 3gssAPIClient is implementation of the GSSAPIClient interface, see the definition of the interface for details. target is the server host you want to log in to.

func KeyboardInteractive(challenge KeyboardInteractiveChallenge) AuthMethod

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

Password returns an AuthMethod using the given password.

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

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

func PublicKeys(signers ...Signer) AuthMethod

PublicKeys returns an AuthMethod that uses the given key pairs.

package main

import ( "log" "os"

"golang.org/x/crypto/ssh"

)

func main() { 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 := os.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.
client, err := ssh.Dial("tcp", "host.com:22", config)
if err != nil {
    log.Fatalf("unable to connect: %v", err)
}
defer client.Close()

}

Output:

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(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).

user := "testuser" NumberOfPrompts := 3

// Normally this would be a callback that prompts the user to answer the // provided questions Cb := func(user, instruction string, questions []string, echos []bool) (answers []string, err error) { return []string{"answer1", "answer2"}, nil }

config := &ClientConfig{ HostKeyCallback: InsecureIgnoreHostKey(), User: user, Auth: []AuthMethod{ RetryableAuthMethod(KeyboardInteractiveChallenge(Cb), NumberOfPrompts), }, }

host := "mysshserver" netConn, err := net.Dial("tcp", host) if err != nil { log.Fatal(err) }

sshConn, _, _, err := NewClientConn(netConn, host, config) if err != nil { log.Fatal(err) } _ = sshConn

Output:

BannerCallback is the function type used for treat the banner sent by the server. A BannerCallback receives the message sent by the remote server.

func BannerDisplayStderr() BannerCallback

BannerDisplayStderr returns a function that can be used for ClientConfig.BannerCallback to display banners on os.Stderr.

type BannerError struct { }

BannerError is an error that can be returned by authentication handlers in ServerConfig to send a banner message to the client.

type CertChecker struct {

SupportedCriticalOptions [][string](/builtin#string)


IsUserAuthority func(auth [PublicKey](#PublicKey)) [bool](/builtin#bool)


IsHostAuthority func(auth [PublicKey](#PublicKey), address [string](/builtin#string)) [bool](/builtin#bool)


Clock func() [time](/time).[Time](/time#Time)


UserKeyFallback func(conn [ConnMetadata](#ConnMetadata), key [PublicKey](#PublicKey)) (*[Permissions](#Permissions), [error](/builtin#error))


HostKeyFallback [HostKeyCallback](#HostKeyCallback)


IsRevoked func(cert *[Certificate](#Certificate)) [bool](/builtin#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 (c CertChecker) Authenticate(conn ConnMetadata, pubKey PublicKey) (Permissions, error)

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

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

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

An Certificate represents an OpenSSH certificate as defined in [PROTOCOL.certkeys]?rev=1.8. The Certificate type implements the PublicKey interface, so it can be unmarshaled using ParsePublicKey.

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

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

SignCert signs the certificate with an authority, setting the Nonce, SignatureKey, and Signature fields. If the authority implements the MultiAlgorithmSigner interface the first algorithm in the list is used. This is useful if you want to sign with a specific algorithm.

package main

import ( "crypto/rand" "crypto/rsa" "fmt" "log"

"golang.org/x/crypto/ssh"

)

func main() { // Sign a certificate with a specific algorithm. privateKey, err := rsa.GenerateKey(rand.Reader, 3072) if err != nil { log.Fatal("unable to generate RSA key: ", err) } publicKey, err := ssh.NewPublicKey(&privateKey.PublicKey) if err != nil { log.Fatal("unable to get RSA public key: ", err) } caKey, err := rsa.GenerateKey(rand.Reader, 3072) if err != nil { log.Fatal("unable to generate CA key: ", err) } signer, err := ssh.NewSignerFromKey(caKey) if err != nil { log.Fatal("unable to generate signer from key: ", err) } mas, err := ssh.NewSignerWithAlgorithms(signer.(ssh.AlgorithmSigner), []string{ssh.KeyAlgoRSASHA256}) if err != nil { log.Fatal("unable to create signer with algorithms: ", err) } certificate := ssh.Certificate{ Key: publicKey, CertType: ssh.UserCert, } if err := certificate.SignCert(rand.Reader, mas); err != nil { log.Fatal("unable to sign certificate: ", err) } // Save the public key to a file and check that rsa-sha-256 is used for // signing: // ssh-keygen -L -f fmt.Println(string(ssh.MarshalAuthorizedKey(&certificate))) }

Output:

Type returns the certificate algorithm name. It is part of the PublicKey interface.

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

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

type Client struct { Conn

}

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

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.

package main

import ( "bytes" "fmt" "log"

"golang.org/x/crypto/ssh"

)

func main() { 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), } client, err := ssh.Dial("tcp", "yourserver.com:22", config) if err != nil { log.Fatal("Failed to dial: ", err) } defer client.Close()

// Each ClientConn can support multiple interactive sessions,
// represented by a Session.
session, err := client.NewSession()
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(c Conn, chans <-chan NewChannel, reqs <-chan *Request) *Client

NewClient creates a Client on top of the given connection.

Dial initiates a connection to the addr from the remote host. The resulting connection has a zero LocalAddr() and RemoteAddr().

DialContext initiates a connection to the addr from the remote host.

The provided Context must be non-nil. If the context expires before the connection is complete, an error is returned. Once successfully connected, any expiration of the context will not affect the connection.

See func Dial for additional information.

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) 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.

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".

package main

import ( "fmt" "log" "net/http"

"golang.org/x/crypto/ssh"

)

func main() { var hostKey ssh.PublicKey config := &ssh.ClientConfig{ User: "username", Auth: []ssh.AuthMethod{ ssh.Password("password"), }, HostKeyCallback: ssh.FixedHostKey(hostKey), } // Dial your ssh server. conn, err := ssh.Dial("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:

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

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

func (c Client) NewSession() (Session, error)

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

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

Config contains configuration data common to both ServerConfig and ClientConfig.

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.

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.

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.

ConnMetadata holds metadata for the connection.

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

type ExitError struct { Waitmsg }

An ExitError reports unsuccessful completion of a remote command.

type ExitMissingError struct{}

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

GSSAPIClient provides the API to plug-in GSSAPI authentication for client logins.

GSSAPIServer provides the API to plug in GSSAPI authentication for server logins.

type GSSAPIWithMICConfig struct {

AllowLogin func(conn [ConnMetadata](#ConnMetadata), srcName [string](/builtin#string)) (*[Permissions](#Permissions), [error](/builtin#error))


Server [GSSAPIServer](#GSSAPIServer)

}

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 SSH connection.

func FixedHostKey(key PublicKey) HostKeyCallback

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

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.

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 name and instruction messages should be printed. RFC 4256 section 3.3 details how the UI should behave for both CLI and GUI environments.

type MultiAlgorithmSigner interface { AlgorithmSigner

Algorithms() [][string](/builtin#string)

}

MultiAlgorithmSigner is an AlgorithmSigner that also reports the algorithms supported by that signer.

NewSignerWithAlgorithms returns a signer restricted to the specified algorithms. The algorithms must be set in preference order. The list must not be empty, and it must not include certificate types. An error is returned if the specified algorithms are incompatible with the public key type.

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 struct { Reason RejectionReason Message string }

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

type PartialSuccessError struct {

Next [ServerAuthCallbacks](#ServerAuthCallbacks)

}

PartialSuccessError can be returned by any of the ServerConfigauthentication callbacks to indicate to the client that authentication has partially succeeded, but further steps are required.

type PassphraseMissingError struct {

PublicKey [PublicKey](#PublicKey)

}

A PassphraseMissingError indicates that parsing this private key requires a passphrase. Use ParsePrivateKeyWithPassphrase.

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.

PublicKey represents a public key using an unspecified algorithm.

Some PublicKeys provided by this package also implement CryptoPublicKey.

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.

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

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.

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

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

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

String converts the rejection reason to human readable form.

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.

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 ServerAuthCallbacks struct {

PasswordCallback func(conn [ConnMetadata](#ConnMetadata), password [][byte](/builtin#byte)) (*[Permissions](#Permissions), [error](/builtin#error))


PublicKeyCallback func(conn [ConnMetadata](#ConnMetadata), key [PublicKey](#PublicKey)) (*[Permissions](#Permissions), [error](/builtin#error))


KeyboardInteractiveCallback func(conn [ConnMetadata](#ConnMetadata), client [KeyboardInteractiveChallenge](#KeyboardInteractiveChallenge)) (*[Permissions](#Permissions), [error](/builtin#error))


GSSAPIWithMICConfig *[GSSAPIWithMICConfig](#GSSAPIWithMICConfig)

}

ServerAuthCallbacks defines server-side authentication callbacks.

type ServerAuthError struct {

Errors [][error](/builtin#error)

}

ServerAuthError represents server authentication errors and is sometimes returned by NewServerConn. It appends any authentication errors that may occur, and is returned if all of the authentication methods provided by the user failed to authenticate.

type ServerConfig struct {

[Config](#Config)


PublicKeyAuthAlgorithms [][string](/builtin#string)


NoClientAuth [bool](/builtin#bool)


NoClientAuthCallback func([ConnMetadata](#ConnMetadata)) (*[Permissions](#Permissions), [error](/builtin#error))


MaxAuthTries [int](/builtin#int)


PasswordCallback func(conn [ConnMetadata](#ConnMetadata), password [][byte](/builtin#byte)) (*[Permissions](#Permissions), [error](/builtin#error))


PublicKeyCallback func(conn [ConnMetadata](#ConnMetadata), key [PublicKey](#PublicKey)) (*[Permissions](#Permissions), [error](/builtin#error))


KeyboardInteractiveCallback func(conn [ConnMetadata](#ConnMetadata), client [KeyboardInteractiveChallenge](#KeyboardInteractiveChallenge)) (*[Permissions](#Permissions), [error](/builtin#error))


AuthLogCallback func(conn [ConnMetadata](#ConnMetadata), method [string](/builtin#string), err [error](/builtin#error))


PreAuthConnCallback func([ServerPreAuthConn](#ServerPreAuthConn))


ServerVersion [string](/builtin#string)


BannerCallback func(conn [ConnMetadata](#ConnMetadata)) [string](/builtin#string)


GSSAPIWithMICConfig *[GSSAPIWithMICConfig](#GSSAPIWithMICConfig)

}

ServerConfig holds server specific configuration data.

func (s *ServerConfig) AddHostKey(key Signer)

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

package main

import ( "fmt" "log" "os"

"golang.org/x/crypto/ssh"

)

func main() { // Minimal ServerConfig supporting only password authentication. config := &ssh.ServerConfig{ 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()) }, }

privateBytes, err := os.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)
}
// Restrict host key algorithms to disable ssh-rsa.
signer, err := ssh.NewSignerWithAlgorithms(private.(ssh.AlgorithmSigner), []string{ssh.KeyAlgoRSASHA256, ssh.KeyAlgoRSASHA512})
if err != nil {
    log.Fatal("Failed to create private key with restricted algorithms: ", err)
}
config.AddHostKey(signer)

}

Output:

type ServerConn struct { Conn

Permissions *[Permissions](#Permissions)

}

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

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.

The returned error may be of type *ServerAuthError for authentication errors.

package main

import ( "fmt" "log" "net" "os" "sync"

"golang.org/x/crypto/ssh"
"golang.org/x/crypto/ssh/terminal"

)

func main() { // Public key authentication is done by comparing // the public key of a received connection // with the entries in the authorized_keys file. authorizedKeysBytes, err := os.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 := os.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.
conn, chans, reqs, err := ssh.NewServerConn(nConn, config)
if err != nil {
    log.Fatal("failed to handshake: ", err)
}
log.Printf("logged in with key %s", conn.Permissions.Extensions["pubkey-fp"])

var wg sync.WaitGroup
defer wg.Wait()

// The incoming Request channel must be serviced.
wg.Add(1)
go func() {
    ssh.DiscardRequests(reqs)
    wg.Done()
}()

// 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.
    wg.Add(1)
    go func(in <-chan *ssh.Request) {
        for req := range in {
            req.Reply(req.Type == "shell", nil)
        }
        wg.Done()
    }(requests)

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

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

}

Output:

type ServerPreAuthConn interface { ConnMetadata

SendAuthBanner([string](/builtin#string)) [error](/builtin#error)

}

ServerPreAuthConn is the interface available on an incoming server connection before authentication has completed.

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

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

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

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

package main

import ( "log"

"golang.org/x/crypto/ssh"

)

func main() { 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 conn, err := ssh.Dial("tcp", "localhost:22", config) if err != nil { log.Fatal("unable to connect: ", err) } defer conn.Close() // Create a session session, err := conn.NewSession() 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:

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

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.

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

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

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

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

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.

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.

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

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.

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.

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

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 struct { Format string Blob []byte Rest []byte ssh:"rest" }

Signature represents a cryptographic signature.

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

Some Signers provided by this package also implement MultiAlgorithmSigner.

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(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. DSA keys must use parameter size L1024N160.

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

ParsePrivateKey returns a Signer from a PEM encoded private key. It supports the same keys as ParseRawPrivateKey. If the private key is encrypted, it will return a PassphraseMissingError.

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.

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

func (w Waitmsg) ExitStatus() int

ExitStatus returns the exit status of the remote command.

Lang returns the language tag. See RFC 3066

Msg returns the exit message given by the remote command

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