diff options
Diffstat (limited to 'design/68723/ssh.html')
| -rw-r--r-- | design/68723/ssh.html | 2817 |
1 files changed, 2817 insertions, 0 deletions
diff --git a/design/68723/ssh.html b/design/68723/ssh.html new file mode 100644 index 0000000..c079e1a --- /dev/null +++ b/design/68723/ssh.html @@ -0,0 +1,2817 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <meta name="generator" content="doc2go"> + <title>ssh</title> + <style> + body { + margin: 1em 2em; + font-family: Helvetica, sans-serif; + background-color: #f8f8f8; + font-size: 1em; + } + + h1, + h2, + h3, + h4, + h5, + h6 { + margin-top: 0.3em; + margin-bottom: 0.3em; + } + + h1, + h2, + h3, + h4 { + font-weight: 500; + } + + h2 { + font-size: 1.75em + } + + h3 { + font-size: 1.5em + } + + h4 { + font-size: 1.33em + } + + h5 { + font-size: 1em + } + + a { + text-decoration: none; + color: #0366a5; + } + + a:hover { + text-decoration: underline; + } + + a.permalink { + display: none; + } + + a.permalink:hover { + text-decoration: none; + } + + *:hover>a.permalink { + display: inline; + } + + nav { + padding: 1em; + background-color: #eee; + border-radius: 0.5em; + display: flex; + flex-wrap: wrap; + } + + nav .navbar-right { + margin-left: auto; + } + + /* Remove first level of nesting for a package's index section. */ + #pkg-index+ul, + #pkg-examples+ul { + list-style-type: none; + padding: 0; + } + + code, + kbd, + pre { + font-family: Consolas, monospace; + } + + pre { + color: #222; + overflow-x: auto; + border: 1px solid #ccc; + border-radius: 0.5em; + background-color: #eee; + padding: 0.75em; + font-size: 0.9em; + } + + details.example>summary { + color: #0366a5; + cursor: pointer; + } + + details.deprecated>summary { + list-style: none; + } + + span.deprecated-tag { + color: #eee; + background-color: #999; + padding: 0.125rem 0.3rem; + border-radius: 0.3rem; + font-size: 0.7rem; + vertical-align: middle; + cursor: pointer; + } + + #search { + margin: 0.3em 0; + } + + #generated-by-footer { + font-size: x-small; + } + + /* Background */ + .bg { + background-color: #ffffff; + } + + /* PreWrapper */ + .chroma { + background-color: #ffffff; + } + + /* Error */ + .chroma .err { + color: #a61717; + background-color: #e3d2d2 + } + + /* LineLink */ + .chroma .lnlinks { + outline: none; + text-decoration: none; + color: inherit + } + + /* LineTableTD */ + .chroma .lntd { + vertical-align: top; + padding: 0; + margin: 0; + border: 0; + } + + /* LineTable */ + .chroma .lntable { + border-spacing: 0; + padding: 0; + margin: 0; + border: 0; + } + + /* LineHighlight */ + .chroma .hl { + background-color: #e5e5e5 + } + + /* LineNumbersTable */ + .chroma .lnt { + white-space: pre; + -webkit-user-select: none; + user-select: none; + margin-right: 0.4em; + padding: 0 0.4em 0 0.4em; + color: #7f7f7f + } + + /* LineNumbers */ + .chroma .ln { + white-space: pre; + -webkit-user-select: none; + user-select: none; + margin-right: 0.4em; + padding: 0 0.4em 0 0.4em; + color: #7f7f7f + } + + /* Line */ + .chroma .line { + display: flex; + } + + /* Keyword */ + .chroma .k { + color: #000000; + font-weight: bold + } + + /* KeywordConstant */ + .chroma .kc { + color: #000000; + font-weight: bold + } + + /* KeywordDeclaration */ + .chroma .kd { + color: #000000; + font-weight: bold + } + + /* KeywordNamespace */ + .chroma .kn { + color: #000000; + font-weight: bold + } + + /* KeywordPseudo */ + .chroma .kp { + color: #000000; + font-weight: bold + } + + /* KeywordReserved */ + .chroma .kr { + color: #000000; + font-weight: bold + } + + /* KeywordType */ + .chroma .kt { + color: #445588; + font-weight: bold + } + + /* NameAttribute */ + .chroma .na { + color: #008080 + } + + /* NameBuiltin */ + .chroma .nb { + color: #0086b3 + } + + /* NameBuiltinPseudo */ + .chroma .bp { + color: #999999 + } + + /* NameClass */ + .chroma .nc { + color: #445588; + font-weight: bold + } + + /* NameConstant */ + .chroma .no { + color: #008080 + } + + /* NameDecorator */ + .chroma .nd { + color: #3c5d5d; + font-weight: bold + } + + /* NameEntity */ + .chroma .ni { + color: #800080 + } + + /* NameException */ + .chroma .ne { + color: #990000; + font-weight: bold + } + + /* NameFunction */ + .chroma .nf { + color: #990000; + font-weight: bold + } + + /* NameLabel */ + .chroma .nl { + color: #990000; + font-weight: bold + } + + /* NameNamespace */ + .chroma .nn { + color: #555555 + } + + /* NameTag */ + .chroma .nt { + color: #000080 + } + + /* NameVariable */ + .chroma .nv { + color: #008080 + } + + /* NameVariableClass */ + .chroma .vc { + color: #008080 + } + + /* NameVariableGlobal */ + .chroma .vg { + color: #008080 + } + + /* NameVariableInstance */ + .chroma .vi { + color: #008080 + } + + /* LiteralString */ + .chroma .s { + color: #dd1144 + } + + /* LiteralStringAffix */ + .chroma .sa { + color: #dd1144 + } + + /* LiteralStringBacktick */ + .chroma .sb { + color: #dd1144 + } + + /* LiteralStringChar */ + .chroma .sc { + color: #dd1144 + } + + /* LiteralStringDelimiter */ + .chroma .dl { + color: #dd1144 + } + + /* LiteralStringDoc */ + .chroma .sd { + color: #dd1144 + } + + /* LiteralStringDouble */ + .chroma .s2 { + color: #dd1144 + } + + /* LiteralStringEscape */ + .chroma .se { + color: #dd1144 + } + + /* LiteralStringHeredoc */ + .chroma .sh { + color: #dd1144 + } + + /* LiteralStringInterpol */ + .chroma .si { + color: #dd1144 + } + + /* LiteralStringOther */ + .chroma .sx { + color: #dd1144 + } + + /* LiteralStringRegex */ + .chroma .sr { + color: #009926 + } + + /* LiteralStringSingle */ + .chroma .s1 { + color: #dd1144 + } + + /* LiteralStringSymbol */ + .chroma .ss { + color: #990073 + } + + /* LiteralNumber */ + .chroma .m { + color: #009999 + } + + /* LiteralNumberBin */ + .chroma .mb { + color: #009999 + } + + /* LiteralNumberFloat */ + .chroma .mf { + color: #009999 + } + + /* LiteralNumberHex */ + .chroma .mh { + color: #009999 + } + + /* LiteralNumberInteger */ + .chroma .mi { + color: #009999 + } + + /* LiteralNumberIntegerLong */ + .chroma .il { + color: #009999 + } + + /* LiteralNumberOct */ + .chroma .mo { + color: #009999 + } + + /* Operator */ + .chroma .o { + color: #000000; + font-weight: bold + } + + /* OperatorWord */ + .chroma .ow { + color: #000000; + font-weight: bold + } + + /* Comment */ + .chroma .c { + color: #999988; + font-style: italic + } + + /* CommentHashbang */ + .chroma .ch { + color: #999988; + font-style: italic + } + + /* CommentMultiline */ + .chroma .cm { + color: #999988; + font-style: italic + } + + /* CommentSingle */ + .chroma .c1 { + color: #999988; + font-style: italic + } + + /* CommentSpecial */ + .chroma .cs { + color: #999999; + font-weight: bold; + font-style: italic + } + + /* CommentPreproc */ + .chroma .cp { + color: #999999; + font-weight: bold; + font-style: italic + } + + /* CommentPreprocFile */ + .chroma .cpf { + color: #999999; + font-weight: bold; + font-style: italic + } + + /* GenericDeleted */ + .chroma .gd { + color: #000000; + background-color: #ffdddd + } + + /* GenericEmph */ + .chroma .ge { + color: #000000; + font-style: italic + } + + /* GenericError */ + .chroma .gr { + color: #aa0000 + } + + /* GenericHeading */ + .chroma .gh { + color: #999999 + } + + /* GenericInserted */ + .chroma .gi { + color: #000000; + background-color: #ddffdd + } + + /* GenericOutput */ + .chroma .go { + color: #888888 + } + + /* GenericPrompt */ + .chroma .gp { + color: #555555 + } + + /* GenericStrong */ + .chroma .gs { + font-weight: bold + } + + /* GenericSubheading */ + .chroma .gu { + color: #aaaaaa + } + + /* GenericTraceback */ + .chroma .gt { + color: #aa0000 + } + + /* GenericUnderline */ + .chroma .gl { + text-decoration: underline + } + + /* TextWhitespace */ + .chroma .w { + color: #bbbbbb + } + </style> +</head> + <body> + <main><h2 id="pkg-overview">package ssh</h2> +<pre class="chroma"><span class="kn">import</span> <span class="s">"golang.org/x/crypto/ssh"</span></pre> +<p>Package ssh implements an SSH client and server. +<p>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. +<p>References: +<pre>[PROTOCOL]: https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL?rev=HEAD +[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 +</pre> +<p>This package does not fall under the stability promise of the Go language itself, +so its API may be changed when pressing needs arise. +<h3 id="pkg-index">Index</h3> +<ul> + <li><a href="#pkg-constants">Constants</a></li><li><a href="#pkg-variables">Variables</a></li><li><a href="#FingerprintLegacyMD5">func FingerprintLegacyMD5(pubKey PublicKey) string</a></li> + <li><a href="#FingerprintSHA256">func FingerprintSHA256(pubKey PublicKey) string</a></li> + <li><a href="#Marshal">func Marshal(msg interface{}) []byte</a></li> + <li><a href="#MarshalAuthorizedKey">func MarshalAuthorizedKey(key PublicKey) []byte</a></li> + <li><a href="#MarshalPrivateKey">func MarshalPrivateKey(key crypto.PrivateKey, comment string) (*pem.Block, error)</a></li> + <li><a href="#MarshalPrivateKeyWithPassphrase">func MarshalPrivateKeyWithPassphrase(key crypto.PrivateKey, comment string, passphrase []byte) (*pem.Block, error)</a></li> + <li><a href="#ParseRawPrivateKey">func ParseRawPrivateKey(pemBytes []byte) (crypto.Signer, error)</a></li> + <li><a href="#ParseRawPrivateKeyWithPassphrase">func ParseRawPrivateKeyWithPassphrase(pemBytes, passphrase []byte) (crypto.Signer, error)</a></li> + <li><a href="#Unmarshal">func Unmarshal(data []byte, out interface{}) error</a></li> + <li> + <a href="#Algorithms">type Algorithms</a> + <ul> + <li><a href="#InsecureAlgorithms">func InsecureAlgorithms() Algorithms</a></li> + <li><a href="#SupportedAlgorithms">func SupportedAlgorithms() Algorithms</a></li> + </ul> + </li> + <li> + <a href="#AuthMethod">type AuthMethod</a> + <ul> + <li><a href="#GSSAPIWithMICAuthMethod">func GSSAPIWithMICAuthMethod(gssAPIClient GSSAPIClient, target string) AuthMethod</a></li> + <li><a href="#KeyboardInteractive">func KeyboardInteractive(challenge KeyboardInteractiveChallenge) AuthMethod</a></li> + <li><a href="#Password">func Password(secret string) AuthMethod</a></li> + <li><a href="#PasswordCallback">func PasswordCallback(prompt func() (secret string, err error)) AuthMethod</a></li> + <li><a href="#PublicKeys">func PublicKeys(signers ...Signer) AuthMethod</a></li> + <li><a href="#PublicKeysCallback">func PublicKeysCallback(getSigners func() (signers []Signer, err error)) AuthMethod</a></li> + <li><a href="#RetryableAuthMethod">func RetryableAuthMethod(auth AuthMethod, maxTries int) AuthMethod</a></li> + </ul> + </li> + <li> + <a href="#BannerCallback">type BannerCallback</a> + <ul> + <li><a href="#BannerDisplayStderr">func BannerDisplayStderr() BannerCallback</a></li> + </ul> + </li> + <li> + <a href="#BannerError">type BannerError</a> + <ul> + <li><a href="#BannerError.Error">func (b *BannerError) Error() string</a></li> + <li><a href="#BannerError.Unwrap">func (b *BannerError) Unwrap() error</a></li> + </ul> + </li> + <li> + <a href="#CertChecker">type CertChecker</a> + <ul> + <li><a href="#CertChecker.Authenticate">func (c *CertChecker) Authenticate(conn ConnMetadata, pubKey PublicKey) (*Permissions, error)</a></li> + <li><a href="#CertChecker.CheckCert">func (c *CertChecker) CheckCert(principal string, cert *Certificate) error</a></li> + <li><a href="#CertChecker.CheckHostKey">func (c *CertChecker) CheckHostKey(addr string, remote net.Addr, key PublicKey) error</a></li> + </ul> + </li> + <li> + <a href="#Certificate">type Certificate</a> + <ul> + <li><a href="#Certificate.Marshal">func (c *Certificate) Marshal() []byte</a></li> + <li><a href="#Certificate.SignCert">func (c *Certificate) SignCert(rand io.Reader, authority Signer) error</a></li> + <li><a href="#Certificate.Type">func (c *Certificate) Type() string</a></li> + <li><a href="#Certificate.Verify">func (c *Certificate) Verify(data []byte, sig *Signature) error</a></li> + </ul> + </li> + <li> + <a href="#Channel">type Channel</a> + <ul> + <li><a href="#Channel.Close">func (c *Channel) Close() error</a></li> + <li><a href="#Channel.CloseWrite">func (c *Channel) CloseWrite() error</a></li> + <li><a href="#Channel.Handle">func (c *Channel) Handle(handler RequestHandler) error</a></li> + <li><a href="#Channel.Read">func (c *Channel) Read(data []byte) (int, error)</a></li> + <li><a href="#Channel.SendRequest">func (c *Channel) SendRequest(name string, wantReply bool, payload []byte) (bool, error)</a></li> + <li><a href="#Channel.SetDeadline">func (c *Channel) SetDeadline(deadline time.Time) error</a></li> + <li><a href="#Channel.SetReadDeadline">func (c *Channel) SetReadDeadline(deadline time.Time) error</a></li> + <li><a href="#Channel.SetWriteDeadline">func (c *Channel) SetWriteDeadline(deadline time.Time) error</a></li> + <li><a href="#Channel.Stderr">func (c *Channel) Stderr() io.ReadWriter</a></li> + <li><a href="#Channel.Write">func (c *Channel) Write(data []byte) (int, error)</a></li> + </ul> + </li> + <li> + <a href="#ChannelHandler">type ChannelHandler</a> + </li> + <li> + <a href="#ChannelHandlerFunc">type ChannelHandlerFunc</a> + <ul> + <li><a href="#ChannelHandlerFunc.NewChannel">func (f ChannelHandlerFunc) NewChannel(ch *NewChannel)</a></li> + </ul> + </li> + <li> + <a href="#Client">type Client</a> + <ul> + <li><a href="#Dial">func Dial(ctx context.Context, network, addr string, config *ClientConfig) (*Client, error)</a></li> + <li><a href="#NewClient">func NewClient(c *ClientConn) *Client</a></li> + <li><a href="#Client.Close">func (c Client) Close() error</a></li> + <li><a href="#Client.Dial">func (c *Client) Dial(ctx context.Context, n, addr string) (net.Conn, error)</a></li> + <li><a href="#Client.DialTCP">func (c *Client) DialTCP(ctx context.Context, n string, laddr, raddr *net.TCPAddr) (net.Conn, error)</a></li> + <li><a href="#Client.HandleChannelOpen">func (c *Client) HandleChannelOpen(channelType string, handler ChannelHandler) error</a></li> + <li><a href="#Client.Listen">func (c *Client) Listen(n, addr string) (net.Listener, error)</a></li> + <li><a href="#Client.ListenUnix">func (c *Client) ListenUnix(socketPath string) (net.Listener, error)</a></li> + <li><a href="#Client.NewSession">func (c *Client) NewSession() (*Session, error)</a></li> + </ul> + </li> + <li> + <a href="#ClientConfig">type ClientConfig</a> + </li> + <li> + <a href="#ClientConn">type ClientConn</a> + <ul> + <li><a href="#NewClientConn">func NewClientConn(c net.Conn, addr string, config *ClientConfig) (*ClientConn, error)</a></li> + <li><a href="#ClientConn.Close">func (c ClientConn) Close() error</a></li> + <li><a href="#ClientConn.Handle">func (c *ClientConn) Handle(channelHandler ChannelHandler, requestHandler RequestHandler) error</a></li> + </ul> + </li> + <li> + <a href="#ClientHandler">type ClientHandler</a> + </li> + <li> + <a href="#ClientHandlerFunc">type ClientHandlerFunc</a> + <ul> + <li><a href="#ClientHandlerFunc.HandleClient">func (f ClientHandlerFunc) HandleClient(conn *ServerConn)</a></li> + </ul> + </li> + <li> + <a href="#Config">type Config</a> + <ul> + <li><a href="#Config.SetDefaults">func (c *Config) SetDefaults()</a></li> + </ul> + </li> + <li> + <a href="#ConnMetadata">type ConnMetadata</a> + <ul> + <li><a href="#ConnMetadata.ClientVersion">func (c ConnMetadata) ClientVersion() []byte</a></li> + <li><a href="#ConnMetadata.LocalAddr">func (c ConnMetadata) LocalAddr() net.Addr</a></li> + <li><a href="#ConnMetadata.RemoteAddr">func (c ConnMetadata) RemoteAddr() net.Addr</a></li> + <li><a href="#ConnMetadata.ServerVersion">func (c ConnMetadata) ServerVersion() []byte</a></li> + <li><a href="#ConnMetadata.SessionID">func (c ConnMetadata) SessionID() []byte</a></li> + <li><a href="#ConnMetadata.User">func (c ConnMetadata) User() string</a></li> + </ul> + </li> + <li> + <a href="#CryptoPublicKey">type CryptoPublicKey</a> + </li> + <li> + <a href="#ExitError">type ExitError</a> + <ul> + <li><a href="#ExitError.Error">func (e *ExitError) Error() string</a></li> + </ul> + </li> + <li> + <a href="#ExitMissingError">type ExitMissingError</a> + <ul> + <li><a href="#ExitMissingError.Error">func (e *ExitMissingError) Error() string</a></li> + </ul> + </li> + <li> + <a href="#GSSAPIClient">type GSSAPIClient</a> + </li> + <li> + <a href="#GSSAPIServer">type GSSAPIServer</a> + </li> + <li> + <a href="#GSSAPIWithMICConfig">type GSSAPIWithMICConfig</a> + </li> + <li> + <a href="#HostKeyCallback">type HostKeyCallback</a> + <ul> + <li><a href="#FixedHostKey">func FixedHostKey(key PublicKey) HostKeyCallback</a></li> + <li><a href="#InsecureIgnoreHostKey">func InsecureIgnoreHostKey() HostKeyCallback</a></li> + </ul> + </li> + <li> + <a href="#KeyboardInteractiveChallenge">type KeyboardInteractiveChallenge</a> + </li> + <li> + <a href="#NewChannel">type NewChannel</a> + <ul> + <li><a href="#NewChannel.Accept">func (c *NewChannel) Accept() (*Channel, error)</a></li> + <li><a href="#NewChannel.ChannelType">func (c *NewChannel) ChannelType() string</a></li> + <li><a href="#NewChannel.ExtraData">func (c *NewChannel) ExtraData() []byte</a></li> + <li><a href="#NewChannel.Reject">func (c *NewChannel) Reject(reason RejectionReason, message string) error</a></li> + </ul> + </li> + <li> + <a href="#OpenChannelError">type OpenChannelError</a> + <ul> + <li><a href="#OpenChannelError.Error">func (e *OpenChannelError) Error() string</a></li> + </ul> + </li> + <li> + <a href="#PartialSuccessError">type PartialSuccessError</a> + <ul> + <li><a href="#PartialSuccessError.Error">func (p *PartialSuccessError) Error() string</a></li> + </ul> + </li> + <li> + <a href="#PassphraseMissingError">type PassphraseMissingError</a> + <ul> + <li><a href="#PassphraseMissingError.Error">func (*PassphraseMissingError) Error() string</a></li> + </ul> + </li> + <li> + <a href="#Permissions">type Permissions</a> + </li> + <li> + <a href="#PublicKey">type PublicKey</a> + <ul> + <li><a href="#NewPublicKey">func NewPublicKey(key interface{}) (PublicKey, error)</a></li> + <li><a href="#ParseAuthorizedKey">func ParseAuthorizedKey(in []byte) (out PublicKey, comment string, options []string, rest []byte, err error)</a></li> + <li><a href="#ParseKnownHosts">func ParseKnownHosts(in []byte) (marker string, hosts []string, pubKey PublicKey, comment string, rest []byte, ...)</a></li> + <li><a href="#ParsePublicKey">func ParsePublicKey(in []byte) (out PublicKey, err error)</a></li> + </ul> + </li> + <li> + <a href="#RejectionReason">type RejectionReason</a> + <ul> + <li><a href="#RejectionReason.String">func (r RejectionReason) String() string</a></li> + </ul> + </li> + <li> + <a href="#Request">type Request</a> + <ul> + <li><a href="#Request.Reply">func (r *Request) Reply(ok bool, payload []byte) error</a></li> + </ul> + </li> + <li> + <a href="#RequestHandler">type RequestHandler</a> + </li> + <li> + <a href="#RequestHandlerFunc">type RequestHandlerFunc</a> + <ul> + <li><a href="#RequestHandlerFunc.NewRequest">func (f RequestHandlerFunc) NewRequest(req *Request)</a></li> + </ul> + </li> + <li> + <a href="#Server">type Server</a> + <ul> + <li><a href="#Server.AddHostKey">func (s *Server) AddHostKey(key Signer)</a></li> + <li><a href="#Server.Close">func (s *Server) Close() error</a></li> + <li><a href="#Server.ListenAndServe">func (s *Server) ListenAndServe(addr string) error</a></li> + <li><a href="#Server.Serve">func (s *Server) Serve(l net.Listener) error</a></li> + </ul> + </li> + <li> + <a href="#ServerAuthCallbacks">type ServerAuthCallbacks</a> + </li> + <li> + <a href="#ServerAuthError">type ServerAuthError</a> + <ul> + <li><a href="#ServerAuthError.Error">func (l ServerAuthError) Error() string</a></li> + </ul> + </li> + <li> + <a href="#ServerConn">type ServerConn</a> + <ul> + <li><a href="#NewServerConn">func NewServerConn(ctx context.Context, c net.Conn, config *Server) (*ServerConn, error)</a></li> + <li><a href="#ServerConn.Close">func (c *ServerConn) Close() error</a></li> + <li><a href="#ServerConn.Handle">func (c *ServerConn) Handle(channelHandler ChannelHandler, requestHandler RequestHandler) error</a></li> + </ul> + </li> + <li> + <a href="#Session">type Session</a> + <ul> + <li><a href="#Session.Close">func (s *Session) Close() error</a></li> + <li><a href="#Session.CombinedOutput">func (s *Session) CombinedOutput(cmd string) ([]byte, error)</a></li> + <li><a href="#Session.Output">func (s *Session) Output(cmd string) ([]byte, error)</a></li> + <li><a href="#Session.RequestPty">func (s *Session) RequestPty(term string, h, w int, termmodes TerminalModes) error</a></li> + <li><a href="#Session.RequestSubsystem">func (s *Session) RequestSubsystem(subsystem string) error</a></li> + <li><a href="#Session.Run">func (s *Session) Run(cmd string) error</a></li> + <li><a href="#Session.SendRequest">func (s *Session) SendRequest(name string, wantReply bool, payload []byte) (bool, error)</a></li> + <li><a href="#Session.Setenv">func (s *Session) Setenv(name, value string) error</a></li> + <li><a href="#Session.Shell">func (s *Session) Shell() error</a></li> + <li><a href="#Session.Signal">func (s *Session) Signal(sig Signal) error</a></li> + <li><a href="#Session.Start">func (s *Session) Start(cmd string) error</a></li> + <li><a href="#Session.StderrPipe">func (s *Session) StderrPipe() (io.Reader, error)</a></li> + <li><a href="#Session.StdinPipe">func (s *Session) StdinPipe() (io.WriteCloser, error)</a></li> + <li><a href="#Session.StdoutPipe">func (s *Session) StdoutPipe() (io.Reader, error)</a></li> + <li><a href="#Session.Wait">func (s *Session) Wait() error</a></li> + <li><a href="#Session.WindowChange">func (s *Session) WindowChange(h, w int) error</a></li> + </ul> + </li> + <li> + <a href="#Signal">type Signal</a> + </li> + <li> + <a href="#Signature">type Signature</a> + </li> + <li> + <a href="#Signer">type Signer</a> + <ul> + <li><a href="#NewCertSigner">func NewCertSigner(cert *Certificate, signer Signer) (Signer, error)</a></li> + <li><a href="#NewSigner">func NewSigner(signer crypto.Signer) (Signer, error)</a></li> + <li><a href="#NewSignerWithAlgorithms">func NewSignerWithAlgorithms(signer Signer, algorithms []string) (Signer, error)</a></li> + <li><a href="#ParsePrivateKey">func ParsePrivateKey(pemBytes []byte) (Signer, error)</a></li> + <li><a href="#ParsePrivateKeyWithPassphrase">func ParsePrivateKeyWithPassphrase(pemBytes, passphrase []byte) (Signer, error)</a></li> + </ul> + </li> + <li> + <a href="#TerminalModes">type TerminalModes</a> + </li> + <li> + <a href="#Waitmsg">type Waitmsg</a> + <ul> + <li><a href="#Waitmsg.ExitStatus">func (w Waitmsg) ExitStatus() int</a></li> + <li><a href="#Waitmsg.Lang">func (w Waitmsg) Lang() string</a></li> + <li><a href="#Waitmsg.Msg">func (w Waitmsg) Msg() string</a></li> + <li><a href="#Waitmsg.Signal">func (w Waitmsg) Signal() string</a></li> + <li><a href="#Waitmsg.String">func (w Waitmsg) String() string</a></li> + </ul> + </li> + </ul><h4 id="pkg-examples">Examples</h4> +<ul> + <li><a href="#example-Certificate.SignCert">Certificate.SignCert</a></li> + <li><a href="#example-Client.Listen">Client.Listen</a></li> + <li><a href="#example-Dial">Dial</a></li> + <li><a href="#example-NewServerConn">NewServerConn</a></li> + <li><a href="#example-PublicKeys">PublicKeys</a></li> + <li><a href="#example-RetryableAuthMethod">RetryableAuthMethod</a></li> + <li><a href="#example-Server.AddHostKey">Server.AddHostKey</a></li> + <li><a href="#example-Server.ListenAndServe">Server.ListenAndServe</a></li> + <li><a href="#example-Session.RequestPty">Session.RequestPty</a></li> + </ul><h3 id="pkg-constants">Constants</h3> + <pre class="chroma"><span class="kd">const</span> <span class="p">(</span> + <span id="CertAlgoRSAv01"><span class="nx">CertAlgoRSAv01</span></span> <span class="p">=</span> <span class="s">"ssh-rsa-cert-v01@openssh.com"</span> + <span id="CertAlgoECDSA256v01"><span class="nx">CertAlgoECDSA256v01</span></span> <span class="p">=</span> <span class="s">"ecdsa-sha2-nistp256-cert-v01@openssh.com"</span> + <span id="CertAlgoECDSA384v01"><span class="nx">CertAlgoECDSA384v01</span></span> <span class="p">=</span> <span class="s">"ecdsa-sha2-nistp384-cert-v01@openssh.com"</span> + <span id="CertAlgoECDSA521v01"><span class="nx">CertAlgoECDSA521v01</span></span> <span class="p">=</span> <span class="s">"ecdsa-sha2-nistp521-cert-v01@openssh.com"</span> + <span id="CertAlgoSKECDSA256v01"><span class="nx">CertAlgoSKECDSA256v01</span></span> <span class="p">=</span> <span class="s">"sk-ecdsa-sha2-nistp256-cert-v01@openssh.com"</span> + <span id="CertAlgoED25519v01"><span class="nx">CertAlgoED25519v01</span></span> <span class="p">=</span> <span class="s">"ssh-ed25519-cert-v01@openssh.com"</span> + <span id="CertAlgoSKED25519v01"><span class="nx">CertAlgoSKED25519v01</span></span> <span class="p">=</span> <span class="s">"sk-ssh-ed25519-cert-v01@openssh.com"</span> + + <span class="c1">// CertAlgoRSASHA256v01 and CertAlgoRSASHA512v01 can't appear as a +</span><span class="c1"></span> <span class="c1">// Certificate.Type (or PublicKey.Type), but only in +</span><span class="c1"></span> <span class="c1">// ClientConfig.HostKeyAlgorithms. +</span><span class="c1"></span> <span id="CertAlgoRSASHA256v01"><span class="nx">CertAlgoRSASHA256v01</span></span> <span class="p">=</span> <span class="s">"rsa-sha2-256-cert-v01@openssh.com"</span> + <span id="CertAlgoRSASHA512v01"><span class="nx">CertAlgoRSASHA512v01</span></span> <span class="p">=</span> <span class="s">"rsa-sha2-512-cert-v01@openssh.com"</span> +<span class="p">)</span></pre> + <p>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. +<pre class="chroma"><span class="kd">const</span> <span class="p">(</span> + <span id="UserCert"><span class="nx">UserCert</span></span> <span class="p">=</span> <span class="mi">1</span> + <span id="HostCert"><span class="nx">HostCert</span></span> <span class="p">=</span> <span class="mi">2</span> +<span class="p">)</span></pre> + <p>Certificate types distinguish between host and user +certificates. The values can be set in the CertType field of +Certificate. +<pre class="chroma"><span class="kd">const</span> <span class="p">(</span> + <span id="CipherAES128GCM"><span class="nx">CipherAES128GCM</span></span> <span class="p">=</span> <span class="s">"aes128-gcm@openssh.com"</span> + <span id="CipherAES256GCM"><span class="nx">CipherAES256GCM</span></span> <span class="p">=</span> <span class="s">"aes256-gcm@openssh.com"</span> + <span id="CipherChacha20Poly1305"><span class="nx">CipherChacha20Poly1305</span></span> <span class="p">=</span> <span class="s">"chacha20-poly1305@openssh.com"</span> + <span id="CipherAES128CTR"><span class="nx">CipherAES128CTR</span></span> <span class="p">=</span> <span class="s">"aes128-ctr"</span> + <span id="CipherAES192CTR"><span class="nx">CipherAES192CTR</span></span> <span class="p">=</span> <span class="s">"aes192-ctr"</span> + <span id="CipherAES256CTR"><span class="nx">CipherAES256CTR</span></span> <span class="p">=</span> <span class="s">"aes256-ctr"</span> + <span id="InsecureCipherAES128CBC"><span class="nx">InsecureCipherAES128CBC</span></span> <span class="p">=</span> <span class="s">"aes128-cbc"</span> + <span id="InsecureCipherTripleDESCBC"><span class="nx">InsecureCipherTripleDESCBC</span></span> <span class="p">=</span> <span class="s">"3des-cbc"</span> + <span id="InsecureCipherRC4"><span class="nx">InsecureCipherRC4</span></span> <span class="p">=</span> <span class="s">"arcfour"</span> + <span id="InsecureCipherRC4128"><span class="nx">InsecureCipherRC4128</span></span> <span class="p">=</span> <span class="s">"arcfour128"</span> + <span id="InsecureCipherRC4256"><span class="nx">InsecureCipherRC4256</span></span> <span class="p">=</span> <span class="s">"arcfour256"</span> +<span class="p">)</span></pre> + <p>Implemented ciphers algorithms. +<pre class="chroma"><span class="kd">const</span> <span class="p">(</span> + <span id="InsecureKeyExchangeDH1SHA1"><span class="nx">InsecureKeyExchangeDH1SHA1</span></span> <span class="p">=</span> <span class="s">"diffie-hellman-group1-sha1"</span> + <span id="InsecureKeyExchangeDH14SHA1"><span class="nx">InsecureKeyExchangeDH14SHA1</span></span> <span class="p">=</span> <span class="s">"diffie-hellman-group14-sha1"</span> + <span id="KeyExchangeDH14SHA256"><span class="nx">KeyExchangeDH14SHA256</span></span> <span class="p">=</span> <span class="s">"diffie-hellman-group14-sha256"</span> + <span id="KeyExchangeDH16SHA512"><span class="nx">KeyExchangeDH16SHA512</span></span> <span class="p">=</span> <span class="s">"diffie-hellman-group16-sha512"</span> + <span id="KeyExchangeECDHP256"><span class="nx">KeyExchangeECDHP256</span></span> <span class="p">=</span> <span class="s">"ecdh-sha2-nistp256"</span> + <span id="KeyExchangeECDHP384"><span class="nx">KeyExchangeECDHP384</span></span> <span class="p">=</span> <span class="s">"ecdh-sha2-nistp384"</span> + <span id="KeyExchangeECDHP521"><span class="nx">KeyExchangeECDHP521</span></span> <span class="p">=</span> <span class="s">"ecdh-sha2-nistp521"</span> + <span id="KeyExchangeCurve25519SHA256"><span class="nx">KeyExchangeCurve25519SHA256</span></span> <span class="p">=</span> <span class="s">"curve25519-sha256"</span> + <span id="InsecureKeyExchangeDHGEXSHA1"><span class="nx">InsecureKeyExchangeDHGEXSHA1</span></span> <span class="p">=</span> <span class="s">"diffie-hellman-group-exchange-sha1"</span> + <span id="KeyExchangeDHGEXSHA256"><span class="nx">KeyExchangeDHGEXSHA256</span></span> <span class="p">=</span> <span class="s">"diffie-hellman-group-exchange-sha256"</span> +<span class="p">)</span></pre> + <p>Implemented key exchanges algorithms. +<pre class="chroma"><span class="kd">const</span> <span class="p">(</span> + <span id="HMACSHA256ETM"><span class="nx">HMACSHA256ETM</span></span> <span class="p">=</span> <span class="s">"hmac-sha2-256-etm@openssh.com"</span> + <span id="HMACSHA512ETM"><span class="nx">HMACSHA512ETM</span></span> <span class="p">=</span> <span class="s">"hmac-sha2-512-etm@openssh.com"</span> + <span id="HMACSHA256"><span class="nx">HMACSHA256</span></span> <span class="p">=</span> <span class="s">"hmac-sha2-256"</span> + <span id="HMACSHA512"><span class="nx">HMACSHA512</span></span> <span class="p">=</span> <span class="s">"hmac-sha2-512"</span> + <span id="InsecureHMACSHA1"><span class="nx">InsecureHMACSHA1</span></span> <span class="p">=</span> <span class="s">"hmac-sha1"</span> + <span id="InsecureHMACSHA196"><span class="nx">InsecureHMACSHA196</span></span> <span class="p">=</span> <span class="s">"hmac-sha1-96"</span> +<span class="p">)</span></pre> + <p>Implemented message authentication code (MAC) algorithms. +<pre class="chroma"><span class="kd">const</span> <span class="p">(</span> + <span id="KeyTypeRSA"><span class="nx">KeyTypeRSA</span></span> <span class="p">=</span> <span class="s">"ssh-rsa"</span> + <span id="KeyTypeECDSA256"><span class="nx">KeyTypeECDSA256</span></span> <span class="p">=</span> <span class="s">"ecdsa-sha2-nistp256"</span> + <span id="KeyTypeECDSA384"><span class="nx">KeyTypeECDSA384</span></span> <span class="p">=</span> <span class="s">"ecdsa-sha2-nistp384"</span> + <span id="KeyTypeECDSA521"><span class="nx">KeyTypeECDSA521</span></span> <span class="p">=</span> <span class="s">"ecdsa-sha2-nistp521"</span> + <span id="KeyTypeSKECDSA256"><span class="nx">KeyTypeSKECDSA256</span></span> <span class="p">=</span> <span class="s">"sk-ecdsa-sha2-nistp256@openssh.com"</span> + <span id="KeyTypeED25519"><span class="nx">KeyTypeED25519</span></span> <span class="p">=</span> <span class="s">"ssh-ed25519"</span> + <span id="KeyTypeSKED25519"><span class="nx">KeyTypeSKED25519</span></span> <span class="p">=</span> <span class="s">"sk-ssh-ed25519@openssh.com"</span> +<span class="p">)</span></pre> + <p>Implemented public key types. +<pre class="chroma"><span class="kd">const</span> <span class="p">(</span> + <span id="KeyAlgoRSA"><span class="nx">KeyAlgoRSA</span></span> <span class="p">=</span> <span class="s">"ssh-rsa"</span> + <span id="KeyAlgoECDSA256"><span class="nx">KeyAlgoECDSA256</span></span> <span class="p">=</span> <span class="s">"ecdsa-sha2-nistp256"</span> + <span id="KeyAlgoSKECDSA256"><span class="nx">KeyAlgoSKECDSA256</span></span> <span class="p">=</span> <span class="s">"sk-ecdsa-sha2-nistp256@openssh.com"</span> + <span id="KeyAlgoECDSA384"><span class="nx">KeyAlgoECDSA384</span></span> <span class="p">=</span> <span class="s">"ecdsa-sha2-nistp384"</span> + <span id="KeyAlgoECDSA521"><span class="nx">KeyAlgoECDSA521</span></span> <span class="p">=</span> <span class="s">"ecdsa-sha2-nistp521"</span> + <span id="KeyAlgoED25519"><span class="nx">KeyAlgoED25519</span></span> <span class="p">=</span> <span class="s">"ssh-ed25519"</span> + <span id="KeyAlgoSKED25519"><span class="nx">KeyAlgoSKED25519</span></span> <span class="p">=</span> <span class="s">"sk-ssh-ed25519@openssh.com"</span> + + <span class="c1">// KeyAlgoRSASHA256 and KeyAlgoRSASHA512 are only public key algorithms, not +</span><span class="c1"></span> <span class="c1">// public key formats, so they can't appear as a PublicKey.Type. The +</span><span class="c1"></span> <span class="c1">// corresponding PublicKey.Type is KeyAlgoRSA. See RFC 8332, Section 2. +</span><span class="c1"></span> <span id="KeyAlgoRSASHA256"><span class="nx">KeyAlgoRSASHA256</span></span> <span class="p">=</span> <span class="s">"rsa-sha2-256"</span> + <span id="KeyAlgoRSASHA512"><span class="nx">KeyAlgoRSASHA512</span></span> <span class="p">=</span> <span class="s">"rsa-sha2-512"</span> +<span class="p">)</span></pre> + <p>Public key algorithms names. These values can appear in PublicKey.Type, +ClientConfig.HostKeyAlgorithms, Signature.Format, or as AlgorithmSigner +arguments. +<pre class="chroma"><span class="kd">const</span> <span class="p">(</span> + <span id="VINTR"><span class="nx">VINTR</span></span> <span class="p">=</span> <span class="mi">1</span> + <span id="VQUIT"><span class="nx">VQUIT</span></span> <span class="p">=</span> <span class="mi">2</span> + <span id="VERASE"><span class="nx">VERASE</span></span> <span class="p">=</span> <span class="mi">3</span> + <span id="VKILL"><span class="nx">VKILL</span></span> <span class="p">=</span> <span class="mi">4</span> + <span id="VEOF"><span class="nx">VEOF</span></span> <span class="p">=</span> <span class="mi">5</span> + <span id="VEOL"><span class="nx">VEOL</span></span> <span class="p">=</span> <span class="mi">6</span> + <span id="VEOL2"><span class="nx">VEOL2</span></span> <span class="p">=</span> <span class="mi">7</span> + <span id="VSTART"><span class="nx">VSTART</span></span> <span class="p">=</span> <span class="mi">8</span> + <span id="VSTOP"><span class="nx">VSTOP</span></span> <span class="p">=</span> <span class="mi">9</span> + <span id="VSUSP"><span class="nx">VSUSP</span></span> <span class="p">=</span> <span class="mi">10</span> + <span id="VDSUSP"><span class="nx">VDSUSP</span></span> <span class="p">=</span> <span class="mi">11</span> + <span id="VREPRINT"><span class="nx">VREPRINT</span></span> <span class="p">=</span> <span class="mi">12</span> + <span id="VWERASE"><span class="nx">VWERASE</span></span> <span class="p">=</span> <span class="mi">13</span> + <span id="VLNEXT"><span class="nx">VLNEXT</span></span> <span class="p">=</span> <span class="mi">14</span> + <span id="VFLUSH"><span class="nx">VFLUSH</span></span> <span class="p">=</span> <span class="mi">15</span> + <span id="VSWTCH"><span class="nx">VSWTCH</span></span> <span class="p">=</span> <span class="mi">16</span> + <span id="VSTATUS"><span class="nx">VSTATUS</span></span> <span class="p">=</span> <span class="mi">17</span> + <span id="VDISCARD"><span class="nx">VDISCARD</span></span> <span class="p">=</span> <span class="mi">18</span> + <span id="IGNPAR"><span class="nx">IGNPAR</span></span> <span class="p">=</span> <span class="mi">30</span> + <span id="PARMRK"><span class="nx">PARMRK</span></span> <span class="p">=</span> <span class="mi">31</span> + <span id="INPCK"><span class="nx">INPCK</span></span> <span class="p">=</span> <span class="mi">32</span> + <span id="ISTRIP"><span class="nx">ISTRIP</span></span> <span class="p">=</span> <span class="mi">33</span> + <span id="INLCR"><span class="nx">INLCR</span></span> <span class="p">=</span> <span class="mi">34</span> + <span id="IGNCR"><span class="nx">IGNCR</span></span> <span class="p">=</span> <span class="mi">35</span> + <span id="ICRNL"><span class="nx">ICRNL</span></span> <span class="p">=</span> <span class="mi">36</span> + <span id="IUCLC"><span class="nx">IUCLC</span></span> <span class="p">=</span> <span class="mi">37</span> + <span id="IXON"><span class="nx">IXON</span></span> <span class="p">=</span> <span class="mi">38</span> + <span id="IXANY"><span class="nx">IXANY</span></span> <span class="p">=</span> <span class="mi">39</span> + <span id="IXOFF"><span class="nx">IXOFF</span></span> <span class="p">=</span> <span class="mi">40</span> + <span id="IMAXBEL"><span class="nx">IMAXBEL</span></span> <span class="p">=</span> <span class="mi">41</span> + <span id="IUTF8"><span class="nx">IUTF8</span></span> <span class="p">=</span> <span class="mi">42</span> <span class="c1">// RFC 8160 +</span><span class="c1"></span> <span id="ISIG"><span class="nx">ISIG</span></span> <span class="p">=</span> <span class="mi">50</span> + <span id="ICANON"><span class="nx">ICANON</span></span> <span class="p">=</span> <span class="mi">51</span> + <span id="XCASE"><span class="nx">XCASE</span></span> <span class="p">=</span> <span class="mi">52</span> + <span id="ECHO"><span class="nx">ECHO</span></span> <span class="p">=</span> <span class="mi">53</span> + <span id="ECHOE"><span class="nx">ECHOE</span></span> <span class="p">=</span> <span class="mi">54</span> + <span id="ECHOK"><span class="nx">ECHOK</span></span> <span class="p">=</span> <span class="mi">55</span> + <span id="ECHONL"><span class="nx">ECHONL</span></span> <span class="p">=</span> <span class="mi">56</span> + <span id="NOFLSH"><span class="nx">NOFLSH</span></span> <span class="p">=</span> <span class="mi">57</span> + <span id="TOSTOP"><span class="nx">TOSTOP</span></span> <span class="p">=</span> <span class="mi">58</span> + <span id="IEXTEN"><span class="nx">IEXTEN</span></span> <span class="p">=</span> <span class="mi">59</span> + <span id="ECHOCTL"><span class="nx">ECHOCTL</span></span> <span class="p">=</span> <span class="mi">60</span> + <span id="ECHOKE"><span class="nx">ECHOKE</span></span> <span class="p">=</span> <span class="mi">61</span> + <span id="PENDIN"><span class="nx">PENDIN</span></span> <span class="p">=</span> <span class="mi">62</span> + <span id="OPOST"><span class="nx">OPOST</span></span> <span class="p">=</span> <span class="mi">70</span> + <span id="OLCUC"><span class="nx">OLCUC</span></span> <span class="p">=</span> <span class="mi">71</span> + <span id="ONLCR"><span class="nx">ONLCR</span></span> <span class="p">=</span> <span class="mi">72</span> + <span id="OCRNL"><span class="nx">OCRNL</span></span> <span class="p">=</span> <span class="mi">73</span> + <span id="ONOCR"><span class="nx">ONOCR</span></span> <span class="p">=</span> <span class="mi">74</span> + <span id="ONLRET"><span class="nx">ONLRET</span></span> <span class="p">=</span> <span class="mi">75</span> + <span id="CS7"><span class="nx">CS7</span></span> <span class="p">=</span> <span class="mi">90</span> + <span id="CS8"><span class="nx">CS8</span></span> <span class="p">=</span> <span class="mi">91</span> + <span id="PARENB"><span class="nx">PARENB</span></span> <span class="p">=</span> <span class="mi">92</span> + <span id="PARODD"><span class="nx">PARODD</span></span> <span class="p">=</span> <span class="mi">93</span> + <span id="TTY_OP_ISPEED"><span class="nx">TTY_OP_ISPEED</span></span> <span class="p">=</span> <span class="mi">128</span> + <span id="TTY_OP_OSPEED"><span class="nx">TTY_OP_OSPEED</span></span> <span class="p">=</span> <span class="mi">129</span> +<span class="p">)</span></pre> + <p>POSIX terminal mode flags as listed in RFC 4254 Section 8. +<pre class="chroma"><span class="kd">const</span> <span id="CertTimeInfinity"><span class="nx">CertTimeInfinity</span></span> <span class="p">=</span> <span class="mi">1</span><span class="o"><<</span><span class="mi">64</span> <span class="o">-</span> <span class="mi">1</span></pre> + <p>CertTimeInfinity can be used for OpenSSHCertV01.ValidBefore to indicate that +a certificate does not expire. +<h3 id="pkg-variables">Variables</h3> + <pre class="chroma"><span class="kd">var</span> <span id="ErrNoAuth"><span class="nx">ErrNoAuth</span></span> <span class="p">=</span> <a href="https://pkg.go.dev/errors"><span class="nx">errors</span></a><span class="p">.</span><a href="https://pkg.go.dev/errors#New"><span class="nf">New</span></a><span class="p">(</span><span class="s">"ssh: no auth passed yet"</span><span class="p">)</span></pre> + <p>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. +<h3 id="pkg-functions">Functions</h3> + <h3 id="FingerprintLegacyMD5">func FingerprintLegacyMD5</h3> + <pre class="chroma"><span class="kd">func</span> <span class="nf">FingerprintLegacyMD5</span><span class="p">(</span><span class="nx">pubKey</span> <a href="#PublicKey"><span class="nx">PublicKey</span></a><span class="p">)</span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a></pre> + <p>FingerprintLegacyMD5 returns the user presentation of the key's +fingerprint as described by RFC 4716 section 4. +<h3 id="FingerprintSHA256">func FingerprintSHA256</h3> + <pre class="chroma"><span class="kd">func</span> <span class="nf">FingerprintSHA256</span><span class="p">(</span><span class="nx">pubKey</span> <a href="#PublicKey"><span class="nx">PublicKey</span></a><span class="p">)</span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a></pre> + <p>FingerprintSHA256 returns the user presentation of the key's +fingerprint as unpadded base64 encoded sha256 hash. +This format was introduced from OpenSSH 6.8. +<a href="https://www.openssh.com/txt/release-6.8">https://www.openssh.com/txt/release-6.8</a> +<a href="https://tools.ietf.org/html/rfc4648#section-3.2">https://tools.ietf.org/html/rfc4648#section-3.2</a> (unpadded base64 encoding) +<h3 id="Marshal">func Marshal</h3> + <pre class="chroma"><span class="kd">func</span> <span class="nf">Marshal</span><span class="p">(</span><span class="nx">msg</span> <span class="kd">interface</span><span class="p">{})</span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#byte"><span class="kt">byte</span></a></pre> + <p>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. +<h3 id="MarshalAuthorizedKey">func MarshalAuthorizedKey</h3> + <pre class="chroma"><span class="kd">func</span> <span class="nf">MarshalAuthorizedKey</span><span class="p">(</span><span class="nx">key</span> <a href="#PublicKey"><span class="nx">PublicKey</span></a><span class="p">)</span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#byte"><span class="kt">byte</span></a></pre> + <p>MarshalAuthorizedKey serializes key for inclusion in an OpenSSH +authorized_keys file. The return value ends with newline. +<h3 id="MarshalPrivateKey">func MarshalPrivateKey</h3> + <pre class="chroma"><span class="kd">func</span> <span class="nf">MarshalPrivateKey</span><span class="p">(</span><span class="nx">key</span> <a href="https://pkg.go.dev/crypto"><span class="nx">crypto</span></a><span class="p">.</span><a href="https://pkg.go.dev/crypto#PrivateKey"><span class="nx">PrivateKey</span></a><span class="p">,</span> <span class="nx">comment</span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a><span class="p">)</span> <span class="p">(</span><span class="o">*</span><a href="https://pkg.go.dev/encoding/pem"><span class="nx">pem</span></a><span class="p">.</span><a href="https://pkg.go.dev/encoding/pem#Block"><span class="nx">Block</span></a><span class="p">,</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a><span class="p">)</span></pre> + <p>MarshalPrivateKey returns a PEM block with the private key serialized in the +OpenSSH format. +<h3 id="MarshalPrivateKeyWithPassphrase">func MarshalPrivateKeyWithPassphrase</h3> + <pre class="chroma"><span class="kd">func</span> <span class="nf">MarshalPrivateKeyWithPassphrase</span><span class="p">(</span><span class="nx">key</span> <a href="https://pkg.go.dev/crypto"><span class="nx">crypto</span></a><span class="p">.</span><a href="https://pkg.go.dev/crypto#PrivateKey"><span class="nx">PrivateKey</span></a><span class="p">,</span> <span class="nx">comment</span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a><span class="p">,</span> <span class="nx">passphrase</span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#byte"><span class="kt">byte</span></a><span class="p">)</span> <span class="p">(</span><span class="o">*</span><a href="https://pkg.go.dev/encoding/pem"><span class="nx">pem</span></a><span class="p">.</span><a href="https://pkg.go.dev/encoding/pem#Block"><span class="nx">Block</span></a><span class="p">,</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a><span class="p">)</span></pre> + <p>MarshalPrivateKeyWithPassphrase returns a PEM block holding the encrypted +private key serialized in the OpenSSH format. +<h3 id="ParseRawPrivateKey">func ParseRawPrivateKey</h3> + <pre class="chroma"><span class="kd">func</span> <span class="nf">ParseRawPrivateKey</span><span class="p">(</span><span class="nx">pemBytes</span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#byte"><span class="kt">byte</span></a><span class="p">)</span> <span class="p">(</span><a href="https://pkg.go.dev/crypto"><span class="nx">crypto</span></a><span class="p">.</span><a href="https://pkg.go.dev/crypto#Signer"><span class="nx">Signer</span></a><span class="p">,</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a><span class="p">)</span></pre> + <p>ParseRawPrivateKey returns a private key from a PEM encoded private key. It supports +RSA, 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. +<h3 id="ParseRawPrivateKeyWithPassphrase">func ParseRawPrivateKeyWithPassphrase</h3> + <pre class="chroma"><span class="kd">func</span> <span class="nf">ParseRawPrivateKeyWithPassphrase</span><span class="p">(</span><span class="nx">pemBytes</span><span class="p">,</span> <span class="nx">passphrase</span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#byte"><span class="kt">byte</span></a><span class="p">)</span> <span class="p">(</span><a href="https://pkg.go.dev/crypto"><span class="nx">crypto</span></a><span class="p">.</span><a href="https://pkg.go.dev/crypto#Signer"><span class="nx">Signer</span></a><span class="p">,</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a><span class="p">)</span></pre> + <p>ParseRawPrivateKeyWithPassphrase returns a private key decrypted with +passphrase from a PEM encoded private key. If the passphrase is wrong, it +will return x509.IncorrectPasswordError. +<h3 id="Unmarshal">func Unmarshal</h3> + <pre class="chroma"><span class="kd">func</span> <span class="nf">Unmarshal</span><span class="p">(</span><span class="nx">data</span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#byte"><span class="kt">byte</span></a><span class="p">,</span> <span class="nx">out</span> <span class="kd">interface</span><span class="p">{})</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a></pre> + <p>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. +<h3 id="pkg-types">Types</h3> + <h3 id="Algorithms">type Algorithms</h3> + <pre class="chroma"><span class="kd">type</span> <span class="nx">Algorithms</span> <span class="kd">struct</span> <span class="p">{</span> + <span id="Algorithms.KeyExchanges"><span class="nx">KeyExchanges</span></span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a> + <span id="Algorithms.Ciphers"><span class="nx">Ciphers</span></span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a> + <span id="Algorithms.MACs"><span class="nx">MACs</span></span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a> + <span id="Algorithms.HostKeys"><span class="nx">HostKeys</span></span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a> + <span id="Algorithms.PublicKeyAuths"><span class="nx">PublicKeyAuths</span></span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a> +<span class="p">}</span></pre> + <p>Algorithms defines a set of algorithms that can be configured in the client +or server config for negotiation during a handshake. +<h4 id="InsecureAlgorithms">func InsecureAlgorithms</h4> + <pre class="chroma"><span class="kd">func</span> <span class="nf">InsecureAlgorithms</span><span class="p">()</span> <a href="#Algorithms"><span class="nx">Algorithms</span></a></pre> + <p>InsecureAlgorithms returns algorithms currently implemented by this package +and which have security issues. +<h4 id="SupportedAlgorithms">func SupportedAlgorithms</h4> + <pre class="chroma"><span class="kd">func</span> <span class="nf">SupportedAlgorithms</span><span class="p">()</span> <a href="#Algorithms"><span class="nx">Algorithms</span></a></pre> + <p>SupportedAlgorithms returns algorithms currently implemented by this package, +excluding those with security issues, which are returned by +InsecureAlgorithms. The algorithms listed here are in preference order. +<h3 id="AuthMethod">type AuthMethod</h3> + <pre class="chroma"><span class="kd">type</span> <span class="nx">AuthMethod</span> <span class="kd">interface</span> <span class="p">{</span> + <span class="c1">// contains filtered or unexported methods +</span><span class="c1"></span><span class="p">}</span></pre> + <p>An AuthMethod represents an instance of an RFC 4252 authentication method. +<h4 id="GSSAPIWithMICAuthMethod">func GSSAPIWithMICAuthMethod</h4> + <pre class="chroma"><span class="kd">func</span> <span class="nf">GSSAPIWithMICAuthMethod</span><span class="p">(</span><span class="nx">gssAPIClient</span> <a href="#GSSAPIClient"><span class="nx">GSSAPIClient</span></a><span class="p">,</span> <span class="nx">target</span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a><span class="p">)</span> <a href="#AuthMethod"><span class="nx">AuthMethod</span></a></pre> + <p>GSSAPIWithMICAuthMethod is an AuthMethod with "gssapi-with-mic" authentication. +See RFC 4462 section 3 +gssAPIClient 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. +<h4 id="KeyboardInteractive">func KeyboardInteractive</h4> + <pre class="chroma"><span class="kd">func</span> <span class="nf">KeyboardInteractive</span><span class="p">(</span><span class="nx">challenge</span> <a href="#KeyboardInteractiveChallenge"><span class="nx">KeyboardInteractiveChallenge</span></a><span class="p">)</span> <a href="#AuthMethod"><span class="nx">AuthMethod</span></a></pre> + <p>KeyboardInteractive returns an AuthMethod using a prompt/response +sequence controlled by the server. +<h4 id="Password">func Password</h4> + <pre class="chroma"><span class="kd">func</span> <span class="nf">Password</span><span class="p">(</span><span class="nx">secret</span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a><span class="p">)</span> <a href="#AuthMethod"><span class="nx">AuthMethod</span></a></pre> + <p>Password returns an AuthMethod using the given password. +<h4 id="PasswordCallback">func PasswordCallback</h4> + <pre class="chroma"><span class="kd">func</span> <span class="nf">PasswordCallback</span><span class="p">(</span><span class="nx">prompt</span> <span class="kd">func</span><span class="p">()</span> <span class="p">(</span><span class="nx">secret</span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a><span class="p">,</span> <span class="nx">err</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a><span class="p">))</span> <a href="#AuthMethod"><span class="nx">AuthMethod</span></a></pre> + <p>PasswordCallback returns an AuthMethod that uses a callback for +fetching a password. +<h4 id="PublicKeys">func PublicKeys</h4> + <pre class="chroma"><span class="kd">func</span> <span class="nf">PublicKeys</span><span class="p">(</span><span class="nx">signers</span> <span class="o">...</span><a href="#Signer"><span class="nx">Signer</span></a><span class="p">)</span> <a href="#AuthMethod"><span class="nx">AuthMethod</span></a></pre> + <p>PublicKeys returns an AuthMethod that uses the given key +pairs. +<details id="example-PublicKeys" class="example"> + <summary>Example</summary> + <pre class="chroma"><span class="kn">package</span> <span class="nx">main</span> + +<span class="kn">import</span> <span class="p">(</span> + <span class="s">"context"</span> + <span class="s">"log"</span> + <span class="s">"os"</span> + + <span class="s">"golang.org/x/crypto/ssh"</span> +<span class="p">)</span> + +<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span> + <span class="kd">var</span> <span class="nx">hostKey</span> <span class="nx">ssh</span><span class="p">.</span><span class="nx">PublicKey</span> + <span class="c1">// A public key may be used to authenticate against the remote +</span><span class="c1"></span> <span class="c1">// server by using an unencrypted PEM-encoded private key file. +</span><span class="c1"></span> <span class="c1">// +</span><span class="c1"></span> <span class="c1">// If you have an encrypted private key, the crypto/x509 package +</span><span class="c1"></span> <span class="c1">// can be used to decrypt it. +</span><span class="c1"></span> <span class="nx">key</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">os</span><span class="p">.</span><span class="nf">ReadFile</span><span class="p">(</span><span class="s">"/home/user/.ssh/id_rsa"</span><span class="p">)</span> + <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span> + <span class="nx">log</span><span class="p">.</span><span class="nf">Fatalf</span><span class="p">(</span><span class="s">"unable to read private key: %v"</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span> + <span class="p">}</span> + + <span class="c1">// Create the Signer for this private key. +</span><span class="c1"></span> <span class="nx">signer</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">ssh</span><span class="p">.</span><span class="nf">ParsePrivateKey</span><span class="p">(</span><span class="nx">key</span><span class="p">)</span> + <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span> + <span class="nx">log</span><span class="p">.</span><span class="nf">Fatalf</span><span class="p">(</span><span class="s">"unable to parse private key: %v"</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span> + <span class="p">}</span> + + <span class="nx">config</span> <span class="o">:=</span> <span class="o">&</span><span class="nx">ssh</span><span class="p">.</span><span class="nx">ClientConfig</span><span class="p">{</span> + <span class="nx">User</span><span class="p">:</span> <span class="s">"user"</span><span class="p">,</span> + <span class="nx">Auth</span><span class="p">:</span> <span class="p">[]</span><span class="nx">ssh</span><span class="p">.</span><span class="nx">AuthMethod</span><span class="p">{</span> + <span class="c1">// Use the PublicKeys method for remote authentication. +</span><span class="c1"></span> <span class="nx">ssh</span><span class="p">.</span><span class="nf">PublicKeys</span><span class="p">(</span><span class="nx">signer</span><span class="p">),</span> + <span class="p">},</span> + <span class="nx">HostKey</span><span class="p">:</span> <span class="nx">ssh</span><span class="p">.</span><span class="nf">FixedHostKey</span><span class="p">(</span><span class="nx">hostKey</span><span class="p">),</span> + <span class="p">}</span> + + <span class="c1">// Connect to the remote server and perform the SSH handshake. +</span><span class="c1"></span> <span class="nx">client</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">ssh</span><span class="p">.</span><span class="nf">Dial</span><span class="p">(</span><span class="nx">context</span><span class="p">.</span><span class="nf">Background</span><span class="p">(),</span> <span class="s">"tcp"</span><span class="p">,</span> <span class="s">"host.com:22"</span><span class="p">,</span> <span class="nx">config</span><span class="p">)</span> + <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span> + <span class="nx">log</span><span class="p">.</span><span class="nf">Fatalf</span><span class="p">(</span><span class="s">"unable to connect: %v"</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span> + <span class="p">}</span> + <span class="k">defer</span> <span class="nx">client</span><span class="p">.</span><span class="nf">Close</span><span class="p">()</span> +<span class="p">}</span></pre> + </details> + <h4 id="PublicKeysCallback">func PublicKeysCallback</h4> + <pre class="chroma"><span class="kd">func</span> <span class="nf">PublicKeysCallback</span><span class="p">(</span><span class="nx">getSigners</span> <span class="kd">func</span><span class="p">()</span> <span class="p">(</span><span class="nx">signers</span> <span class="p">[]</span><a href="#Signer"><span class="nx">Signer</span></a><span class="p">,</span> <span class="nx">err</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a><span class="p">))</span> <a href="#AuthMethod"><span class="nx">AuthMethod</span></a></pre> + <p>PublicKeysCallback returns an AuthMethod that runs the given +function to obtain a list of key pairs. +<h4 id="RetryableAuthMethod">func RetryableAuthMethod</h4> + <pre class="chroma"><span class="kd">func</span> <span class="nf">RetryableAuthMethod</span><span class="p">(</span><span class="nx">auth</span> <a href="#AuthMethod"><span class="nx">AuthMethod</span></a><span class="p">,</span> <span class="nx">maxTries</span> <a href="https://pkg.go.dev/builtin#int"><span class="kt">int</span></a><span class="p">)</span> <a href="#AuthMethod"><span class="nx">AuthMethod</span></a></pre> + <p>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 +<p>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). +<details id="example-RetryableAuthMethod" class="example"> + <summary>Example</summary> + <pre class="chroma"><span class="nx">user</span> <span class="o">:=</span> <span class="s">"testuser"</span> +<span class="nx">NumberOfPrompts</span> <span class="o">:=</span> <span class="mi">3</span> + +<span class="c1">// Normally this would be a callback that prompts the user to answer the +</span><span class="c1">// provided questions +</span><span class="c1"></span><span class="nx">Cb</span> <span class="o">:=</span> <span class="kd">func</span><span class="p">(</span><span class="nx">user</span><span class="p">,</span> <span class="nx">instruction</span> <span class="kt">string</span><span class="p">,</span> <span class="nx">questions</span> <span class="p">[]</span><span class="kt">string</span><span class="p">,</span> <span class="nx">echos</span> <span class="p">[]</span><span class="kt">bool</span><span class="p">)</span> <span class="p">(</span><span class="nx">answers</span> <span class="p">[]</span><span class="kt">string</span><span class="p">,</span> <span class="nx">err</span> <span class="kt">error</span><span class="p">)</span> <span class="p">{</span> + <span class="k">return</span> <span class="p">[]</span><span class="kt">string</span><span class="p">{</span><span class="s">"answer1"</span><span class="p">,</span> <span class="s">"answer2"</span><span class="p">},</span> <span class="kc">nil</span> +<span class="p">}</span> + +<span class="nx">config</span> <span class="o">:=</span> <span class="o">&</span><span class="nx">ClientConfig</span><span class="p">{</span> + <span class="nx">HostKey</span><span class="p">:</span> <span class="nf">InsecureIgnoreHostKey</span><span class="p">(),</span> + <span class="nx">User</span><span class="p">:</span> <span class="nx">user</span><span class="p">,</span> + <span class="nx">Auth</span><span class="p">:</span> <span class="p">[]</span><span class="nx">AuthMethod</span><span class="p">{</span> + <span class="nf">RetryableAuthMethod</span><span class="p">(</span><span class="nf">KeyboardInteractiveChallenge</span><span class="p">(</span><span class="nx">Cb</span><span class="p">),</span> <span class="nx">NumberOfPrompts</span><span class="p">),</span> + <span class="p">},</span> +<span class="p">}</span> + +<span class="nx">host</span> <span class="o">:=</span> <span class="s">"mysshserver"</span> +<span class="nx">netConn</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">net</span><span class="p">.</span><span class="nf">Dial</span><span class="p">(</span><span class="s">"tcp"</span><span class="p">,</span> <span class="nx">host</span><span class="p">)</span> +<span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span> + <span class="nx">log</span><span class="p">.</span><span class="nf">Fatal</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span> +<span class="p">}</span> + +<span class="nx">sshConn</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nf">NewClientConn</span><span class="p">(</span><span class="nx">netConn</span><span class="p">,</span> <span class="nx">host</span><span class="p">,</span> <span class="nx">config</span><span class="p">)</span> +<span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span> + <span class="nx">log</span><span class="p">.</span><span class="nf">Fatal</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span> +<span class="p">}</span> +<span class="nx">_</span> <span class="p">=</span> <span class="nx">sshConn</span></pre> + </details> + <h3 id="BannerCallback">type BannerCallback</h3> + <pre class="chroma"><span class="kd">type</span> <span class="nx">BannerCallback</span> <span class="kd">func</span><span class="p">(</span><span class="nx">message</span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a><span class="p">)</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a></pre> + <p>BannerCallback is the function type used for treat the banner sent by +the server. A BannerCallback receives the message sent by the remote server. +<h4 id="BannerDisplayStderr">func BannerDisplayStderr</h4> + <pre class="chroma"><span class="kd">func</span> <span class="nf">BannerDisplayStderr</span><span class="p">()</span> <a href="#BannerCallback"><span class="nx">BannerCallback</span></a></pre> + <p>BannerDisplayStderr returns a function that can be used for +ClientConfig.BannerCallback to display banners on os.Stderr. +<h3 id="BannerError">type BannerError</h3> + <pre class="chroma"><span class="kd">type</span> <span class="nx">BannerError</span> <span class="kd">struct</span> <span class="p">{</span> + <span id="BannerError.Err"><span class="nx">Err</span></span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a> + <span id="BannerError.Message"><span class="nx">Message</span></span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a> +<span class="p">}</span></pre> + <p>BannerError is an error that can be returned by authentication handlers in +Server to send a banner message to the client. +<h4 id="BannerError.Error">func (*BannerError) Error</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">b</span> <span class="o">*</span><a href="#BannerError"><span class="nx">BannerError</span></a><span class="p">)</span> <span class="nf">Error</span><span class="p">()</span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a></pre> + <h4 id="BannerError.Unwrap">func (*BannerError) Unwrap</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">b</span> <span class="o">*</span><a href="#BannerError"><span class="nx">BannerError</span></a><span class="p">)</span> <span class="nf">Unwrap</span><span class="p">()</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a></pre> + <h3 id="CertChecker">type CertChecker</h3> + <pre class="chroma"><span class="kd">type</span> <span class="nx">CertChecker</span> <span class="kd">struct</span> <span class="p">{</span> + <span class="c1">// SupportedCriticalOptions lists the CriticalOptions that the +</span><span class="c1"></span> <span class="c1">// server application layer understands. These are only used +</span><span class="c1"></span> <span class="c1">// for user certificates. +</span><span class="c1"></span> <span id="CertChecker.SupportedCriticalOptions"><span class="nx">SupportedCriticalOptions</span></span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a> + + <span class="c1">// IsUserAuthority should return true if the key is recognized as an +</span><span class="c1"></span> <span class="c1">// authority for the given user certificate. This allows for +</span><span class="c1"></span> <span class="c1">// certificates to be signed by other certificates. This must be set +</span><span class="c1"></span> <span class="c1">// if this CertChecker will be checking user certificates. +</span><span class="c1"></span> <span id="CertChecker.IsUserAuthority"><span class="nx">IsUserAuthority</span></span> <span class="kd">func</span><span class="p">(</span><span class="nx">auth</span> <a href="#PublicKey"><span class="nx">PublicKey</span></a><span class="p">)</span> <a href="https://pkg.go.dev/builtin#bool"><span class="kt">bool</span></a> + + <span class="c1">// IsHostAuthority should report whether the key is recognized as +</span><span class="c1"></span> <span class="c1">// an authority for this host. This allows for certificates to be +</span><span class="c1"></span> <span class="c1">// signed by other keys, and for those other keys to only be valid +</span><span class="c1"></span> <span class="c1">// signers for particular hostnames. This must be set if this +</span><span class="c1"></span> <span class="c1">// CertChecker will be checking host certificates. +</span><span class="c1"></span> <span id="CertChecker.IsHostAuthority"><span class="nx">IsHostAuthority</span></span> <span class="kd">func</span><span class="p">(</span><span class="nx">auth</span> <a href="#PublicKey"><span class="nx">PublicKey</span></a><span class="p">,</span> <span class="nx">address</span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a><span class="p">)</span> <a href="https://pkg.go.dev/builtin#bool"><span class="kt">bool</span></a> + + <span class="c1">// Clock is used for verifying time stamps. If nil, time.Now +</span><span class="c1"></span> <span class="c1">// is used. +</span><span class="c1"></span> <span id="CertChecker.Clock"><span class="nx">Clock</span></span> <span class="kd">func</span><span class="p">()</span> <a href="https://pkg.go.dev/time"><span class="nx">time</span></a><span class="p">.</span><a href="https://pkg.go.dev/time#Time"><span class="nx">Time</span></a> + + <span class="c1">// UserKeyFallback is called when CertChecker.Authenticate encounters a +</span><span class="c1"></span> <span class="c1">// public key that is not a certificate. It must implement validation +</span><span class="c1"></span> <span class="c1">// of user keys or else, if nil, all such keys are rejected. +</span><span class="c1"></span> <span id="CertChecker.UserKeyFallback"><span class="nx">UserKeyFallback</span></span> <span class="kd">func</span><span class="p">(</span><span class="nx">conn</span> <a href="#ConnMetadata"><span class="nx">ConnMetadata</span></a><span class="p">,</span> <span class="nx">key</span> <a href="#PublicKey"><span class="nx">PublicKey</span></a><span class="p">)</span> <span class="p">(</span><span class="o">*</span><a href="#Permissions"><span class="nx">Permissions</span></a><span class="p">,</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a><span class="p">)</span> + + <span class="c1">// HostKeyFallback is called when CertChecker.CheckHostKey encounters a +</span><span class="c1"></span> <span class="c1">// public key that is not a certificate. It must implement host key +</span><span class="c1"></span> <span class="c1">// validation or else, if nil, all such keys are rejected. +</span><span class="c1"></span> <span id="CertChecker.HostKeyFallback"><span class="nx">HostKeyFallback</span></span> <a href="#HostKeyCallback"><span class="nx">HostKeyCallback</span></a> + + <span class="c1">// IsRevoked is called for each certificate so that revocation checking +</span><span class="c1"></span> <span class="c1">// can be implemented. It should return true if the given certificate +</span><span class="c1"></span> <span class="c1">// is revoked and false otherwise. If nil, no certificates are +</span><span class="c1"></span> <span class="c1">// considered to have been revoked. +</span><span class="c1"></span> <span id="CertChecker.IsRevoked"><span class="nx">IsRevoked</span></span> <span class="kd">func</span><span class="p">(</span><span class="nx">cert</span> <span class="o">*</span><a href="#Certificate"><span class="nx">Certificate</span></a><span class="p">)</span> <a href="https://pkg.go.dev/builtin#bool"><span class="kt">bool</span></a> +<span class="p">}</span></pre> + <p>CertChecker does the work of verifying a certificate. Its methods +can be plugged into ClientConfig.HostKeyCallback and +Server.PublicKeyCallback. For the CertChecker to work, +minimally, the IsAuthority callback should be set. +<h4 id="CertChecker.Authenticate">func (*CertChecker) Authenticate</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">c</span> <span class="o">*</span><a href="#CertChecker"><span class="nx">CertChecker</span></a><span class="p">)</span> <span class="nf">Authenticate</span><span class="p">(</span><span class="nx">conn</span> <a href="#ConnMetadata"><span class="nx">ConnMetadata</span></a><span class="p">,</span> <span class="nx">pubKey</span> <a href="#PublicKey"><span class="nx">PublicKey</span></a><span class="p">)</span> <span class="p">(</span><span class="o">*</span><a href="#Permissions"><span class="nx">Permissions</span></a><span class="p">,</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a><span class="p">)</span></pre> + <p>Authenticate checks a user certificate. Authenticate can be used as +a value for Server.PublicKeyCallback. +<h4 id="CertChecker.CheckCert">func (*CertChecker) CheckCert</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">c</span> <span class="o">*</span><a href="#CertChecker"><span class="nx">CertChecker</span></a><span class="p">)</span> <span class="nf">CheckCert</span><span class="p">(</span><span class="nx">principal</span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a><span class="p">,</span> <span class="nx">cert</span> <span class="o">*</span><a href="#Certificate"><span class="nx">Certificate</span></a><span class="p">)</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a></pre> + <p>CheckCert checks CriticalOptions, ValidPrincipals, revocation, timestamp and +the signature of the certificate. +<h4 id="CertChecker.CheckHostKey">func (*CertChecker) CheckHostKey</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">c</span> <span class="o">*</span><a href="#CertChecker"><span class="nx">CertChecker</span></a><span class="p">)</span> <span class="nf">CheckHostKey</span><span class="p">(</span><span class="nx">addr</span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a><span class="p">,</span> <span class="nx">remote</span> <a href="https://pkg.go.dev/net"><span class="nx">net</span></a><span class="p">.</span><a href="https://pkg.go.dev/net#Addr"><span class="nx">Addr</span></a><span class="p">,</span> <span class="nx">key</span> <a href="#PublicKey"><span class="nx">PublicKey</span></a><span class="p">)</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a></pre> + <p>CheckHostKey checks a host key certificate. This method can be +plugged into ClientConfig.HostKeyCallback. +<h3 id="Certificate">type Certificate</h3> + <pre class="chroma"><span class="kd">type</span> <span class="nx">Certificate</span> <span class="kd">struct</span> <span class="p">{</span> + <span id="Certificate.Nonce"><span class="nx">Nonce</span></span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#byte"><span class="kt">byte</span></a> + <span id="Certificate.Key"><span class="nx">Key</span></span> <a href="#PublicKey"><span class="nx">PublicKey</span></a> + <span id="Certificate.Serial"><span class="nx">Serial</span></span> <a href="https://pkg.go.dev/builtin#uint64"><span class="kt">uint64</span></a> + <span id="Certificate.CertType"><span class="nx">CertType</span></span> <a href="https://pkg.go.dev/builtin#uint32"><span class="kt">uint32</span></a> + <span id="Certificate.KeyId"><span class="nx">KeyId</span></span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a> + <span id="Certificate.ValidPrincipals"><span class="nx">ValidPrincipals</span></span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a> + <span id="Certificate.ValidAfter"><span class="nx">ValidAfter</span></span> <a href="https://pkg.go.dev/builtin#uint64"><span class="kt">uint64</span></a> + <span id="Certificate.ValidBefore"><span class="nx">ValidBefore</span></span> <a href="https://pkg.go.dev/builtin#uint64"><span class="kt">uint64</span></a> + <a href="#Permissions"><span class="nx">Permissions</span></a> + <span id="Certificate.Reserved"><span class="nx">Reserved</span></span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#byte"><span class="kt">byte</span></a> + <span id="Certificate.SignatureKey"><span class="nx">SignatureKey</span></span> <a href="#PublicKey"><span class="nx">PublicKey</span></a> + <span id="Certificate.Signature"><span class="nx">Signature</span></span> <span class="o">*</span><a href="#Signature"><span class="nx">Signature</span></a> +<span class="p">}</span></pre> + <p>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. +<h4 id="Certificate.Marshal">func (*Certificate) Marshal</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">c</span> <span class="o">*</span><a href="#Certificate"><span class="nx">Certificate</span></a><span class="p">)</span> <span class="nf">Marshal</span><span class="p">()</span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#byte"><span class="kt">byte</span></a></pre> + <p>Marshal serializes c into OpenSSH's wire format. It is part of the +PublicKey interface. +<h4 id="Certificate.SignCert">func (*Certificate) SignCert</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">c</span> <span class="o">*</span><a href="#Certificate"><span class="nx">Certificate</span></a><span class="p">)</span> <span class="nf">SignCert</span><span class="p">(</span><span class="nx">rand</span> <a href="https://pkg.go.dev/io"><span class="nx">io</span></a><span class="p">.</span><a href="https://pkg.go.dev/io#Reader"><span class="nx">Reader</span></a><span class="p">,</span> <span class="nx">authority</span> <a href="#Signer"><span class="nx">Signer</span></a><span class="p">)</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a></pre> + <p>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. +<details id="example-Certificate.SignCert" class="example"> + <summary>Example</summary> + <pre class="chroma"><span class="kn">package</span> <span class="nx">main</span> + +<span class="kn">import</span> <span class="p">(</span> + <span class="s">"crypto/rand"</span> + <span class="s">"crypto/rsa"</span> + <span class="s">"fmt"</span> + <span class="s">"log"</span> + + <span class="s">"golang.org/x/crypto/ssh"</span> +<span class="p">)</span> + +<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span> + <span class="c1">// Sign a certificate with a specific algorithm. +</span><span class="c1"></span> <span class="nx">privateKey</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">rsa</span><span class="p">.</span><span class="nf">GenerateKey</span><span class="p">(</span><span class="nx">rand</span><span class="p">.</span><span class="nx">Reader</span><span class="p">,</span> <span class="mi">3072</span><span class="p">)</span> + <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span> + <span class="nx">log</span><span class="p">.</span><span class="nf">Fatal</span><span class="p">(</span><span class="s">"unable to generate RSA key: "</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span> + <span class="p">}</span> + <span class="nx">publicKey</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">ssh</span><span class="p">.</span><span class="nf">NewPublicKey</span><span class="p">(</span><span class="o">&</span><span class="nx">privateKey</span><span class="p">.</span><span class="nx">PublicKey</span><span class="p">)</span> + <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span> + <span class="nx">log</span><span class="p">.</span><span class="nf">Fatal</span><span class="p">(</span><span class="s">"unable to get RSA public key: "</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span> + <span class="p">}</span> + <span class="nx">caKey</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">rsa</span><span class="p">.</span><span class="nf">GenerateKey</span><span class="p">(</span><span class="nx">rand</span><span class="p">.</span><span class="nx">Reader</span><span class="p">,</span> <span class="mi">3072</span><span class="p">)</span> + <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span> + <span class="nx">log</span><span class="p">.</span><span class="nf">Fatal</span><span class="p">(</span><span class="s">"unable to generate CA key: "</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span> + <span class="p">}</span> + <span class="nx">signer</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">ssh</span><span class="p">.</span><span class="nf">NewSigner</span><span class="p">(</span><span class="nx">caKey</span><span class="p">)</span> + <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span> + <span class="nx">log</span><span class="p">.</span><span class="nf">Fatal</span><span class="p">(</span><span class="s">"unable to generate signer from key: "</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span> + <span class="p">}</span> + <span class="nx">mas</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">ssh</span><span class="p">.</span><span class="nf">NewSignerWithAlgorithms</span><span class="p">(</span><span class="nx">signer</span><span class="p">,</span> <span class="p">[]</span><span class="kt">string</span><span class="p">{</span><span class="nx">ssh</span><span class="p">.</span><span class="nx">KeyAlgoRSASHA256</span><span class="p">})</span> + <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span> + <span class="nx">log</span><span class="p">.</span><span class="nf">Fatal</span><span class="p">(</span><span class="s">"unable to create signer with algorithms: "</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span> + <span class="p">}</span> + <span class="nx">certificate</span> <span class="o">:=</span> <span class="nx">ssh</span><span class="p">.</span><span class="nx">Certificate</span><span class="p">{</span> + <span class="nx">Key</span><span class="p">:</span> <span class="nx">publicKey</span><span class="p">,</span> + <span class="nx">CertType</span><span class="p">:</span> <span class="nx">ssh</span><span class="p">.</span><span class="nx">UserCert</span><span class="p">,</span> + <span class="p">}</span> + <span class="k">if</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">certificate</span><span class="p">.</span><span class="nf">SignCert</span><span class="p">(</span><span class="nx">rand</span><span class="p">.</span><span class="nx">Reader</span><span class="p">,</span> <span class="nx">mas</span><span class="p">);</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span> + <span class="nx">log</span><span class="p">.</span><span class="nf">Fatal</span><span class="p">(</span><span class="s">"unable to sign certificate: "</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span> + <span class="p">}</span> + <span class="c1">// Save the public key to a file and check that rsa-sha-256 is used for +</span><span class="c1"></span> <span class="c1">// signing: +</span><span class="c1"></span> <span class="c1">// ssh-keygen -L -f <path to the file> +</span><span class="c1"></span> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nb">string</span><span class="p">(</span><span class="nx">ssh</span><span class="p">.</span><span class="nf">MarshalAuthorizedKey</span><span class="p">(</span><span class="o">&</span><span class="nx">certificate</span><span class="p">)))</span> +<span class="p">}</span></pre> + </details> + <h4 id="Certificate.Type">func (*Certificate) Type</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">c</span> <span class="o">*</span><a href="#Certificate"><span class="nx">Certificate</span></a><span class="p">)</span> <span class="nf">Type</span><span class="p">()</span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a></pre> + <p>Type returns the certificate algorithm name. It is part of the PublicKey interface. +<h4 id="Certificate.Verify">func (*Certificate) Verify</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">c</span> <span class="o">*</span><a href="#Certificate"><span class="nx">Certificate</span></a><span class="p">)</span> <span class="nf">Verify</span><span class="p">(</span><span class="nx">data</span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#byte"><span class="kt">byte</span></a><span class="p">,</span> <span class="nx">sig</span> <span class="o">*</span><a href="#Signature"><span class="nx">Signature</span></a><span class="p">)</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a></pre> + <p>Verify verifies a signature against the certificate's public +key. It is part of the PublicKey interface. +<h3 id="Channel">type Channel</h3> + <pre class="chroma"><span class="kd">type</span> <span class="nx">Channel</span> <span class="kd">struct</span> <span class="p">{</span> + <span class="c1">// contains filtered or unexported fields +</span><span class="c1"></span><span class="p">}</span></pre> + <p>A Channel is an ordered, reliable, flow-controlled, duplex stream +that is multiplexed over an SSH connection. +<h4 id="Channel.Close">func (*Channel) Close</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">c</span> <span class="o">*</span><a href="#Channel"><span class="nx">Channel</span></a><span class="p">)</span> <span class="nf">Close</span><span class="p">()</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a></pre> + <p>Close signals end of channel use. No data may be sent after this call. +<h4 id="Channel.CloseWrite">func (*Channel) CloseWrite</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">c</span> <span class="o">*</span><a href="#Channel"><span class="nx">Channel</span></a><span class="p">)</span> <span class="nf">CloseWrite</span><span class="p">()</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a></pre> + <p>CloseWrite signals the end of sending in-band data. Requests may still be +sent, and the other side may still send data. +<h4 id="Channel.Handle">func (*Channel) Handle</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">c</span> <span class="o">*</span><a href="#Channel"><span class="nx">Channel</span></a><span class="p">)</span> <span class="nf">Handle</span><span class="p">(</span><span class="nx">handler</span> <a href="#RequestHandler"><span class="nx">RequestHandler</span></a><span class="p">)</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a></pre> + <p>Handle must be called to handle channel's requests. Handle blocks. If +requestHandler is nil, requests will be discarded. +<h4 id="Channel.Read">func (*Channel) Read</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">c</span> <span class="o">*</span><a href="#Channel"><span class="nx">Channel</span></a><span class="p">)</span> <span class="nf">Read</span><span class="p">(</span><span class="nx">data</span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#byte"><span class="kt">byte</span></a><span class="p">)</span> <span class="p">(</span><a href="https://pkg.go.dev/builtin#int"><span class="kt">int</span></a><span class="p">,</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a><span class="p">)</span></pre> + <p>Read reads up to len(data) bytes from the channel. +<h4 id="Channel.SendRequest">func (*Channel) SendRequest</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">c</span> <span class="o">*</span><a href="#Channel"><span class="nx">Channel</span></a><span class="p">)</span> <span class="nf">SendRequest</span><span class="p">(</span><span class="nx">name</span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a><span class="p">,</span> <span class="nx">wantReply</span> <a href="https://pkg.go.dev/builtin#bool"><span class="kt">bool</span></a><span class="p">,</span> <span class="nx">payload</span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#byte"><span class="kt">byte</span></a><span class="p">)</span> <span class="p">(</span><a href="https://pkg.go.dev/builtin#bool"><span class="kt">bool</span></a><span class="p">,</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a><span class="p">)</span></pre> + <p>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. +<h4 id="Channel.SetDeadline">func (*Channel) SetDeadline</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">c</span> <span class="o">*</span><a href="#Channel"><span class="nx">Channel</span></a><span class="p">)</span> <span class="nf">SetDeadline</span><span class="p">(</span><span class="nx">deadline</span> <a href="https://pkg.go.dev/time"><span class="nx">time</span></a><span class="p">.</span><a href="https://pkg.go.dev/time#Time"><span class="nx">Time</span></a><span class="p">)</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a></pre> + <p>SetDeadline sets the read and write deadlines associated with the +channel. It is equivalent to calling both SetReadDeadline and +SetWriteDeadline. Deadlines errors are not fatal, the Channel can be used +again after resetting the deadlines. +<h4 id="Channel.SetReadDeadline">func (*Channel) SetReadDeadline</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">c</span> <span class="o">*</span><a href="#Channel"><span class="nx">Channel</span></a><span class="p">)</span> <span class="nf">SetReadDeadline</span><span class="p">(</span><span class="nx">deadline</span> <a href="https://pkg.go.dev/time"><span class="nx">time</span></a><span class="p">.</span><a href="https://pkg.go.dev/time#Time"><span class="nx">Time</span></a><span class="p">)</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a></pre> + <p>SetReadDeadline sets the deadline for future Read calls and unblock Read +calls waiting for data. A zero value for t means Read will not time out. +<h4 id="Channel.SetWriteDeadline">func (*Channel) SetWriteDeadline</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">c</span> <span class="o">*</span><a href="#Channel"><span class="nx">Channel</span></a><span class="p">)</span> <span class="nf">SetWriteDeadline</span><span class="p">(</span><span class="nx">deadline</span> <a href="https://pkg.go.dev/time"><span class="nx">time</span></a><span class="p">.</span><a href="https://pkg.go.dev/time#Time"><span class="nx">Time</span></a><span class="p">)</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a></pre> + <p>SetWriteDeadline sets the deadline for future Write calls and unblock +Write calls waiting for window capacity. A zero value for t means Write +will not time out. +<h4 id="Channel.Stderr">func (*Channel) Stderr</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">c</span> <span class="o">*</span><a href="#Channel"><span class="nx">Channel</span></a><span class="p">)</span> <span class="nf">Stderr</span><span class="p">()</span> <a href="https://pkg.go.dev/io"><span class="nx">io</span></a><span class="p">.</span><a href="https://pkg.go.dev/io#ReadWriter"><span class="nx">ReadWriter</span></a></pre> + <p>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. +<h4 id="Channel.Write">func (*Channel) Write</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">c</span> <span class="o">*</span><a href="#Channel"><span class="nx">Channel</span></a><span class="p">)</span> <span class="nf">Write</span><span class="p">(</span><span class="nx">data</span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#byte"><span class="kt">byte</span></a><span class="p">)</span> <span class="p">(</span><a href="https://pkg.go.dev/builtin#int"><span class="kt">int</span></a><span class="p">,</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a><span class="p">)</span></pre> + <p>Write writes len(data) bytes to the channel. +<h3 id="ChannelHandler">type ChannelHandler</h3> + <pre class="chroma"><span class="kd">type</span> <span class="nx">ChannelHandler</span> <span class="kd">interface</span> <span class="p">{</span> + <span id="ChannelHandler.NewChannel"><span class="nf">NewChannel</span></span><span class="p">(</span><span class="nx">ch</span> <span class="o">*</span><a href="#NewChannel"><span class="nx">NewChannel</span></a><span class="p">)</span> +<span class="p">}</span></pre> + <p>ChannelHandler defines the interface to handle new channel requests. +<h3 id="ChannelHandlerFunc">type ChannelHandlerFunc</h3> + <pre class="chroma"><span class="kd">type</span> <span class="nx">ChannelHandlerFunc</span> <span class="kd">func</span><span class="p">(</span><span class="nx">ch</span> <span class="o">*</span><a href="#NewChannel"><span class="nx">NewChannel</span></a><span class="p">)</span></pre> + <p>ChannelHandlerFunc is an adapter to allow the use of ordinary function as +<a href="#ChannelHandler">ChannelHandler</a>. If f is a function with the appropriate signature, +ChannelHandlerFunc(f) is a <a href="#ChannelHandler">ChannelHandler</a> that calls f. +<h4 id="ChannelHandlerFunc.NewChannel">func (ChannelHandlerFunc) NewChannel</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">f</span> <a href="#ChannelHandlerFunc"><span class="nx">ChannelHandlerFunc</span></a><span class="p">)</span> <span class="nf">NewChannel</span><span class="p">(</span><span class="nx">ch</span> <span class="o">*</span><a href="#NewChannel"><span class="nx">NewChannel</span></a><span class="p">)</span></pre> + <p>NewChannel calls f(ch). +<h3 id="Client">type Client</h3> + <pre class="chroma"><span class="kd">type</span> <span class="nx">Client</span> <span class="kd">struct</span> <span class="p">{</span> + <span class="c1">// contains filtered or unexported fields +</span><span class="c1"></span><span class="p">}</span></pre> + <p>Client implements a traditional SSH client that supports shells, +subprocesses, TCP port/streamlocal forwarding and tunneled dialing. +<h4 id="Dial">func Dial</h4> + <pre class="chroma"><span class="kd">func</span> <span class="nf">Dial</span><span class="p">(</span><span class="nx">ctx</span> <a href="https://pkg.go.dev/context"><span class="nx">context</span></a><span class="p">.</span><a href="https://pkg.go.dev/context#Context"><span class="nx">Context</span></a><span class="p">,</span> <span class="nx">network</span><span class="p">,</span> <span class="nx">addr</span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a><span class="p">,</span> <span class="nx">config</span> <span class="o">*</span><a href="#ClientConfig"><span class="nx">ClientConfig</span></a><span class="p">)</span> <span class="p">(</span><span class="o">*</span><a href="#Client"><span class="nx">Client</span></a><span class="p">,</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a><span class="p">)</span></pre> + <p>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. +<details id="example-Dial" class="example"> + <summary>Example</summary> + <pre class="chroma"><span class="kn">package</span> <span class="nx">main</span> + +<span class="kn">import</span> <span class="p">(</span> + <span class="s">"bytes"</span> + <span class="s">"context"</span> + <span class="s">"fmt"</span> + <span class="s">"log"</span> + <span class="s">"time"</span> + + <span class="s">"golang.org/x/crypto/ssh"</span> +<span class="p">)</span> + +<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span> + <span class="kd">var</span> <span class="nx">hostKey</span> <span class="nx">ssh</span><span class="p">.</span><span class="nx">PublicKey</span> + <span class="c1">// An SSH client is represented with a ClientConn. +</span><span class="c1"></span> <span class="c1">// +</span><span class="c1"></span> <span class="c1">// To authenticate with the remote server you must pass at least one +</span><span class="c1"></span> <span class="c1">// implementation of AuthMethod via the Auth field in ClientConfig, +</span><span class="c1"></span> <span class="c1">// and provide a HostKeyCallback. +</span><span class="c1"></span> <span class="nx">config</span> <span class="o">:=</span> <span class="o">&</span><span class="nx">ssh</span><span class="p">.</span><span class="nx">ClientConfig</span><span class="p">{</span> + <span class="nx">User</span><span class="p">:</span> <span class="s">"username"</span><span class="p">,</span> + <span class="nx">Auth</span><span class="p">:</span> <span class="p">[]</span><span class="nx">ssh</span><span class="p">.</span><span class="nx">AuthMethod</span><span class="p">{</span> + <span class="nx">ssh</span><span class="p">.</span><span class="nf">Password</span><span class="p">(</span><span class="s">"yourpassword"</span><span class="p">),</span> + <span class="p">},</span> + <span class="nx">HostKey</span><span class="p">:</span> <span class="nx">ssh</span><span class="p">.</span><span class="nf">FixedHostKey</span><span class="p">(</span><span class="nx">hostKey</span><span class="p">),</span> + <span class="p">}</span> + <span class="c1">// Allow at most 10 seconds to complete the handshake and create the Client. +</span><span class="c1"></span> <span class="nx">ctx</span><span class="p">,</span> <span class="nx">cancel</span> <span class="o">:=</span> <span class="nx">context</span><span class="p">.</span><span class="nf">WithTimeout</span><span class="p">(</span><span class="nx">context</span><span class="p">.</span><span class="nf">Background</span><span class="p">(),</span> <span class="mi">10</span><span class="o">*</span><span class="nx">time</span><span class="p">.</span><span class="nx">Second</span><span class="p">)</span> + <span class="k">defer</span> <span class="nf">cancel</span><span class="p">()</span> + + <span class="nx">client</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">ssh</span><span class="p">.</span><span class="nf">Dial</span><span class="p">(</span><span class="nx">ctx</span><span class="p">,</span> <span class="s">"tcp"</span><span class="p">,</span> <span class="s">"yourserver.com:22"</span><span class="p">,</span> <span class="nx">config</span><span class="p">)</span> + <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span> + <span class="nx">log</span><span class="p">.</span><span class="nf">Fatal</span><span class="p">(</span><span class="s">"Failed to dial: "</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span> + <span class="p">}</span> + <span class="k">defer</span> <span class="nx">client</span><span class="p">.</span><span class="nf">Close</span><span class="p">()</span> + + <span class="c1">// Each ClientConn can support multiple interactive sessions, +</span><span class="c1"></span> <span class="c1">// represented by a Session. +</span><span class="c1"></span> <span class="nx">session</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">client</span><span class="p">.</span><span class="nf">NewSession</span><span class="p">()</span> + <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span> + <span class="nx">log</span><span class="p">.</span><span class="nf">Fatal</span><span class="p">(</span><span class="s">"Failed to create session: "</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span> + <span class="p">}</span> + <span class="k">defer</span> <span class="nx">session</span><span class="p">.</span><span class="nf">Close</span><span class="p">()</span> + + <span class="c1">// Once a Session is created, you can execute a single command on +</span><span class="c1"></span> <span class="c1">// the remote side using the Run method. +</span><span class="c1"></span> <span class="kd">var</span> <span class="nx">b</span> <span class="nx">bytes</span><span class="p">.</span><span class="nx">Buffer</span> + <span class="nx">session</span><span class="p">.</span><span class="nx">Stdout</span> <span class="p">=</span> <span class="o">&</span><span class="nx">b</span> + <span class="k">if</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">session</span><span class="p">.</span><span class="nf">Run</span><span class="p">(</span><span class="s">"/usr/bin/whoami"</span><span class="p">);</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span> + <span class="nx">log</span><span class="p">.</span><span class="nf">Fatal</span><span class="p">(</span><span class="s">"Failed to run: "</span> <span class="o">+</span> <span class="nx">err</span><span class="p">.</span><span class="nf">Error</span><span class="p">())</span> + <span class="p">}</span> + <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nx">b</span><span class="p">.</span><span class="nf">String</span><span class="p">())</span> +<span class="p">}</span></pre> + </details> + <h4 id="NewClient">func NewClient</h4> + <pre class="chroma"><span class="kd">func</span> <span class="nf">NewClient</span><span class="p">(</span><span class="nx">c</span> <span class="o">*</span><a href="#ClientConn"><span class="nx">ClientConn</span></a><span class="p">)</span> <span class="o">*</span><a href="#Client"><span class="nx">Client</span></a></pre> + <p>NewClient creates a Client on top of the given connection. +<h4 id="Client.Close">func (Client) Close</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">c</span> <span class="nx">Client</span><span class="p">)</span> <span class="nf">Close</span><span class="p">()</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a></pre> + <h4 id="Client.Dial">func (*Client) Dial</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">c</span> <span class="o">*</span><a href="#Client"><span class="nx">Client</span></a><span class="p">)</span> <span class="nf">Dial</span><span class="p">(</span><span class="nx">ctx</span> <a href="https://pkg.go.dev/context"><span class="nx">context</span></a><span class="p">.</span><a href="https://pkg.go.dev/context#Context"><span class="nx">Context</span></a><span class="p">,</span> <span class="nx">n</span><span class="p">,</span> <span class="nx">addr</span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a><span class="p">)</span> <span class="p">(</span><a href="https://pkg.go.dev/net"><span class="nx">net</span></a><span class="p">.</span><a href="https://pkg.go.dev/net#Conn"><span class="nx">Conn</span></a><span class="p">,</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a><span class="p">)</span></pre> + <p>Dial initiates a connection to the addr from the remote host. +The resulting connection has a zero LocalAddr() and RemoteAddr(). +<h4 id="Client.DialTCP">func (*Client) DialTCP</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">c</span> <span class="o">*</span><a href="#Client"><span class="nx">Client</span></a><span class="p">)</span> <span class="nf">DialTCP</span><span class="p">(</span><span class="nx">ctx</span> <a href="https://pkg.go.dev/context"><span class="nx">context</span></a><span class="p">.</span><a href="https://pkg.go.dev/context#Context"><span class="nx">Context</span></a><span class="p">,</span> <span class="nx">n</span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a><span class="p">,</span> <span class="nx">laddr</span><span class="p">,</span> <span class="nx">raddr</span> <span class="o">*</span><a href="https://pkg.go.dev/net"><span class="nx">net</span></a><span class="p">.</span><a href="https://pkg.go.dev/net#TCPAddr"><span class="nx">TCPAddr</span></a><span class="p">)</span> <span class="p">(</span><a href="https://pkg.go.dev/net"><span class="nx">net</span></a><span class="p">.</span><a href="https://pkg.go.dev/net#Conn"><span class="nx">Conn</span></a><span class="p">,</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a><span class="p">)</span></pre> + <p>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. +<h4 id="Client.HandleChannelOpen">func (*Client) HandleChannelOpen</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">c</span> <span class="o">*</span><a href="#Client"><span class="nx">Client</span></a><span class="p">)</span> <span class="nf">HandleChannelOpen</span><span class="p">(</span><span class="nx">channelType</span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a><span class="p">,</span> <span class="nx">handler</span> <a href="#ChannelHandler"><span class="nx">ChannelHandler</span></a><span class="p">)</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a></pre> + <p>HandleChannelOpen allows to define a <a href="#ChannelHandler">ChannelHandler</a> for the specified +channel type. An error is returned if an handler for the specified type is +already registered. +<h4 id="Client.Listen">func (*Client) Listen</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">c</span> <span class="o">*</span><a href="#Client"><span class="nx">Client</span></a><span class="p">)</span> <span class="nf">Listen</span><span class="p">(</span><span class="nx">n</span><span class="p">,</span> <span class="nx">addr</span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a><span class="p">)</span> <span class="p">(</span><a href="https://pkg.go.dev/net"><span class="nx">net</span></a><span class="p">.</span><a href="https://pkg.go.dev/net#Listener"><span class="nx">Listener</span></a><span class="p">,</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a><span class="p">)</span></pre> + <p>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". +<details id="example-Client.Listen" class="example"> + <summary>Example</summary> + <pre class="chroma"><span class="kn">package</span> <span class="nx">main</span> + +<span class="kn">import</span> <span class="p">(</span> + <span class="s">"context"</span> + <span class="s">"fmt"</span> + <span class="s">"log"</span> + <span class="s">"net/http"</span> + + <span class="s">"golang.org/x/crypto/ssh"</span> +<span class="p">)</span> + +<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span> + <span class="kd">var</span> <span class="nx">hostKey</span> <span class="nx">ssh</span><span class="p">.</span><span class="nx">PublicKey</span> + <span class="nx">config</span> <span class="o">:=</span> <span class="o">&</span><span class="nx">ssh</span><span class="p">.</span><span class="nx">ClientConfig</span><span class="p">{</span> + <span class="nx">User</span><span class="p">:</span> <span class="s">"username"</span><span class="p">,</span> + <span class="nx">Auth</span><span class="p">:</span> <span class="p">[]</span><span class="nx">ssh</span><span class="p">.</span><span class="nx">AuthMethod</span><span class="p">{</span> + <span class="nx">ssh</span><span class="p">.</span><span class="nf">Password</span><span class="p">(</span><span class="s">"password"</span><span class="p">),</span> + <span class="p">},</span> + <span class="nx">HostKey</span><span class="p">:</span> <span class="nx">ssh</span><span class="p">.</span><span class="nf">FixedHostKey</span><span class="p">(</span><span class="nx">hostKey</span><span class="p">),</span> + <span class="p">}</span> + <span class="c1">// Dial your ssh server. +</span><span class="c1"></span> <span class="nx">conn</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">ssh</span><span class="p">.</span><span class="nf">Dial</span><span class="p">(</span><span class="nx">context</span><span class="p">.</span><span class="nf">Background</span><span class="p">(),</span> <span class="s">"tcp"</span><span class="p">,</span> <span class="s">"localhost:22"</span><span class="p">,</span> <span class="nx">config</span><span class="p">)</span> + <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span> + <span class="nx">log</span><span class="p">.</span><span class="nf">Fatal</span><span class="p">(</span><span class="s">"unable to connect: "</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span> + <span class="p">}</span> + <span class="k">defer</span> <span class="nx">conn</span><span class="p">.</span><span class="nf">Close</span><span class="p">()</span> + + <span class="c1">// Request the remote side to open port 8080 on all interfaces. +</span><span class="c1"></span> <span class="nx">l</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">conn</span><span class="p">.</span><span class="nf">Listen</span><span class="p">(</span><span class="s">"tcp"</span><span class="p">,</span> <span class="s">"0.0.0.0:8080"</span><span class="p">)</span> + <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span> + <span class="nx">log</span><span class="p">.</span><span class="nf">Fatal</span><span class="p">(</span><span class="s">"unable to register tcp forward: "</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span> + <span class="p">}</span> + <span class="k">defer</span> <span class="nx">l</span><span class="p">.</span><span class="nf">Close</span><span class="p">()</span> + + <span class="c1">// Serve HTTP with your SSH server acting as a reverse proxy. +</span><span class="c1"></span> <span class="nx">http</span><span class="p">.</span><span class="nf">Serve</span><span class="p">(</span><span class="nx">l</span><span class="p">,</span> <span class="nx">http</span><span class="p">.</span><span class="nf">HandlerFunc</span><span class="p">(</span><span class="kd">func</span><span class="p">(</span><span class="nx">resp</span> <span class="nx">http</span><span class="p">.</span><span class="nx">ResponseWriter</span><span class="p">,</span> <span class="nx">req</span> <span class="o">*</span><span class="nx">http</span><span class="p">.</span><span class="nx">Request</span><span class="p">)</span> <span class="p">{</span> + <span class="nx">fmt</span><span class="p">.</span><span class="nf">Fprintf</span><span class="p">(</span><span class="nx">resp</span><span class="p">,</span> <span class="s">"Hello world!\n"</span><span class="p">)</span> + <span class="p">}))</span> +<span class="p">}</span></pre> + </details> + <h4 id="Client.ListenUnix">func (*Client) ListenUnix</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">c</span> <span class="o">*</span><a href="#Client"><span class="nx">Client</span></a><span class="p">)</span> <span class="nf">ListenUnix</span><span class="p">(</span><span class="nx">socketPath</span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a><span class="p">)</span> <span class="p">(</span><a href="https://pkg.go.dev/net"><span class="nx">net</span></a><span class="p">.</span><a href="https://pkg.go.dev/net#Listener"><span class="nx">Listener</span></a><span class="p">,</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a><span class="p">)</span></pre> + <p>ListenUnix is similar to ListenTCP but uses a Unix domain socket. +<h4 id="Client.NewSession">func (*Client) NewSession</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">c</span> <span class="o">*</span><a href="#Client"><span class="nx">Client</span></a><span class="p">)</span> <span class="nf">NewSession</span><span class="p">()</span> <span class="p">(</span><span class="o">*</span><a href="#Session"><span class="nx">Session</span></a><span class="p">,</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a><span class="p">)</span></pre> + <p>NewSession opens a new Session for this client. (A session is a remote +execution of a program.) +<h3 id="ClientConfig">type ClientConfig</h3> + <pre class="chroma"><span class="kd">type</span> <span class="nx">ClientConfig</span> <span class="kd">struct</span> <span class="p">{</span> + <span class="c1">// Config contains configuration that is shared between clients and +</span><span class="c1"></span> <span class="c1">// servers. +</span><span class="c1"></span> <a href="#Config"><span class="nx">Config</span></a> + + <span class="c1">// User contains the username to authenticate as. +</span><span class="c1"></span> <span id="ClientConfig.User"><span class="nx">User</span></span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a> + + <span class="c1">// Auth contains possible authentication methods to use with the +</span><span class="c1"></span> <span class="c1">// server. Only the first instance of a particular RFC 4252 method will +</span><span class="c1"></span> <span class="c1">// be used during authentication. +</span><span class="c1"></span> <span id="ClientConfig.Auth"><span class="nx">Auth</span></span> <span class="p">[]</span><a href="#AuthMethod"><span class="nx">AuthMethod</span></a> + + <span class="c1">// HostKey is called during the cryptographic +</span><span class="c1"></span> <span class="c1">// handshake to validate the server's host key. The client +</span><span class="c1"></span> <span class="c1">// configuration must supply this callback for the connection +</span><span class="c1"></span> <span class="c1">// to succeed. The functions InsecureIgnoreHostKey or +</span><span class="c1"></span> <span class="c1">// FixedHostKey can be used for simplistic host key checks. +</span><span class="c1"></span> <span id="ClientConfig.HostKey"><span class="nx">HostKey</span></span> <a href="#HostKeyCallback"><span class="nx">HostKeyCallback</span></a> + + <span class="c1">// Banner is called during the SSH dance to display a custom +</span><span class="c1"></span> <span class="c1">// server's message. The client configuration can supply this callback to +</span><span class="c1"></span> <span class="c1">// handle it as wished. The function BannerDisplayStderr can be used for +</span><span class="c1"></span> <span class="c1">// simplistic display on Stderr. +</span><span class="c1"></span> <span id="ClientConfig.Banner"><span class="nx">Banner</span></span> <a href="#BannerCallback"><span class="nx">BannerCallback</span></a> + + <span class="c1">// ClientVersion contains the version identification string that will +</span><span class="c1"></span> <span class="c1">// be used for the connection. If empty, a reasonable default is used. +</span><span class="c1"></span> <span id="ClientConfig.ClientVersion"><span class="nx">ClientVersion</span></span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a> + + <span class="c1">// HostKeyAlgorithms lists the public key algorithms that the client will +</span><span class="c1"></span> <span class="c1">// accept from the server for host key authentication, in order of +</span><span class="c1"></span> <span class="c1">// preference. If empty, a reasonable default is used. Any +</span><span class="c1"></span> <span class="c1">// string returned from a PublicKey.Type method may be used, or +</span><span class="c1"></span> <span class="c1">// any of the CertAlgo and KeyAlgo constants. +</span><span class="c1"></span> <span id="ClientConfig.HostKeyAlgorithms"><span class="nx">HostKeyAlgorithms</span></span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a> +<span class="p">}</span></pre> + <p>A ClientConfig structure is used to configure a Client. It must not be +modified after having been passed to an SSH function. +<h3 id="ClientConn">type ClientConn</h3> + <pre class="chroma"><span class="kd">type</span> <span class="nx">ClientConn</span> <span class="kd">struct</span> <span class="p">{</span> + <span class="c1">// contains filtered or unexported fields +</span><span class="c1"></span><span class="p">}</span></pre> + <p>ClientConn is an authenticated SSH connection, as seen from the +client +<h4 id="NewClientConn">func NewClientConn</h4> + <pre class="chroma"><span class="kd">func</span> <span class="nf">NewClientConn</span><span class="p">(</span><span class="nx">c</span> <a href="https://pkg.go.dev/net"><span class="nx">net</span></a><span class="p">.</span><a href="https://pkg.go.dev/net#Conn"><span class="nx">Conn</span></a><span class="p">,</span> <span class="nx">addr</span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a><span class="p">,</span> <span class="nx">config</span> <span class="o">*</span><a href="#ClientConfig"><span class="nx">ClientConfig</span></a><span class="p">)</span> <span class="p">(</span><span class="o">*</span><a href="#ClientConn"><span class="nx">ClientConn</span></a><span class="p">,</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a><span class="p">)</span></pre> + <p>NewClientConn establishes an authenticated SSH connection using c as the +underlying transport. You can use <a href="#NewClient">NewClient</a> to build an SSH client or +handle this client connection yourself by using <a href="#ClientConn.Handle">ClientConn.Handle</a>. +<h4 id="ClientConn.Close">func (ClientConn) Close</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">c</span> <span class="nx">ClientConn</span><span class="p">)</span> <span class="nf">Close</span><span class="p">()</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a></pre> + <h4 id="ClientConn.Handle">func (*ClientConn) Handle</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">c</span> <span class="o">*</span><a href="#ClientConn"><span class="nx">ClientConn</span></a><span class="p">)</span> <span class="nf">Handle</span><span class="p">(</span><span class="nx">channelHandler</span> <a href="#ChannelHandler"><span class="nx">ChannelHandler</span></a><span class="p">,</span> <span class="nx">requestHandler</span> <a href="#RequestHandler"><span class="nx">RequestHandler</span></a><span class="p">)</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a></pre> + <p>Handle must be called to handle requests and channels if you want to handle a +<a href="#ClientConn">ClientConn</a> yourself without building a <a href="#Client">Client</a> using <a href="#NewClient">NewClient</a>. Handle +blocks. If channelHandler is nil channels will be rejected. If requestHandler +is nil, requests will be discarded. +<h3 id="ClientHandler">type ClientHandler</h3> + <pre class="chroma"><span class="kd">type</span> <span class="nx">ClientHandler</span> <span class="kd">interface</span> <span class="p">{</span> + <span class="c1">// HandleClient is called after the handshake completes and a client +</span><span class="c1"></span> <span class="c1">// authenticates with the server. +</span><span class="c1"></span> <span id="ClientHandler.HandleClient"><span class="nf">HandleClient</span></span><span class="p">(</span><span class="nx">conn</span> <span class="o">*</span><a href="#ServerConn"><span class="nx">ServerConn</span></a><span class="p">)</span> +<span class="p">}</span></pre> + <p>ClientHandler defines the interface to handle authenticated server +connections. +<h3 id="ClientHandlerFunc">type ClientHandlerFunc</h3> + <pre class="chroma"><span class="kd">type</span> <span class="nx">ClientHandlerFunc</span> <span class="kd">func</span><span class="p">(</span><span class="nx">conn</span> <span class="o">*</span><a href="#ServerConn"><span class="nx">ServerConn</span></a><span class="p">)</span></pre> + <p>ClientHandlerFunc is an adapter to allow the use of ordinary function as +<a href="#ClientHandler">ClientHandler</a>. If f is a function with the appropriate signature, +ClientHandlerFunc(f) is a <a href="#ClientHandler">ClientHandler</a> that calls f. +<h4 id="ClientHandlerFunc.HandleClient">func (ClientHandlerFunc) HandleClient</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">f</span> <a href="#ClientHandlerFunc"><span class="nx">ClientHandlerFunc</span></a><span class="p">)</span> <span class="nf">HandleClient</span><span class="p">(</span><span class="nx">conn</span> <span class="o">*</span><a href="#ServerConn"><span class="nx">ServerConn</span></a><span class="p">)</span></pre> + <p>HandleClient calls f(conn). +<h3 id="Config">type Config</h3> + <pre class="chroma"><span class="kd">type</span> <span class="nx">Config</span> <span class="kd">struct</span> <span class="p">{</span> + <span class="c1">// Rand provides the source of entropy for cryptographic +</span><span class="c1"></span> <span class="c1">// primitives. If Rand is nil, the cryptographic random reader +</span><span class="c1"></span> <span class="c1">// in package crypto/rand will be used. +</span><span class="c1"></span> <span id="Config.Rand"><span class="nx">Rand</span></span> <a href="https://pkg.go.dev/io"><span class="nx">io</span></a><span class="p">.</span><a href="https://pkg.go.dev/io#Reader"><span class="nx">Reader</span></a> + + <span class="c1">// The maximum number of bytes sent or received after which a +</span><span class="c1"></span> <span class="c1">// new key is negotiated. It must be at least 256. If +</span><span class="c1"></span> <span class="c1">// unspecified, a size suitable for the chosen cipher is used. +</span><span class="c1"></span> <span id="Config.RekeyThreshold"><span class="nx">RekeyThreshold</span></span> <a href="https://pkg.go.dev/builtin#uint64"><span class="kt">uint64</span></a> + + <span class="c1">// The allowed key exchanges algorithms. If unspecified then a default set +</span><span class="c1"></span> <span class="c1">// of algorithms is used. Unsupported values are silently ignored. +</span><span class="c1"></span> <span id="Config.KeyExchanges"><span class="nx">KeyExchanges</span></span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a> + + <span class="c1">// The allowed cipher algorithms. If unspecified then a sensible default is +</span><span class="c1"></span> <span class="c1">// used. Unsupported values are silently ignored. +</span><span class="c1"></span> <span id="Config.Ciphers"><span class="nx">Ciphers</span></span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a> + + <span class="c1">// The allowed MAC algorithms. If unspecified then a sensible default is +</span><span class="c1"></span> <span class="c1">// used. Unsupported values are silently ignored. +</span><span class="c1"></span> <span id="Config.MACs"><span class="nx">MACs</span></span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a> +<span class="p">}</span></pre> + <p>Config contains configuration data common to both Server and +ClientConfig. +<h4 id="Config.SetDefaults">func (*Config) SetDefaults</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">c</span> <span class="o">*</span><a href="#Config"><span class="nx">Config</span></a><span class="p">)</span> <span class="nf">SetDefaults</span><span class="p">()</span></pre> + <p>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. +<h3 id="ConnMetadata">type ConnMetadata</h3> + <pre class="chroma"><span class="kd">type</span> <span class="nx">ConnMetadata</span> <span class="kd">struct</span> <span class="p">{</span> + <span class="c1">// contains filtered or unexported fields +</span><span class="c1"></span><span class="p">}</span></pre> + <p>ConnMetadata holds metadata for the connection. +<h4 id="ConnMetadata.ClientVersion">func (ConnMetadata) ClientVersion</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">c</span> <span class="nx">ConnMetadata</span><span class="p">)</span> <span class="nf">ClientVersion</span><span class="p">()</span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#byte"><span class="kt">byte</span></a></pre> + <p>ClientVersion returns the client's version string as hashed into the session +ID. +<h4 id="ConnMetadata.LocalAddr">func (ConnMetadata) LocalAddr</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">c</span> <span class="nx">ConnMetadata</span><span class="p">)</span> <span class="nf">LocalAddr</span><span class="p">()</span> <a href="https://pkg.go.dev/net"><span class="nx">net</span></a><span class="p">.</span><a href="https://pkg.go.dev/net#Addr"><span class="nx">Addr</span></a></pre> + <p>LocalAddr returns the local address for this connection. +<h4 id="ConnMetadata.RemoteAddr">func (ConnMetadata) RemoteAddr</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">c</span> <span class="nx">ConnMetadata</span><span class="p">)</span> <span class="nf">RemoteAddr</span><span class="p">()</span> <a href="https://pkg.go.dev/net"><span class="nx">net</span></a><span class="p">.</span><a href="https://pkg.go.dev/net#Addr"><span class="nx">Addr</span></a></pre> + <p>RemoteAddr returns the remote address for this connection. +<h4 id="ConnMetadata.ServerVersion">func (ConnMetadata) ServerVersion</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">c</span> <span class="nx">ConnMetadata</span><span class="p">)</span> <span class="nf">ServerVersion</span><span class="p">()</span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#byte"><span class="kt">byte</span></a></pre> + <p>ServerVersion returns the server's version string as hashed into the session +ID. +<h4 id="ConnMetadata.SessionID">func (ConnMetadata) SessionID</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">c</span> <span class="nx">ConnMetadata</span><span class="p">)</span> <span class="nf">SessionID</span><span class="p">()</span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#byte"><span class="kt">byte</span></a></pre> + <p>SessionID returns the session hash, also denoted by H. +<h4 id="ConnMetadata.User">func (ConnMetadata) User</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">c</span> <span class="nx">ConnMetadata</span><span class="p">)</span> <span class="nf">User</span><span class="p">()</span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a></pre> + <p>User returns the user ID for this connection. +<h3 id="CryptoPublicKey">type CryptoPublicKey</h3> + <pre class="chroma"><span class="kd">type</span> <span class="nx">CryptoPublicKey</span> <span class="kd">interface</span> <span class="p">{</span> + <span id="CryptoPublicKey.CryptoPublicKey"><span class="nf">CryptoPublicKey</span></span><span class="p">()</span> <a href="https://pkg.go.dev/crypto"><span class="nx">crypto</span></a><span class="p">.</span><a href="https://pkg.go.dev/crypto#PublicKey"><span class="nx">PublicKey</span></a> +<span class="p">}</span></pre> + <p>CryptoPublicKey, if implemented by a PublicKey, +returns the underlying crypto.PublicKey form of the key. +<h3 id="ExitError">type ExitError</h3> + <pre class="chroma"><span class="kd">type</span> <span class="nx">ExitError</span> <span class="kd">struct</span> <span class="p">{</span> + <a href="#Waitmsg"><span class="nx">Waitmsg</span></a> +<span class="p">}</span></pre> + <p>An ExitError reports unsuccessful completion of a remote command. +<h4 id="ExitError.Error">func (*ExitError) Error</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">e</span> <span class="o">*</span><a href="#ExitError"><span class="nx">ExitError</span></a><span class="p">)</span> <span class="nf">Error</span><span class="p">()</span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a></pre> + <h3 id="ExitMissingError">type ExitMissingError</h3> + <pre class="chroma"><span class="kd">type</span> <span class="nx">ExitMissingError</span> <span class="kd">struct</span><span class="p">{}</span></pre> + <p>ExitMissingError is returned if a session is torn down cleanly, but +the server sends no confirmation of the exit status. +<h4 id="ExitMissingError.Error">func (*ExitMissingError) Error</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">e</span> <span class="o">*</span><a href="#ExitMissingError"><span class="nx">ExitMissingError</span></a><span class="p">)</span> <span class="nf">Error</span><span class="p">()</span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a></pre> + <h3 id="GSSAPIClient">type GSSAPIClient</h3> + <pre class="chroma"><span class="kd">type</span> <span class="nx">GSSAPIClient</span> <span class="kd">interface</span> <span class="p">{</span> + <span class="c1">// InitSecContext initiates the establishment of a security context for GSS-API between the +</span><span class="c1"></span> <span class="c1">// ssh client and ssh server. Initially the token parameter should be specified as nil. +</span><span class="c1"></span> <span class="c1">// The routine may return a outputToken which should be transferred to +</span><span class="c1"></span> <span class="c1">// the ssh server, where the ssh server will present it to +</span><span class="c1"></span> <span class="c1">// AcceptSecContext. If no token need be sent, InitSecContext will indicate this by setting +</span><span class="c1"></span> <span class="c1">// needContinue to false. To complete the context +</span><span class="c1"></span> <span class="c1">// establishment, one or more reply tokens may be required from the ssh +</span><span class="c1"></span> <span class="c1">// server;if so, InitSecContext will return a needContinue which is true. +</span><span class="c1"></span> <span class="c1">// In this case, InitSecContext should be called again when the +</span><span class="c1"></span> <span class="c1">// reply token is received from the ssh server, passing the reply +</span><span class="c1"></span> <span class="c1">// token to InitSecContext via the token parameters. +</span><span class="c1"></span> <span class="c1">// See RFC 2743 section 2.2.1 and RFC 4462 section 3.4. +</span><span class="c1"></span> <span id="GSSAPIClient.InitSecContext"><span class="nf">InitSecContext</span></span><span class="p">(</span><span class="nx">target</span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a><span class="p">,</span> <span class="nx">token</span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#byte"><span class="kt">byte</span></a><span class="p">,</span> <span class="nx">isGSSDelegCreds</span> <a href="https://pkg.go.dev/builtin#bool"><span class="kt">bool</span></a><span class="p">)</span> <span class="p">(</span><span class="nx">outputToken</span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#byte"><span class="kt">byte</span></a><span class="p">,</span> <span class="nx">needContinue</span> <a href="https://pkg.go.dev/builtin#bool"><span class="kt">bool</span></a><span class="p">,</span> <span class="nx">err</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a><span class="p">)</span> + <span class="c1">// GetMIC generates a cryptographic MIC for the SSH2 message, and places +</span><span class="c1"></span> <span class="c1">// the MIC in a token for transfer to the ssh server. +</span><span class="c1"></span> <span class="c1">// The contents of the MIC field are obtained by calling GSS_GetMIC() +</span><span class="c1"></span> <span class="c1">// over the following, using the GSS-API context that was just +</span><span class="c1"></span> <span class="c1">// established: +</span><span class="c1"></span> <span class="c1">// string session identifier +</span><span class="c1"></span> <span class="c1">// byte SSH_MSG_USERAUTH_REQUEST +</span><span class="c1"></span> <span class="c1">// string user name +</span><span class="c1"></span> <span class="c1">// string service +</span><span class="c1"></span> <span class="c1">// string "gssapi-with-mic" +</span><span class="c1"></span> <span class="c1">// See RFC 2743 section 2.3.1 and RFC 4462 3.5. +</span><span class="c1"></span> <span id="GSSAPIClient.GetMIC"><span class="nf">GetMIC</span></span><span class="p">(</span><span class="nx">micFiled</span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#byte"><span class="kt">byte</span></a><span class="p">)</span> <span class="p">([]</span><a href="https://pkg.go.dev/builtin#byte"><span class="kt">byte</span></a><span class="p">,</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a><span class="p">)</span> + <span class="c1">// Whenever possible, it should be possible for +</span><span class="c1"></span> <span class="c1">// DeleteSecContext() calls to be successfully processed even +</span><span class="c1"></span> <span class="c1">// if other calls cannot succeed, thereby enabling context-related +</span><span class="c1"></span> <span class="c1">// resources to be released. +</span><span class="c1"></span> <span class="c1">// In addition to deleting established security contexts, +</span><span class="c1"></span> <span class="c1">// gss_delete_sec_context must also be able to delete "half-built" +</span><span class="c1"></span> <span class="c1">// security contexts resulting from an incomplete sequence of +</span><span class="c1"></span> <span class="c1">// InitSecContext()/AcceptSecContext() calls. +</span><span class="c1"></span> <span class="c1">// See RFC 2743 section 2.2.3. +</span><span class="c1"></span> <span id="GSSAPIClient.DeleteSecContext"><span class="nf">DeleteSecContext</span></span><span class="p">()</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a> +<span class="p">}</span></pre> + <p>GSSAPIClient provides the API to plug-in GSSAPI authentication for client logins. +<h3 id="GSSAPIServer">type GSSAPIServer</h3> + <pre class="chroma"><span class="kd">type</span> <span class="nx">GSSAPIServer</span> <span class="kd">interface</span> <span class="p">{</span> + <span class="c1">// AcceptSecContext allows a remotely initiated security context between the application +</span><span class="c1"></span> <span class="c1">// and a remote peer to be established by the ssh client. The routine may return a +</span><span class="c1"></span> <span class="c1">// outputToken which should be transferred to the ssh client, +</span><span class="c1"></span> <span class="c1">// where the ssh client will present it to InitSecContext. +</span><span class="c1"></span> <span class="c1">// If no token need be sent, AcceptSecContext will indicate this +</span><span class="c1"></span> <span class="c1">// by setting the needContinue to false. To +</span><span class="c1"></span> <span class="c1">// complete the context establishment, one or more reply tokens may be +</span><span class="c1"></span> <span class="c1">// required from the ssh client. if so, AcceptSecContext +</span><span class="c1"></span> <span class="c1">// will return a needContinue which is true, in which case it +</span><span class="c1"></span> <span class="c1">// should be called again when the reply token is received from the ssh +</span><span class="c1"></span> <span class="c1">// client, passing the token to AcceptSecContext via the +</span><span class="c1"></span> <span class="c1">// token parameters. +</span><span class="c1"></span> <span class="c1">// The srcName return value is the authenticated username. +</span><span class="c1"></span> <span class="c1">// See RFC 2743 section 2.2.2 and RFC 4462 section 3.4. +</span><span class="c1"></span> <span id="GSSAPIServer.AcceptSecContext"><span class="nf">AcceptSecContext</span></span><span class="p">(</span><span class="nx">token</span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#byte"><span class="kt">byte</span></a><span class="p">)</span> <span class="p">(</span><span class="nx">outputToken</span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#byte"><span class="kt">byte</span></a><span class="p">,</span> <span class="nx">srcName</span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a><span class="p">,</span> <span class="nx">needContinue</span> <a href="https://pkg.go.dev/builtin#bool"><span class="kt">bool</span></a><span class="p">,</span> <span class="nx">err</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a><span class="p">)</span> + <span class="c1">// VerifyMIC verifies that a cryptographic MIC, contained in the token parameter, +</span><span class="c1"></span> <span class="c1">// fits the supplied message is received from the ssh client. +</span><span class="c1"></span> <span class="c1">// See RFC 2743 section 2.3.2. +</span><span class="c1"></span> <span id="GSSAPIServer.VerifyMIC"><span class="nf">VerifyMIC</span></span><span class="p">(</span><span class="nx">micField</span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#byte"><span class="kt">byte</span></a><span class="p">,</span> <span class="nx">micToken</span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#byte"><span class="kt">byte</span></a><span class="p">)</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a> + <span class="c1">// Whenever possible, it should be possible for +</span><span class="c1"></span> <span class="c1">// DeleteSecContext() calls to be successfully processed even +</span><span class="c1"></span> <span class="c1">// if other calls cannot succeed, thereby enabling context-related +</span><span class="c1"></span> <span class="c1">// resources to be released. +</span><span class="c1"></span> <span class="c1">// In addition to deleting established security contexts, +</span><span class="c1"></span> <span class="c1">// gss_delete_sec_context must also be able to delete "half-built" +</span><span class="c1"></span> <span class="c1">// security contexts resulting from an incomplete sequence of +</span><span class="c1"></span> <span class="c1">// InitSecContext()/AcceptSecContext() calls. +</span><span class="c1"></span> <span class="c1">// See RFC 2743 section 2.2.3. +</span><span class="c1"></span> <span id="GSSAPIServer.DeleteSecContext"><span class="nf">DeleteSecContext</span></span><span class="p">()</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a> +<span class="p">}</span></pre> + <p>GSSAPIServer provides the API to plug in GSSAPI authentication for server logins. +<h3 id="GSSAPIWithMICConfig">type GSSAPIWithMICConfig</h3> + <pre class="chroma"><span class="kd">type</span> <span class="nx">GSSAPIWithMICConfig</span> <span class="kd">struct</span> <span class="p">{</span> + <span class="c1">// AllowLogin, must be set, is called when gssapi-with-mic +</span><span class="c1"></span> <span class="c1">// authentication is selected (RFC 4462 section 3). The srcName is from the +</span><span class="c1"></span> <span class="c1">// results of the GSS-API authentication. The format is username@DOMAIN. +</span><span class="c1"></span> <span class="c1">// GSSAPI just guarantees to the server who the user is, but not if they can log in, and with what permissions. +</span><span class="c1"></span> <span class="c1">// This callback is called after the user identity is established with GSSAPI to decide if the user can login with +</span><span class="c1"></span> <span class="c1">// which permissions. If the user is allowed to login, it should return a nil error. +</span><span class="c1"></span> <span id="GSSAPIWithMICConfig.AllowLogin"><span class="nx">AllowLogin</span></span> <span class="kd">func</span><span class="p">(</span><span class="nx">conn</span> <a href="#ConnMetadata"><span class="nx">ConnMetadata</span></a><span class="p">,</span> <span class="nx">srcName</span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a><span class="p">)</span> <span class="p">(</span><span class="o">*</span><a href="#Permissions"><span class="nx">Permissions</span></a><span class="p">,</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a><span class="p">)</span> + + <span class="c1">// Server must be set. It's the implementation +</span><span class="c1"></span> <span class="c1">// of the GSSAPIServer interface. See GSSAPIServer interface for details. +</span><span class="c1"></span> <span id="GSSAPIWithMICConfig.Server"><span class="nx">Server</span></span> <a href="#GSSAPIServer"><span class="nx">GSSAPIServer</span></a> +<span class="p">}</span></pre> + <h3 id="HostKeyCallback">type HostKeyCallback</h3> + <pre class="chroma"><span class="kd">type</span> <span class="nx">HostKeyCallback</span> <span class="kd">func</span><span class="p">(</span><span class="nx">hostname</span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a><span class="p">,</span> <span class="nx">remote</span> <a href="https://pkg.go.dev/net"><span class="nx">net</span></a><span class="p">.</span><a href="https://pkg.go.dev/net#Addr"><span class="nx">Addr</span></a><span class="p">,</span> <span class="nx">key</span> <a href="#PublicKey"><span class="nx">PublicKey</span></a><span class="p">)</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a></pre> + <p>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. +<h4 id="FixedHostKey">func FixedHostKey</h4> + <pre class="chroma"><span class="kd">func</span> <span class="nf">FixedHostKey</span><span class="p">(</span><span class="nx">key</span> <a href="#PublicKey"><span class="nx">PublicKey</span></a><span class="p">)</span> <a href="#HostKeyCallback"><span class="nx">HostKeyCallback</span></a></pre> + <p>FixedHostKey returns a function for use in +ClientConfig.HostKeyCallback to accept only a specific host key. +<h4 id="InsecureIgnoreHostKey">func InsecureIgnoreHostKey</h4> + <pre class="chroma"><span class="kd">func</span> <span class="nf">InsecureIgnoreHostKey</span><span class="p">()</span> <a href="#HostKeyCallback"><span class="nx">HostKeyCallback</span></a></pre> + <p>InsecureIgnoreHostKey returns a function that can be used for +ClientConfig.HostKeyCallback to accept any host key. It should +not be used for production code. +<h3 id="KeyboardInteractiveChallenge">type KeyboardInteractiveChallenge</h3> + <pre class="chroma"><span class="kd">type</span> <span class="nx">KeyboardInteractiveChallenge</span> <span class="kd">func</span><span class="p">(</span><span class="nx">name</span><span class="p">,</span> <span class="nx">instruction</span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a><span class="p">,</span> <span class="nx">questions</span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a><span class="p">,</span> <span class="nx">echos</span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#bool"><span class="kt">bool</span></a><span class="p">)</span> <span class="p">(</span><span class="nx">answers</span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a><span class="p">,</span> <span class="nx">err</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a><span class="p">)</span></pre> + <p>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. +<h3 id="NewChannel">type NewChannel</h3> + <pre class="chroma"><span class="kd">type</span> <span class="nx">NewChannel</span> <span class="kd">struct</span> <span class="p">{</span> + <span class="c1">// contains filtered or unexported fields +</span><span class="c1"></span><span class="p">}</span></pre> + <p>NewChannel represents an incoming request to a channel. It must either be +accepted for use by calling Accept, or rejected by calling Reject. +<h4 id="NewChannel.Accept">func (*NewChannel) Accept</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">c</span> <span class="o">*</span><a href="#NewChannel"><span class="nx">NewChannel</span></a><span class="p">)</span> <span class="nf">Accept</span><span class="p">()</span> <span class="p">(</span><span class="o">*</span><a href="#Channel"><span class="nx">Channel</span></a><span class="p">,</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a><span class="p">)</span></pre> + <p>Accept accepts the channel creation request. The returned channel must be +serviced using <a href="#Channel.Handle">Channel.Handle</a>. +<h4 id="NewChannel.ChannelType">func (*NewChannel) ChannelType</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">c</span> <span class="o">*</span><a href="#NewChannel"><span class="nx">NewChannel</span></a><span class="p">)</span> <span class="nf">ChannelType</span><span class="p">()</span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a></pre> + <p>ChannelType returns the type of the channel, as supplied by the +client. +<h4 id="NewChannel.ExtraData">func (*NewChannel) ExtraData</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">c</span> <span class="o">*</span><a href="#NewChannel"><span class="nx">NewChannel</span></a><span class="p">)</span> <span class="nf">ExtraData</span><span class="p">()</span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#byte"><span class="kt">byte</span></a></pre> + <p>ExtraData returns the arbitrary payload for this channel, as supplied +by the client. This data is specific to the channel type. +<h4 id="NewChannel.Reject">func (*NewChannel) Reject</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">c</span> <span class="o">*</span><a href="#NewChannel"><span class="nx">NewChannel</span></a><span class="p">)</span> <span class="nf">Reject</span><span class="p">(</span><span class="nx">reason</span> <a href="#RejectionReason"><span class="nx">RejectionReason</span></a><span class="p">,</span> <span class="nx">message</span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a><span class="p">)</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a></pre> + <p>Reject rejects the channel creation request. After calling +this, no other methods on the Channel may be called. +<h3 id="OpenChannelError">type OpenChannelError</h3> + <pre class="chroma"><span class="kd">type</span> <span class="nx">OpenChannelError</span> <span class="kd">struct</span> <span class="p">{</span> + <span id="OpenChannelError.Reason"><span class="nx">Reason</span></span> <a href="#RejectionReason"><span class="nx">RejectionReason</span></a> + <span id="OpenChannelError.Message"><span class="nx">Message</span></span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a> +<span class="p">}</span></pre> + <p>OpenChannelError is returned if the other side rejects an +OpenChannel request. +<h4 id="OpenChannelError.Error">func (*OpenChannelError) Error</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">e</span> <span class="o">*</span><a href="#OpenChannelError"><span class="nx">OpenChannelError</span></a><span class="p">)</span> <span class="nf">Error</span><span class="p">()</span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a></pre> + <h3 id="PartialSuccessError">type PartialSuccessError</h3> + <pre class="chroma"><span class="kd">type</span> <span class="nx">PartialSuccessError</span> <span class="kd">struct</span> <span class="p">{</span> + <span class="c1">// Next defines the authentication callbacks to apply to further steps. The +</span><span class="c1"></span> <span class="c1">// available methods communicated to the client are based on the non-nil +</span><span class="c1"></span> <span class="c1">// ServerAuthCallbacks fields. +</span><span class="c1"></span> <span id="PartialSuccessError.Next"><span class="nx">Next</span></span> <a href="#ServerAuthCallbacks"><span class="nx">ServerAuthCallbacks</span></a> +<span class="p">}</span></pre> + <p>PartialSuccessError can be returned by any of the <a href="#Server">Server</a> +authentication callbacks to indicate to the client that authentication has +partially succeeded, but further steps are required. +<h4 id="PartialSuccessError.Error">func (*PartialSuccessError) Error</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">p</span> <span class="o">*</span><a href="#PartialSuccessError"><span class="nx">PartialSuccessError</span></a><span class="p">)</span> <span class="nf">Error</span><span class="p">()</span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a></pre> + <h3 id="PassphraseMissingError">type PassphraseMissingError</h3> + <pre class="chroma"><span class="kd">type</span> <span class="nx">PassphraseMissingError</span> <span class="kd">struct</span> <span class="p">{</span> + <span class="c1">// PublicKey will be set if the private key format includes an unencrypted +</span><span class="c1"></span> <span class="c1">// public key along with the encrypted private key. +</span><span class="c1"></span> <span id="PassphraseMissingError.PublicKey"><span class="nx">PublicKey</span></span> <a href="#PublicKey"><span class="nx">PublicKey</span></a> +<span class="p">}</span></pre> + <p>A PassphraseMissingError indicates that parsing this private key requires a +passphrase. Use ParsePrivateKeyWithPassphrase. +<h4 id="PassphraseMissingError.Error">func (*PassphraseMissingError) Error</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="o">*</span><a href="#PassphraseMissingError"><span class="nx">PassphraseMissingError</span></a><span class="p">)</span> <span class="nf">Error</span><span class="p">()</span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a></pre> + <h3 id="Permissions">type Permissions</h3> + <pre class="chroma"><span class="kd">type</span> <span class="nx">Permissions</span> <span class="kd">struct</span> <span class="p">{</span> + <span class="c1">// CriticalOptions indicate restrictions to the default +</span><span class="c1"></span> <span class="c1">// permissions, and are typically used in conjunction with +</span><span class="c1"></span> <span class="c1">// user certificates. The standard for SSH certificates +</span><span class="c1"></span> <span class="c1">// defines "force-command" (only allow the given command to +</span><span class="c1"></span> <span class="c1">// execute) and "source-address" (only allow connections from +</span><span class="c1"></span> <span class="c1">// the given address). The SSH package currently only enforces +</span><span class="c1"></span> <span class="c1">// the "source-address" critical option. It is up to server +</span><span class="c1"></span> <span class="c1">// implementations to enforce other critical options, such as +</span><span class="c1"></span> <span class="c1">// "force-command", by checking them after the SSH handshake +</span><span class="c1"></span> <span class="c1">// is successful. In general, SSH servers should reject +</span><span class="c1"></span> <span class="c1">// connections that specify critical options that are unknown +</span><span class="c1"></span> <span class="c1">// or not supported. +</span><span class="c1"></span> <span id="Permissions.CriticalOptions"><span class="nx">CriticalOptions</span></span> <span class="kd">map</span><span class="p">[</span><a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a><span class="p">]</span><a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a> + + <span class="c1">// Extensions are extra functionality that the server may +</span><span class="c1"></span> <span class="c1">// offer on authenticated connections. Lack of support for an +</span><span class="c1"></span> <span class="c1">// extension does not preclude authenticating a user. Common +</span><span class="c1"></span> <span class="c1">// extensions are "permit-agent-forwarding", +</span><span class="c1"></span> <span class="c1">// "permit-X11-forwarding". The Go SSH library currently does +</span><span class="c1"></span> <span class="c1">// not act on any extension, and it is up to server +</span><span class="c1"></span> <span class="c1">// implementations to honor them. Extensions can be used to +</span><span class="c1"></span> <span class="c1">// pass data from the authentication callbacks to the server +</span><span class="c1"></span> <span class="c1">// application layer. +</span><span class="c1"></span> <span id="Permissions.Extensions"><span class="nx">Extensions</span></span> <span class="kd">map</span><span class="p">[</span><a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a><span class="p">]</span><a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a> +<span class="p">}</span></pre> + <p>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. +<h3 id="PublicKey">type PublicKey</h3> + <pre class="chroma"><span class="kd">type</span> <span class="nx">PublicKey</span> <span class="kd">interface</span> <span class="p">{</span> + <span class="c1">// Type returns the key format name, e.g. "ssh-rsa". +</span><span class="c1"></span> <span id="PublicKey.Type"><span class="nf">Type</span></span><span class="p">()</span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a> + + <span class="c1">// Marshal returns the serialized key data in SSH wire format, with the name +</span><span class="c1"></span> <span class="c1">// prefix. To unmarshal the returned data, use the ParsePublicKey function. +</span><span class="c1"></span> <span id="PublicKey.Marshal"><span class="nf">Marshal</span></span><span class="p">()</span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#byte"><span class="kt">byte</span></a> + + <span class="c1">// Verify that sig is a signature on the given data using this key. This +</span><span class="c1"></span> <span class="c1">// method will hash the data appropriately first. sig.Format is allowed to +</span><span class="c1"></span> <span class="c1">// be any signature algorithm compatible with the key type, the caller +</span><span class="c1"></span> <span class="c1">// should check if it has more stringent requirements. +</span><span class="c1"></span> <span id="PublicKey.Verify"><span class="nf">Verify</span></span><span class="p">(</span><span class="nx">data</span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#byte"><span class="kt">byte</span></a><span class="p">,</span> <span class="nx">sig</span> <span class="o">*</span><a href="#Signature"><span class="nx">Signature</span></a><span class="p">)</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a> +<span class="p">}</span></pre> + <p>PublicKey represents a public key using an unspecified algorithm. +<p>Some PublicKeys provided by this package also implement CryptoPublicKey. +<h4 id="NewPublicKey">func NewPublicKey</h4> + <pre class="chroma"><span class="kd">func</span> <span class="nf">NewPublicKey</span><span class="p">(</span><span class="nx">key</span> <span class="kd">interface</span><span class="p">{})</span> <span class="p">(</span><a href="#PublicKey"><span class="nx">PublicKey</span></a><span class="p">,</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a><span class="p">)</span></pre> + <p>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. +<h4 id="ParseAuthorizedKey">func ParseAuthorizedKey</h4> + <pre class="chroma"><span class="kd">func</span> <span class="nf">ParseAuthorizedKey</span><span class="p">(</span><span class="nx">in</span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#byte"><span class="kt">byte</span></a><span class="p">)</span> <span class="p">(</span><span class="nx">out</span> <a href="#PublicKey"><span class="nx">PublicKey</span></a><span class="p">,</span> <span class="nx">comment</span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a><span class="p">,</span> <span class="nx">options</span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a><span class="p">,</span> <span class="nx">rest</span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#byte"><span class="kt">byte</span></a><span class="p">,</span> <span class="nx">err</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a><span class="p">)</span></pre> + <p>ParseAuthorizedKey parses a public key from an authorized_keys +file used in OpenSSH according to the sshd(8) manual page. +<h4 id="ParseKnownHosts">func ParseKnownHosts</h4> + <pre class="chroma"><span class="kd">func</span> <span class="nf">ParseKnownHosts</span><span class="p">(</span><span class="nx">in</span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#byte"><span class="kt">byte</span></a><span class="p">)</span> <span class="p">(</span><span class="nx">marker</span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a><span class="p">,</span> <span class="nx">hosts</span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a><span class="p">,</span> <span class="nx">pubKey</span> <a href="#PublicKey"><span class="nx">PublicKey</span></a><span class="p">,</span> <span class="nx">comment</span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a><span class="p">,</span> <span class="nx">rest</span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#byte"><span class="kt">byte</span></a><span class="p">,</span> <span class="nx">err</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a><span class="p">)</span></pre> + <p>ParseKnownHosts parses an entry in the format of the known_hosts file. +<p>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. +<p>The unparsed remainder of the input will be returned in rest. This function +can be called repeatedly to parse multiple entries. +<p>If no entries were found in the input then err will be io.EOF. Otherwise a +non-nil err value indicates a parse error. +<h4 id="ParsePublicKey">func ParsePublicKey</h4> + <pre class="chroma"><span class="kd">func</span> <span class="nf">ParsePublicKey</span><span class="p">(</span><span class="nx">in</span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#byte"><span class="kt">byte</span></a><span class="p">)</span> <span class="p">(</span><span class="nx">out</span> <a href="#PublicKey"><span class="nx">PublicKey</span></a><span class="p">,</span> <span class="nx">err</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a><span class="p">)</span></pre> + <p>ParsePublicKey parses an SSH public key formatted for use in +the SSH wire protocol according to RFC 4253, section 6.6. +<h3 id="RejectionReason">type RejectionReason</h3> + <pre class="chroma"><span class="kd">type</span> <span class="nx">RejectionReason</span> <a href="https://pkg.go.dev/builtin#uint32"><span class="kt">uint32</span></a></pre> + <p>RejectionReason is an enumeration used when rejecting channel creation +requests. See RFC 4254, section 5.1. +<pre class="chroma"><span class="kd">const</span> <span class="p">(</span> + <span id="Prohibited"><span class="nx">Prohibited</span></span> <a href="#RejectionReason"><span class="nx">RejectionReason</span></a> <span class="p">=</span> <a href="https://pkg.go.dev/builtin#iota"><span class="kc">iota</span></a> <span class="o">+</span> <span class="mi">1</span> + <span id="ConnectionFailed"><span class="nx">ConnectionFailed</span></span> + <span id="UnknownChannelType"><span class="nx">UnknownChannelType</span></span> + <span id="ResourceShortage"><span class="nx">ResourceShortage</span></span> +<span class="p">)</span></pre> + <h4 id="RejectionReason.String">func (RejectionReason) String</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">r</span> <a href="#RejectionReason"><span class="nx">RejectionReason</span></a><span class="p">)</span> <span class="nf">String</span><span class="p">()</span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a></pre> + <p>String converts the rejection reason to human readable form. +<h3 id="Request">type Request</h3> + <pre class="chroma"><span class="kd">type</span> <span class="nx">Request</span> <span class="kd">struct</span> <span class="p">{</span> + <span id="Request.Type"><span class="nx">Type</span></span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a> + <span id="Request.WantReply"><span class="nx">WantReply</span></span> <a href="https://pkg.go.dev/builtin#bool"><span class="kt">bool</span></a> + <span id="Request.Payload"><span class="nx">Payload</span></span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#byte"><span class="kt">byte</span></a> + <span class="c1">// contains filtered or unexported fields +</span><span class="c1"></span><span class="p">}</span></pre> + <p>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. +<h4 id="Request.Reply">func (*Request) Reply</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">r</span> <span class="o">*</span><a href="#Request"><span class="nx">Request</span></a><span class="p">)</span> <span class="nf">Reply</span><span class="p">(</span><span class="nx">ok</span> <a href="https://pkg.go.dev/builtin#bool"><span class="kt">bool</span></a><span class="p">,</span> <span class="nx">payload</span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#byte"><span class="kt">byte</span></a><span class="p">)</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a></pre> + <p>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. +<h3 id="RequestHandler">type RequestHandler</h3> + <pre class="chroma"><span class="kd">type</span> <span class="nx">RequestHandler</span> <span class="kd">interface</span> <span class="p">{</span> + <span id="RequestHandler.NewRequest"><span class="nf">NewRequest</span></span><span class="p">(</span><span class="nx">req</span> <span class="o">*</span><a href="#Request"><span class="nx">Request</span></a><span class="p">)</span> +<span class="p">}</span></pre> + <p>RequestHandler defines the interface to handle new <a href="#Request">Request</a>.ListenTCP +<h3 id="RequestHandlerFunc">type RequestHandlerFunc</h3> + <pre class="chroma"><span class="kd">type</span> <span class="nx">RequestHandlerFunc</span> <span class="kd">func</span><span class="p">(</span><span class="nx">req</span> <span class="o">*</span><a href="#Request"><span class="nx">Request</span></a><span class="p">)</span></pre> + <p>RequestHandlerFunc is an adapter to allow the use of ordinary function as +<a href="#RequestHandler">RequestHandler</a>. If f is a function with the appropriate signature, +RequestHandlerFunc(f) is a <a href="#RequestHandler">RequestHandler</a> that calls f. +<h4 id="RequestHandlerFunc.NewRequest">func (RequestHandlerFunc) NewRequest</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">f</span> <a href="#RequestHandlerFunc"><span class="nx">RequestHandlerFunc</span></a><span class="p">)</span> <span class="nf">NewRequest</span><span class="p">(</span><span class="nx">req</span> <span class="o">*</span><a href="#Request"><span class="nx">Request</span></a><span class="p">)</span></pre> + <p>NewRequest calls f(req). +<h3 id="Server">type Server</h3> + <pre class="chroma"><span class="kd">type</span> <span class="nx">Server</span> <span class="kd">struct</span> <span class="p">{</span> + <span class="c1">// Config contains configuration shared between client and server. +</span><span class="c1"></span> <a href="#Config"><span class="nx">Config</span></a> + + <span class="c1">// PublicKeyAuthAlgorithms specifies the supported client public key +</span><span class="c1"></span> <span class="c1">// authentication algorithms. Note that this should not include certificate +</span><span class="c1"></span> <span class="c1">// types since those use the underlying algorithm. This list is sent to the +</span><span class="c1"></span> <span class="c1">// client if it supports the server-sig-algs extension. Order is irrelevant. +</span><span class="c1"></span> <span class="c1">// If unspecified then a default set of algorithms is used. +</span><span class="c1"></span> <span id="Server.PublicKeyAuthAlgorithms"><span class="nx">PublicKeyAuthAlgorithms</span></span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a> + + <span class="c1">// NoClientAuth, if non-nil, is called when a user +</span><span class="c1"></span> <span class="c1">// attempts to authenticate with auth method "none". +</span><span class="c1"></span> <span id="Server.NoClientAuth"><span class="nx">NoClientAuth</span></span> <span class="kd">func</span><span class="p">(</span><a href="#ConnMetadata"><span class="nx">ConnMetadata</span></a><span class="p">)</span> <span class="p">(</span><span class="o">*</span><a href="#Permissions"><span class="nx">Permissions</span></a><span class="p">,</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a><span class="p">)</span> + + <span class="c1">// MaxAuthTries specifies the maximum number of authentication attempts +</span><span class="c1"></span> <span class="c1">// permitted per connection. If set to a negative number, the number of +</span><span class="c1"></span> <span class="c1">// attempts are unlimited. If set to zero, the number of attempts are limited +</span><span class="c1"></span> <span class="c1">// to 6. +</span><span class="c1"></span> <span id="Server.MaxAuthTries"><span class="nx">MaxAuthTries</span></span> <a href="https://pkg.go.dev/builtin#int"><span class="kt">int</span></a> + + <span class="c1">// Password, if non-nil, is called when a user +</span><span class="c1"></span> <span class="c1">// attempts to authenticate using a password. +</span><span class="c1"></span> <span id="Server.Password"><span class="nx">Password</span></span> <span class="kd">func</span><span class="p">(</span><span class="nx">conn</span> <a href="#ConnMetadata"><span class="nx">ConnMetadata</span></a><span class="p">,</span> <span class="nx">password</span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#byte"><span class="kt">byte</span></a><span class="p">)</span> <span class="p">(</span><span class="o">*</span><a href="#Permissions"><span class="nx">Permissions</span></a><span class="p">,</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a><span class="p">)</span> + + <span class="c1">// PublicKey, if non-nil, is called when a client +</span><span class="c1"></span> <span class="c1">// offers a public key for authentication. It must return a nil error +</span><span class="c1"></span> <span class="c1">// if the given public key can be used to authenticate the +</span><span class="c1"></span> <span class="c1">// given user. For example, see CertChecker.Authenticate. A +</span><span class="c1"></span> <span class="c1">// call to this function does not guarantee that the key +</span><span class="c1"></span> <span class="c1">// offered is in fact used to authenticate. To record any data +</span><span class="c1"></span> <span class="c1">// depending on the public key, store it inside a +</span><span class="c1"></span> <span class="c1">// Permissions.Extensions entry. +</span><span class="c1"></span> <span id="Server.PublicKey"><span class="nx">PublicKey</span></span> <span class="kd">func</span><span class="p">(</span><span class="nx">conn</span> <a href="#ConnMetadata"><span class="nx">ConnMetadata</span></a><span class="p">,</span> <span class="nx">key</span> <a href="#PublicKey"><span class="nx">PublicKey</span></a><span class="p">)</span> <span class="p">(</span><span class="o">*</span><a href="#Permissions"><span class="nx">Permissions</span></a><span class="p">,</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a><span class="p">)</span> + + <span class="c1">// KeyboardInteractive, if non-nil, is called when +</span><span class="c1"></span> <span class="c1">// keyboard-interactive authentication is selected (RFC +</span><span class="c1"></span> <span class="c1">// 4256). The client object's Challenge function should be +</span><span class="c1"></span> <span class="c1">// used to query the user. The callback may offer multiple +</span><span class="c1"></span> <span class="c1">// Challenge rounds. To avoid information leaks, the client +</span><span class="c1"></span> <span class="c1">// should be presented a challenge even if the user is +</span><span class="c1"></span> <span class="c1">// unknown. +</span><span class="c1"></span> <span id="Server.KeyboardInteractive"><span class="nx">KeyboardInteractive</span></span> <span class="kd">func</span><span class="p">(</span><span class="nx">conn</span> <a href="#ConnMetadata"><span class="nx">ConnMetadata</span></a><span class="p">,</span> <span class="nx">client</span> <a href="#KeyboardInteractiveChallenge"><span class="nx">KeyboardInteractiveChallenge</span></a><span class="p">)</span> <span class="p">(</span><span class="o">*</span><a href="#Permissions"><span class="nx">Permissions</span></a><span class="p">,</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a><span class="p">)</span> + + <span class="c1">// AuthLog, if non-nil, is called to log all authentication +</span><span class="c1"></span> <span class="c1">// attempts. +</span><span class="c1"></span> <span id="Server.AuthLog"><span class="nx">AuthLog</span></span> <span class="kd">func</span><span class="p">(</span><span class="nx">conn</span> <a href="#ConnMetadata"><span class="nx">ConnMetadata</span></a><span class="p">,</span> <span class="nx">method</span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a><span class="p">,</span> <span class="nx">err</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a><span class="p">)</span> + + <span class="c1">// ServerVersion is the version identification string to announce in +</span><span class="c1"></span> <span class="c1">// the public handshake. +</span><span class="c1"></span> <span class="c1">// If empty, a reasonable default is used. +</span><span class="c1"></span> <span class="c1">// Note that RFC 4253 section 4.2 requires that this string start with +</span><span class="c1"></span> <span class="c1">// "SSH-2.0-". +</span><span class="c1"></span> <span id="Server.ServerVersion"><span class="nx">ServerVersion</span></span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a> + + <span class="c1">// BannerCallback, if present, is called and the return string is sent to +</span><span class="c1"></span> <span class="c1">// the client after key exchange completed but before authentication. +</span><span class="c1"></span> <span id="Server.Banner"><span class="nx">Banner</span></span> <span class="kd">func</span><span class="p">(</span><span class="nx">conn</span> <a href="#ConnMetadata"><span class="nx">ConnMetadata</span></a><span class="p">)</span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a> + + <span class="c1">// GSSAPIWithMICConfig includes gssapi server and callback, which if both non-nil, is used +</span><span class="c1"></span> <span class="c1">// when gssapi-with-mic authentication is selected (RFC 4462 section 3). +</span><span class="c1"></span> <span id="Server.GSSAPIWithMICConfig"><span class="nx">GSSAPIWithMICConfig</span></span> <span class="o">*</span><a href="#GSSAPIWithMICConfig"><span class="nx">GSSAPIWithMICConfig</span></a> + + <span class="c1">// HandshakeTimeout defines the timeout for the initial handshake, as milliseconds. +</span><span class="c1"></span> <span id="Server.HandshakeTimeout"><span class="nx">HandshakeTimeout</span></span> <a href="https://pkg.go.dev/builtin#int"><span class="kt">int</span></a> + + <span class="c1">// ConnectionFailed, if non-nil, is called to report handshake errors. +</span><span class="c1"></span> <span id="Server.ConnectionFailed"><span class="nx">ConnectionFailed</span></span> <span class="kd">func</span><span class="p">(</span><span class="nx">c</span> <a href="https://pkg.go.dev/net"><span class="nx">net</span></a><span class="p">.</span><a href="https://pkg.go.dev/net#Conn"><span class="nx">Conn</span></a><span class="p">,</span> <span class="nx">err</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a><span class="p">)</span> + + <span class="c1">// ConnectionAddedCallback, if non-nil, is called when a client connects, by +</span><span class="c1"></span> <span class="c1">// returning an error the connection will be refused. +</span><span class="c1"></span> <span id="Server.ConnectionAdded"><span class="nx">ConnectionAdded</span></span> <span class="kd">func</span><span class="p">(</span><span class="nx">c</span> <a href="https://pkg.go.dev/net"><span class="nx">net</span></a><span class="p">.</span><a href="https://pkg.go.dev/net#Conn"><span class="nx">Conn</span></a><span class="p">)</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a> + + <span class="c1">// ClientHandler defines the handler for authenticated clients. It is called +</span><span class="c1"></span> <span class="c1">// if the handshake is successfull. The handler must serve requests and +</span><span class="c1"></span> <span class="c1">// channels using [ServerConn.Handle]. +</span><span class="c1"></span> <span id="Server.ClientHandler"><span class="nx">ClientHandler</span></span> <a href="#ClientHandler"><span class="nx">ClientHandler</span></a> + <span class="c1">// contains filtered or unexported fields +</span><span class="c1"></span><span class="p">}</span></pre> + <p>Server holds server specific configuration data. +<h4 id="Server.AddHostKey">func (*Server) AddHostKey</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">s</span> <span class="o">*</span><a href="#Server"><span class="nx">Server</span></a><span class="p">)</span> <span class="nf">AddHostKey</span><span class="p">(</span><span class="nx">key</span> <a href="#Signer"><span class="nx">Signer</span></a><span class="p">)</span></pre> + <p>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. +<details id="example-Server.AddHostKey" class="example"> + <summary>Example</summary> + <pre class="chroma"><span class="kn">package</span> <span class="nx">main</span> + +<span class="kn">import</span> <span class="p">(</span> + <span class="s">"fmt"</span> + <span class="s">"log"</span> + <span class="s">"os"</span> + + <span class="s">"golang.org/x/crypto/ssh"</span> +<span class="p">)</span> + +<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span> + <span class="c1">// Minimal Server supporting only password authentication. +</span><span class="c1"></span> <span class="nx">config</span> <span class="o">:=</span> <span class="o">&</span><span class="nx">ssh</span><span class="p">.</span><span class="nx">Server</span><span class="p">{</span> + <span class="nx">Password</span><span class="p">:</span> <span class="kd">func</span><span class="p">(</span><span class="nx">c</span> <span class="nx">ssh</span><span class="p">.</span><span class="nx">ConnMetadata</span><span class="p">,</span> <span class="nx">pass</span> <span class="p">[]</span><span class="kt">byte</span><span class="p">)</span> <span class="p">(</span><span class="o">*</span><span class="nx">ssh</span><span class="p">.</span><span class="nx">Permissions</span><span class="p">,</span> <span class="kt">error</span><span class="p">)</span> <span class="p">{</span> + <span class="c1">// Should use constant-time compare (or better, salt+hash) in +</span><span class="c1"></span> <span class="c1">// a production setting. +</span><span class="c1"></span> <span class="k">if</span> <span class="nx">c</span><span class="p">.</span><span class="nf">User</span><span class="p">()</span> <span class="o">==</span> <span class="s">"testuser"</span> <span class="o">&&</span> <span class="nb">string</span><span class="p">(</span><span class="nx">pass</span><span class="p">)</span> <span class="o">==</span> <span class="s">"tiger"</span> <span class="p">{</span> + <span class="k">return</span> <span class="kc">nil</span><span class="p">,</span> <span class="kc">nil</span> + <span class="p">}</span> + <span class="k">return</span> <span class="kc">nil</span><span class="p">,</span> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Errorf</span><span class="p">(</span><span class="s">"password rejected for %q"</span><span class="p">,</span> <span class="nx">c</span><span class="p">.</span><span class="nf">User</span><span class="p">())</span> + <span class="p">},</span> + <span class="p">}</span> + + <span class="nx">privateBytes</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">os</span><span class="p">.</span><span class="nf">ReadFile</span><span class="p">(</span><span class="s">"id_rsa"</span><span class="p">)</span> + <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span> + <span class="nx">log</span><span class="p">.</span><span class="nf">Fatal</span><span class="p">(</span><span class="s">"Failed to load private key: "</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span> + <span class="p">}</span> + + <span class="nx">private</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">ssh</span><span class="p">.</span><span class="nf">ParsePrivateKey</span><span class="p">(</span><span class="nx">privateBytes</span><span class="p">)</span> + <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span> + <span class="nx">log</span><span class="p">.</span><span class="nf">Fatal</span><span class="p">(</span><span class="s">"Failed to parse private key: "</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span> + <span class="p">}</span> + <span class="c1">// Restrict host key algorithms to disable ssh-rsa. +</span><span class="c1"></span> <span class="nx">signer</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">ssh</span><span class="p">.</span><span class="nf">NewSignerWithAlgorithms</span><span class="p">(</span><span class="nx">private</span><span class="p">,</span> <span class="p">[]</span><span class="kt">string</span><span class="p">{</span><span class="nx">ssh</span><span class="p">.</span><span class="nx">KeyAlgoRSASHA256</span><span class="p">,</span> <span class="nx">ssh</span><span class="p">.</span><span class="nx">KeyAlgoRSASHA512</span><span class="p">})</span> + <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span> + <span class="nx">log</span><span class="p">.</span><span class="nf">Fatal</span><span class="p">(</span><span class="s">"Failed to create private key with restricted algorithms: "</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span> + <span class="p">}</span> + <span class="nx">config</span><span class="p">.</span><span class="nf">AddHostKey</span><span class="p">(</span><span class="nx">signer</span><span class="p">)</span> +<span class="p">}</span></pre> + </details> + <h4 id="Server.Close">func (*Server) Close</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">s</span> <span class="o">*</span><a href="#Server"><span class="nx">Server</span></a><span class="p">)</span> <span class="nf">Close</span><span class="p">()</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a></pre> + <p>Close immediately closes all active net.Listeners. +<h4 id="Server.ListenAndServe">func (*Server) ListenAndServe</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">s</span> <span class="o">*</span><a href="#Server"><span class="nx">Server</span></a><span class="p">)</span> <span class="nf">ListenAndServe</span><span class="p">(</span><span class="nx">addr</span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a><span class="p">)</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a></pre> + <details id="example-Server.ListenAndServe" class="example"> + <summary>Example</summary> + <pre class="chroma"><span class="kn">package</span> <span class="nx">main</span> + +<span class="kn">import</span> <span class="p">(</span> + <span class="s">"fmt"</span> + <span class="s">"log"</span> + <span class="s">"net"</span> + <span class="s">"os"</span> + + <span class="s">"golang.org/x/crypto/ssh"</span> + <span class="s">"golang.org/x/term"</span> +<span class="p">)</span> + +<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span> + <span class="c1">// Public key authentication is done by comparing +</span><span class="c1"></span> <span class="c1">// the public key of a received connection +</span><span class="c1"></span> <span class="c1">// with the entries in the authorized_keys file. +</span><span class="c1"></span> <span class="nx">authorizedKeysBytes</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">os</span><span class="p">.</span><span class="nf">ReadFile</span><span class="p">(</span><span class="s">"authorized_keys"</span><span class="p">)</span> + <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span> + <span class="nx">log</span><span class="p">.</span><span class="nf">Fatalf</span><span class="p">(</span><span class="s">"Failed to load authorized_keys, err: %v"</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span> + <span class="p">}</span> + + <span class="nx">authorizedKeysMap</span> <span class="o">:=</span> <span class="kd">map</span><span class="p">[</span><span class="kt">string</span><span class="p">]</span><span class="kt">bool</span><span class="p">{}</span> + <span class="k">for</span> <span class="nb">len</span><span class="p">(</span><span class="nx">authorizedKeysBytes</span><span class="p">)</span> <span class="p">></span> <span class="mi">0</span> <span class="p">{</span> + <span class="nx">pubKey</span><span class="p">,</span> <span class="nx">_</span><span class="p">,</span> <span class="nx">_</span><span class="p">,</span> <span class="nx">rest</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">ssh</span><span class="p">.</span><span class="nf">ParseAuthorizedKey</span><span class="p">(</span><span class="nx">authorizedKeysBytes</span><span class="p">)</span> + <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span> + <span class="nx">log</span><span class="p">.</span><span class="nf">Fatal</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span> + <span class="p">}</span> + + <span class="nx">authorizedKeysMap</span><span class="p">[</span><span class="nb">string</span><span class="p">(</span><span class="nx">pubKey</span><span class="p">.</span><span class="nf">Marshal</span><span class="p">())]</span> <span class="p">=</span> <span class="kc">true</span> + <span class="nx">authorizedKeysBytes</span> <span class="p">=</span> <span class="nx">rest</span> + <span class="p">}</span> + + <span class="c1">// An SSH server is represented by a Server, which holds +</span><span class="c1"></span> <span class="c1">// certificate details and handles authentication of ServerConns. +</span><span class="c1"></span> <span class="nx">server</span> <span class="o">:=</span> <span class="o">&</span><span class="nx">ssh</span><span class="p">.</span><span class="nx">Server</span><span class="p">{</span> + <span class="c1">// Remove to disable password auth. +</span><span class="c1"></span> <span class="nx">Password</span><span class="p">:</span> <span class="kd">func</span><span class="p">(</span><span class="nx">c</span> <span class="nx">ssh</span><span class="p">.</span><span class="nx">ConnMetadata</span><span class="p">,</span> <span class="nx">pass</span> <span class="p">[]</span><span class="kt">byte</span><span class="p">)</span> <span class="p">(</span><span class="o">*</span><span class="nx">ssh</span><span class="p">.</span><span class="nx">Permissions</span><span class="p">,</span> <span class="kt">error</span><span class="p">)</span> <span class="p">{</span> + <span class="c1">// Should use constant-time compare (or better, salt+hash) in +</span><span class="c1"></span> <span class="c1">// a production setting. +</span><span class="c1"></span> <span class="k">if</span> <span class="nx">c</span><span class="p">.</span><span class="nf">User</span><span class="p">()</span> <span class="o">==</span> <span class="s">"testuser"</span> <span class="o">&&</span> <span class="nb">string</span><span class="p">(</span><span class="nx">pass</span><span class="p">)</span> <span class="o">==</span> <span class="s">"tiger"</span> <span class="p">{</span> + <span class="k">return</span> <span class="kc">nil</span><span class="p">,</span> <span class="kc">nil</span> + <span class="p">}</span> + <span class="k">return</span> <span class="kc">nil</span><span class="p">,</span> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Errorf</span><span class="p">(</span><span class="s">"password rejected for %q"</span><span class="p">,</span> <span class="nx">c</span><span class="p">.</span><span class="nf">User</span><span class="p">())</span> + <span class="p">},</span> + + <span class="c1">// Remove to disable public key auth. +</span><span class="c1"></span> <span class="nx">PublicKey</span><span class="p">:</span> <span class="kd">func</span><span class="p">(</span><span class="nx">c</span> <span class="nx">ssh</span><span class="p">.</span><span class="nx">ConnMetadata</span><span class="p">,</span> <span class="nx">pubKey</span> <span class="nx">ssh</span><span class="p">.</span><span class="nx">PublicKey</span><span class="p">)</span> <span class="p">(</span><span class="o">*</span><span class="nx">ssh</span><span class="p">.</span><span class="nx">Permissions</span><span class="p">,</span> <span class="kt">error</span><span class="p">)</span> <span class="p">{</span> + <span class="k">if</span> <span class="nx">authorizedKeysMap</span><span class="p">[</span><span class="nb">string</span><span class="p">(</span><span class="nx">pubKey</span><span class="p">.</span><span class="nf">Marshal</span><span class="p">())]</span> <span class="p">{</span> + <span class="k">return</span> <span class="o">&</span><span class="nx">ssh</span><span class="p">.</span><span class="nx">Permissions</span><span class="p">{</span> + <span class="c1">// Record the public key used for authentication. +</span><span class="c1"></span> <span class="nx">Extensions</span><span class="p">:</span> <span class="kd">map</span><span class="p">[</span><span class="kt">string</span><span class="p">]</span><span class="kt">string</span><span class="p">{</span> + <span class="s">"pubkey-fp"</span><span class="p">:</span> <span class="nx">ssh</span><span class="p">.</span><span class="nf">FingerprintSHA256</span><span class="p">(</span><span class="nx">pubKey</span><span class="p">),</span> + <span class="p">},</span> + <span class="p">},</span> <span class="kc">nil</span> + <span class="p">}</span> + <span class="k">return</span> <span class="kc">nil</span><span class="p">,</span> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Errorf</span><span class="p">(</span><span class="s">"unknown public key for %q"</span><span class="p">,</span> <span class="nx">c</span><span class="p">.</span><span class="nf">User</span><span class="p">())</span> + <span class="p">},</span> + <span class="nx">ConnectionFailed</span><span class="p">:</span> <span class="kd">func</span><span class="p">(</span><span class="nx">c</span> <span class="nx">net</span><span class="p">.</span><span class="nx">Conn</span><span class="p">,</span> <span class="nx">err</span> <span class="kt">error</span><span class="p">)</span> <span class="p">{</span> + <span class="c1">// Here we can get the error if an handshake fails +</span><span class="c1"></span> <span class="p">},</span> + <span class="nx">ClientHandler</span><span class="p">:</span> <span class="nx">ssh</span><span class="p">.</span><span class="nf">ClientHandlerFunc</span><span class="p">(</span><span class="kd">func</span><span class="p">(</span><span class="nx">conn</span> <span class="o">*</span><span class="nx">ssh</span><span class="p">.</span><span class="nx">ServerConn</span><span class="p">)</span> <span class="p">{</span> + <span class="nx">conn</span><span class="p">.</span><span class="nf">Handle</span><span class="p">(</span> + <span class="nx">ssh</span><span class="p">.</span><span class="nf">ChannelHandlerFunc</span><span class="p">(</span><span class="kd">func</span><span class="p">(</span><span class="nx">newChannel</span> <span class="o">*</span><span class="nx">ssh</span><span class="p">.</span><span class="nx">NewChannel</span><span class="p">)</span> <span class="p">{</span> + <span class="c1">// In this handler we have to accept and use the new channel or reject it. +</span><span class="c1"></span> + <span class="c1">// Channels have a type, depending on the application level +</span><span class="c1"></span> <span class="c1">// protocol intended. In the case of a shell, the type is +</span><span class="c1"></span> <span class="c1">// "session" and ServerShell may be used to present a simple +</span><span class="c1"></span> <span class="c1">// terminal interface. +</span><span class="c1"></span> <span class="k">if</span> <span class="nx">newChannel</span><span class="p">.</span><span class="nf">ChannelType</span><span class="p">()</span> <span class="o">!=</span> <span class="s">"session"</span> <span class="p">{</span> + <span class="nx">newChannel</span><span class="p">.</span><span class="nf">Reject</span><span class="p">(</span><span class="nx">ssh</span><span class="p">.</span><span class="nx">UnknownChannelType</span><span class="p">,</span> <span class="s">"unknown channel type"</span><span class="p">)</span> + <span class="k">return</span> + <span class="p">}</span> + <span class="nx">channel</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">newChannel</span><span class="p">.</span><span class="nf">Accept</span><span class="p">()</span> + <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span> + <span class="nx">log</span><span class="p">.</span><span class="nf">Fatalf</span><span class="p">(</span><span class="s">"Could not accept channel: %v"</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span> + <span class="p">}</span> + <span class="nx">err</span> <span class="p">=</span> <span class="nx">channel</span><span class="p">.</span><span class="nf">Handle</span><span class="p">(</span><span class="nx">ssh</span><span class="p">.</span><span class="nf">RequestHandlerFunc</span><span class="p">(</span><span class="kd">func</span><span class="p">(</span><span class="nx">req</span> <span class="o">*</span><span class="nx">ssh</span><span class="p">.</span><span class="nx">Request</span><span class="p">)</span> <span class="p">{</span> + <span class="c1">// Sessions have out-of-band requests such as "shell", +</span><span class="c1"></span> <span class="c1">// "pty-req" and "env". Here we handle only the +</span><span class="c1"></span> <span class="c1">// "shell" request. +</span><span class="c1"></span> <span class="nx">req</span><span class="p">.</span><span class="nf">Reply</span><span class="p">(</span><span class="nx">req</span><span class="p">.</span><span class="nx">Type</span> <span class="o">==</span> <span class="s">"shell"</span><span class="p">,</span> <span class="kc">nil</span><span class="p">)</span> + <span class="p">}))</span> + + <span class="nx">terminal</span> <span class="o">:=</span> <span class="nx">term</span><span class="p">.</span><span class="nf">NewTerminal</span><span class="p">(</span><span class="nx">channel</span><span class="p">,</span> <span class="s">"> "</span><span class="p">)</span> + + <span class="k">go</span> <span class="kd">func</span><span class="p">()</span> <span class="p">{</span> + <span class="k">defer</span> <span class="kd">func</span><span class="p">()</span> <span class="p">{</span> + <span class="nx">channel</span><span class="p">.</span><span class="nf">Close</span><span class="p">()</span> + <span class="p">}()</span> + <span class="k">for</span> <span class="p">{</span> + <span class="nx">line</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">terminal</span><span class="p">.</span><span class="nf">ReadLine</span><span class="p">()</span> + <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span> + <span class="k">break</span> + <span class="p">}</span> + <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nx">line</span><span class="p">)</span> + <span class="p">}</span> + <span class="p">}()</span> + <span class="p">}),</span> + <span class="nx">ssh</span><span class="p">.</span><span class="nf">RequestHandlerFunc</span><span class="p">(</span><span class="kd">func</span><span class="p">(</span><span class="nx">req</span> <span class="o">*</span><span class="nx">ssh</span><span class="p">.</span><span class="nx">Request</span><span class="p">)</span> <span class="p">{</span> + <span class="k">if</span> <span class="nx">req</span><span class="p">.</span><span class="nx">WantReply</span> <span class="p">{</span> + <span class="nx">req</span><span class="p">.</span><span class="nf">Reply</span><span class="p">(</span><span class="kc">false</span><span class="p">,</span> <span class="kc">nil</span><span class="p">)</span> + <span class="p">}</span> + <span class="p">}),</span> + <span class="p">)</span> + <span class="p">}),</span> + <span class="p">}</span> + + <span class="nx">privateBytes</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">os</span><span class="p">.</span><span class="nf">ReadFile</span><span class="p">(</span><span class="s">"id_rsa"</span><span class="p">)</span> + <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span> + <span class="nx">log</span><span class="p">.</span><span class="nf">Fatal</span><span class="p">(</span><span class="s">"Failed to load private key: "</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span> + <span class="p">}</span> + + <span class="nx">private</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">ssh</span><span class="p">.</span><span class="nf">ParsePrivateKey</span><span class="p">(</span><span class="nx">privateBytes</span><span class="p">)</span> + <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span> + <span class="nx">log</span><span class="p">.</span><span class="nf">Fatal</span><span class="p">(</span><span class="s">"Failed to parse private key: "</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span> + <span class="p">}</span> + <span class="nx">server</span><span class="p">.</span><span class="nf">AddHostKey</span><span class="p">(</span><span class="nx">private</span><span class="p">)</span> + + <span class="nx">server</span><span class="p">.</span><span class="nf">ListenAndServe</span><span class="p">(</span><span class="s">"0.0.0.0:2022"</span><span class="p">)</span> +<span class="p">}</span></pre> + </details> + <h4 id="Server.Serve">func (*Server) Serve</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">s</span> <span class="o">*</span><a href="#Server"><span class="nx">Server</span></a><span class="p">)</span> <span class="nf">Serve</span><span class="p">(</span><span class="nx">l</span> <a href="https://pkg.go.dev/net"><span class="nx">net</span></a><span class="p">.</span><a href="https://pkg.go.dev/net#Listener"><span class="nx">Listener</span></a><span class="p">)</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a></pre> + <p>Serve accepts incoming connections on the Listener l, creating a new service +goroutine for each and execute the provided <a href="#ClientHandler">ClientHandler</a> implementation. +<h3 id="ServerAuthCallbacks">type ServerAuthCallbacks</h3> + <pre class="chroma"><span class="kd">type</span> <span class="nx">ServerAuthCallbacks</span> <span class="kd">struct</span> <span class="p">{</span> + <span class="c1">// Password behaves like [Server.PasswordCallback]. +</span><span class="c1"></span> <span id="ServerAuthCallbacks.Password"><span class="nx">Password</span></span> <span class="kd">func</span><span class="p">(</span><span class="nx">conn</span> <a href="#ConnMetadata"><span class="nx">ConnMetadata</span></a><span class="p">,</span> <span class="nx">password</span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#byte"><span class="kt">byte</span></a><span class="p">)</span> <span class="p">(</span><span class="o">*</span><a href="#Permissions"><span class="nx">Permissions</span></a><span class="p">,</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a><span class="p">)</span> + + <span class="c1">// PublicKey behaves like [Server.PublicKeyCallback]. +</span><span class="c1"></span> <span id="ServerAuthCallbacks.PublicKey"><span class="nx">PublicKey</span></span> <span class="kd">func</span><span class="p">(</span><span class="nx">conn</span> <a href="#ConnMetadata"><span class="nx">ConnMetadata</span></a><span class="p">,</span> <span class="nx">key</span> <a href="#PublicKey"><span class="nx">PublicKey</span></a><span class="p">)</span> <span class="p">(</span><span class="o">*</span><a href="#Permissions"><span class="nx">Permissions</span></a><span class="p">,</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a><span class="p">)</span> + + <span class="c1">// KeyboardInteractive behaves like [Server.KeyboardInteractiveCallback]. +</span><span class="c1"></span> <span id="ServerAuthCallbacks.KeyboardInteractive"><span class="nx">KeyboardInteractive</span></span> <span class="kd">func</span><span class="p">(</span><span class="nx">conn</span> <a href="#ConnMetadata"><span class="nx">ConnMetadata</span></a><span class="p">,</span> <span class="nx">client</span> <a href="#KeyboardInteractiveChallenge"><span class="nx">KeyboardInteractiveChallenge</span></a><span class="p">)</span> <span class="p">(</span><span class="o">*</span><a href="#Permissions"><span class="nx">Permissions</span></a><span class="p">,</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a><span class="p">)</span> + + <span class="c1">// GSSAPIWithMICConfig behaves like [Server.GSSAPIWithMICConfig]. +</span><span class="c1"></span> <span id="ServerAuthCallbacks.GSSAPIWithMICConfig"><span class="nx">GSSAPIWithMICConfig</span></span> <span class="o">*</span><a href="#GSSAPIWithMICConfig"><span class="nx">GSSAPIWithMICConfig</span></a> +<span class="p">}</span></pre> + <p>ServerAuthCallbacks defines server-side authentication callbacks. +<h3 id="ServerAuthError">type ServerAuthError</h3> + <pre class="chroma"><span class="kd">type</span> <span class="nx">ServerAuthError</span> <span class="kd">struct</span> <span class="p">{</span> + <span class="c1">// Errors contains authentication errors returned by the authentication +</span><span class="c1"></span> <span class="c1">// callback methods. The first entry is typically ErrNoAuth. +</span><span class="c1"></span> <span id="ServerAuthError.Errors"><span class="nx">Errors</span></span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a> +<span class="p">}</span></pre> + <p>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. +<h4 id="ServerAuthError.Error">func (ServerAuthError) Error</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">l</span> <a href="#ServerAuthError"><span class="nx">ServerAuthError</span></a><span class="p">)</span> <span class="nf">Error</span><span class="p">()</span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a></pre> + <h3 id="ServerConn">type ServerConn</h3> + <pre class="chroma"><span class="kd">type</span> <span class="nx">ServerConn</span> <span class="kd">struct</span> <span class="p">{</span> + + <span class="c1">// If the succeeding authentication callback returned a +</span><span class="c1"></span> <span class="c1">// non-nil Permissions pointer, it is stored here. +</span><span class="c1"></span> <span id="ServerConn.Permissions"><span class="nx">Permissions</span></span> <span class="o">*</span><a href="#Permissions"><span class="nx">Permissions</span></a> + <span class="c1">// contains filtered or unexported fields +</span><span class="c1"></span><span class="p">}</span></pre> + <p>ServerConn is an authenticated SSH connection, as seen from the +server +<h4 id="NewServerConn">func NewServerConn</h4> + <pre class="chroma"><span class="kd">func</span> <span class="nf">NewServerConn</span><span class="p">(</span><span class="nx">ctx</span> <a href="https://pkg.go.dev/context"><span class="nx">context</span></a><span class="p">.</span><a href="https://pkg.go.dev/context#Context"><span class="nx">Context</span></a><span class="p">,</span> <span class="nx">c</span> <a href="https://pkg.go.dev/net"><span class="nx">net</span></a><span class="p">.</span><a href="https://pkg.go.dev/net#Conn"><span class="nx">Conn</span></a><span class="p">,</span> <span class="nx">config</span> <span class="o">*</span><a href="#Server"><span class="nx">Server</span></a><span class="p">)</span> <span class="p">(</span><span class="o">*</span><a href="#ServerConn"><span class="nx">ServerConn</span></a><span class="p">,</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a><span class="p">)</span></pre> + <p>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. +<p>The returned error may be of type *ServerAuthError for +authentication errors. +<p>This is a low level API useful for advanced use cases, you must use +<a href="#ServerConn.Handle">ServerConn.Handle</a> to handle Requests and Channels. +<details id="example-NewServerConn" class="example"> + <summary>Example</summary> + <pre class="chroma"><span class="kn">package</span> <span class="nx">main</span> + +<span class="kn">import</span> <span class="p">(</span> + <span class="s">"context"</span> + <span class="s">"fmt"</span> + <span class="s">"log"</span> + <span class="s">"net"</span> + <span class="s">"os"</span> + <span class="s">"sync"</span> + <span class="s">"time"</span> + + <span class="s">"golang.org/x/crypto/ssh"</span> + <span class="s">"golang.org/x/term"</span> +<span class="p">)</span> + +<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span> + <span class="c1">// Public key authentication is done by comparing +</span><span class="c1"></span> <span class="c1">// the public key of a received connection +</span><span class="c1"></span> <span class="c1">// with the entries in the authorized_keys file. +</span><span class="c1"></span> <span class="nx">authorizedKeysBytes</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">os</span><span class="p">.</span><span class="nf">ReadFile</span><span class="p">(</span><span class="s">"authorized_keys"</span><span class="p">)</span> + <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span> + <span class="nx">log</span><span class="p">.</span><span class="nf">Fatalf</span><span class="p">(</span><span class="s">"Failed to load authorized_keys, err: %v"</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span> + <span class="p">}</span> + + <span class="nx">authorizedKeysMap</span> <span class="o">:=</span> <span class="kd">map</span><span class="p">[</span><span class="kt">string</span><span class="p">]</span><span class="kt">bool</span><span class="p">{}</span> + <span class="k">for</span> <span class="nb">len</span><span class="p">(</span><span class="nx">authorizedKeysBytes</span><span class="p">)</span> <span class="p">></span> <span class="mi">0</span> <span class="p">{</span> + <span class="nx">pubKey</span><span class="p">,</span> <span class="nx">_</span><span class="p">,</span> <span class="nx">_</span><span class="p">,</span> <span class="nx">rest</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">ssh</span><span class="p">.</span><span class="nf">ParseAuthorizedKey</span><span class="p">(</span><span class="nx">authorizedKeysBytes</span><span class="p">)</span> + <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span> + <span class="nx">log</span><span class="p">.</span><span class="nf">Fatal</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span> + <span class="p">}</span> + + <span class="nx">authorizedKeysMap</span><span class="p">[</span><span class="nb">string</span><span class="p">(</span><span class="nx">pubKey</span><span class="p">.</span><span class="nf">Marshal</span><span class="p">())]</span> <span class="p">=</span> <span class="kc">true</span> + <span class="nx">authorizedKeysBytes</span> <span class="p">=</span> <span class="nx">rest</span> + <span class="p">}</span> + + <span class="c1">// An SSH server is represented by a Server, which holds +</span><span class="c1"></span> <span class="c1">// certificate details and handles authentication of ServerConns. +</span><span class="c1"></span> <span class="nx">config</span> <span class="o">:=</span> <span class="o">&</span><span class="nx">ssh</span><span class="p">.</span><span class="nx">Server</span><span class="p">{</span> + <span class="c1">// Remove to disable password auth. +</span><span class="c1"></span> <span class="nx">Password</span><span class="p">:</span> <span class="kd">func</span><span class="p">(</span><span class="nx">c</span> <span class="nx">ssh</span><span class="p">.</span><span class="nx">ConnMetadata</span><span class="p">,</span> <span class="nx">pass</span> <span class="p">[]</span><span class="kt">byte</span><span class="p">)</span> <span class="p">(</span><span class="o">*</span><span class="nx">ssh</span><span class="p">.</span><span class="nx">Permissions</span><span class="p">,</span> <span class="kt">error</span><span class="p">)</span> <span class="p">{</span> + <span class="c1">// Should use constant-time compare (or better, salt+hash) in +</span><span class="c1"></span> <span class="c1">// a production setting. +</span><span class="c1"></span> <span class="k">if</span> <span class="nx">c</span><span class="p">.</span><span class="nf">User</span><span class="p">()</span> <span class="o">==</span> <span class="s">"testuser"</span> <span class="o">&&</span> <span class="nb">string</span><span class="p">(</span><span class="nx">pass</span><span class="p">)</span> <span class="o">==</span> <span class="s">"tiger"</span> <span class="p">{</span> + <span class="k">return</span> <span class="kc">nil</span><span class="p">,</span> <span class="kc">nil</span> + <span class="p">}</span> + <span class="k">return</span> <span class="kc">nil</span><span class="p">,</span> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Errorf</span><span class="p">(</span><span class="s">"password rejected for %q"</span><span class="p">,</span> <span class="nx">c</span><span class="p">.</span><span class="nf">User</span><span class="p">())</span> + <span class="p">},</span> + + <span class="c1">// Remove to disable public key auth. +</span><span class="c1"></span> <span class="nx">PublicKey</span><span class="p">:</span> <span class="kd">func</span><span class="p">(</span><span class="nx">c</span> <span class="nx">ssh</span><span class="p">.</span><span class="nx">ConnMetadata</span><span class="p">,</span> <span class="nx">pubKey</span> <span class="nx">ssh</span><span class="p">.</span><span class="nx">PublicKey</span><span class="p">)</span> <span class="p">(</span><span class="o">*</span><span class="nx">ssh</span><span class="p">.</span><span class="nx">Permissions</span><span class="p">,</span> <span class="kt">error</span><span class="p">)</span> <span class="p">{</span> + <span class="k">if</span> <span class="nx">authorizedKeysMap</span><span class="p">[</span><span class="nb">string</span><span class="p">(</span><span class="nx">pubKey</span><span class="p">.</span><span class="nf">Marshal</span><span class="p">())]</span> <span class="p">{</span> + <span class="k">return</span> <span class="o">&</span><span class="nx">ssh</span><span class="p">.</span><span class="nx">Permissions</span><span class="p">{</span> + <span class="c1">// Record the public key used for authentication. +</span><span class="c1"></span> <span class="nx">Extensions</span><span class="p">:</span> <span class="kd">map</span><span class="p">[</span><span class="kt">string</span><span class="p">]</span><span class="kt">string</span><span class="p">{</span> + <span class="s">"pubkey-fp"</span><span class="p">:</span> <span class="nx">ssh</span><span class="p">.</span><span class="nf">FingerprintSHA256</span><span class="p">(</span><span class="nx">pubKey</span><span class="p">),</span> + <span class="p">},</span> + <span class="p">},</span> <span class="kc">nil</span> + <span class="p">}</span> + <span class="k">return</span> <span class="kc">nil</span><span class="p">,</span> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Errorf</span><span class="p">(</span><span class="s">"unknown public key for %q"</span><span class="p">,</span> <span class="nx">c</span><span class="p">.</span><span class="nf">User</span><span class="p">())</span> + <span class="p">},</span> + <span class="p">}</span> + + <span class="nx">privateBytes</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">os</span><span class="p">.</span><span class="nf">ReadFile</span><span class="p">(</span><span class="s">"id_rsa"</span><span class="p">)</span> + <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span> + <span class="nx">log</span><span class="p">.</span><span class="nf">Fatal</span><span class="p">(</span><span class="s">"Failed to load private key: "</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span> + <span class="p">}</span> + + <span class="nx">private</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">ssh</span><span class="p">.</span><span class="nf">ParsePrivateKey</span><span class="p">(</span><span class="nx">privateBytes</span><span class="p">)</span> + <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span> + <span class="nx">log</span><span class="p">.</span><span class="nf">Fatal</span><span class="p">(</span><span class="s">"Failed to parse private key: "</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span> + <span class="p">}</span> + <span class="nx">config</span><span class="p">.</span><span class="nf">AddHostKey</span><span class="p">(</span><span class="nx">private</span><span class="p">)</span> + + <span class="c1">// Once a Server has been configured, connections can be +</span><span class="c1"></span> <span class="c1">// accepted. +</span><span class="c1"></span> <span class="nx">listener</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">net</span><span class="p">.</span><span class="nf">Listen</span><span class="p">(</span><span class="s">"tcp"</span><span class="p">,</span> <span class="s">"0.0.0.0:2022"</span><span class="p">)</span> + <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span> + <span class="nx">log</span><span class="p">.</span><span class="nf">Fatal</span><span class="p">(</span><span class="s">"failed to listen for connection: "</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span> + <span class="p">}</span> + <span class="nx">nConn</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">listener</span><span class="p">.</span><span class="nf">Accept</span><span class="p">()</span> + <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span> + <span class="nx">log</span><span class="p">.</span><span class="nf">Fatal</span><span class="p">(</span><span class="s">"failed to accept incoming connection: "</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span> + <span class="p">}</span> + + <span class="c1">// Allow at most 10 seconds to complete the handshake and create the +</span><span class="c1"></span> <span class="c1">// server connection. +</span><span class="c1"></span> <span class="nx">ctx</span><span class="p">,</span> <span class="nx">cancel</span> <span class="o">:=</span> <span class="nx">context</span><span class="p">.</span><span class="nf">WithTimeout</span><span class="p">(</span><span class="nx">context</span><span class="p">.</span><span class="nf">Background</span><span class="p">(),</span> <span class="mi">10</span><span class="o">*</span><span class="nx">time</span><span class="p">.</span><span class="nx">Second</span><span class="p">)</span> + <span class="k">defer</span> <span class="nf">cancel</span><span class="p">()</span> + + <span class="c1">// Before use, a handshake must be performed on the incoming +</span><span class="c1"></span> <span class="c1">// net.Conn. +</span><span class="c1"></span> <span class="nx">conn</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">ssh</span><span class="p">.</span><span class="nf">NewServerConn</span><span class="p">(</span><span class="nx">ctx</span><span class="p">,</span> <span class="nx">nConn</span><span class="p">,</span> <span class="nx">config</span><span class="p">)</span> + <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span> + <span class="nx">log</span><span class="p">.</span><span class="nf">Fatal</span><span class="p">(</span><span class="s">"failed to handshake: "</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span> + <span class="p">}</span> + <span class="nx">log</span><span class="p">.</span><span class="nf">Printf</span><span class="p">(</span><span class="s">"logged in with key %s"</span><span class="p">,</span> <span class="nx">conn</span><span class="p">.</span><span class="nx">Permissions</span><span class="p">.</span><span class="nx">Extensions</span><span class="p">[</span><span class="s">"pubkey-fp"</span><span class="p">])</span> + + <span class="kd">var</span> <span class="nx">wg</span> <span class="nx">sync</span><span class="p">.</span><span class="nx">WaitGroup</span> + <span class="k">defer</span> <span class="nx">wg</span><span class="p">.</span><span class="nf">Wait</span><span class="p">()</span> + + <span class="nx">conn</span><span class="p">.</span><span class="nf">Handle</span><span class="p">(</span> + <span class="nx">ssh</span><span class="p">.</span><span class="nf">ChannelHandlerFunc</span><span class="p">(</span><span class="kd">func</span><span class="p">(</span><span class="nx">newChannel</span> <span class="o">*</span><span class="nx">ssh</span><span class="p">.</span><span class="nx">NewChannel</span><span class="p">)</span> <span class="p">{</span> + <span class="c1">// Channels have a type, depending on the application level +</span><span class="c1"></span> <span class="c1">// protocol intended. In the case of a shell, the type is +</span><span class="c1"></span> <span class="c1">// "session" and ServerShell may be used to present a simple +</span><span class="c1"></span> <span class="c1">// terminal interface. +</span><span class="c1"></span> <span class="k">if</span> <span class="nx">newChannel</span><span class="p">.</span><span class="nf">ChannelType</span><span class="p">()</span> <span class="o">!=</span> <span class="s">"session"</span> <span class="p">{</span> + <span class="nx">newChannel</span><span class="p">.</span><span class="nf">Reject</span><span class="p">(</span><span class="nx">ssh</span><span class="p">.</span><span class="nx">UnknownChannelType</span><span class="p">,</span> <span class="s">"unknown channel type"</span><span class="p">)</span> + <span class="k">return</span> + <span class="p">}</span> + <span class="nx">channel</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">newChannel</span><span class="p">.</span><span class="nf">Accept</span><span class="p">()</span> + <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span> + <span class="nx">log</span><span class="p">.</span><span class="nf">Fatalf</span><span class="p">(</span><span class="s">"Could not accept channel: %v"</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span> + <span class="p">}</span> + <span class="nx">err</span> <span class="p">=</span> <span class="nx">channel</span><span class="p">.</span><span class="nf">Handle</span><span class="p">(</span><span class="nx">ssh</span><span class="p">.</span><span class="nf">RequestHandlerFunc</span><span class="p">(</span><span class="kd">func</span><span class="p">(</span><span class="nx">req</span> <span class="o">*</span><span class="nx">ssh</span><span class="p">.</span><span class="nx">Request</span><span class="p">)</span> <span class="p">{</span> + <span class="c1">// Sessions have out-of-band requests such as "shell", +</span><span class="c1"></span> <span class="c1">// "pty-req" and "env". Here we handle only the +</span><span class="c1"></span> <span class="c1">// "shell" request. +</span><span class="c1"></span> <span class="nx">req</span><span class="p">.</span><span class="nf">Reply</span><span class="p">(</span><span class="nx">req</span><span class="p">.</span><span class="nx">Type</span> <span class="o">==</span> <span class="s">"shell"</span><span class="p">,</span> <span class="kc">nil</span><span class="p">)</span> + <span class="p">}))</span> + <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span> + <span class="nx">log</span><span class="p">.</span><span class="nf">Fatalf</span><span class="p">(</span><span class="s">"Could not handle channel: %v"</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span> + <span class="p">}</span> + + <span class="nx">terminal</span> <span class="o">:=</span> <span class="nx">term</span><span class="p">.</span><span class="nf">NewTerminal</span><span class="p">(</span><span class="nx">channel</span><span class="p">,</span> <span class="s">"> "</span><span class="p">)</span> + + <span class="nx">wg</span><span class="p">.</span><span class="nf">Add</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> + <span class="k">go</span> <span class="kd">func</span><span class="p">()</span> <span class="p">{</span> + <span class="k">defer</span> <span class="kd">func</span><span class="p">()</span> <span class="p">{</span> + <span class="nx">channel</span><span class="p">.</span><span class="nf">Close</span><span class="p">()</span> + <span class="nx">wg</span><span class="p">.</span><span class="nf">Done</span><span class="p">()</span> + <span class="p">}()</span> + <span class="k">for</span> <span class="p">{</span> + <span class="nx">line</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">terminal</span><span class="p">.</span><span class="nf">ReadLine</span><span class="p">()</span> + <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span> + <span class="k">break</span> + <span class="p">}</span> + <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nx">line</span><span class="p">)</span> + <span class="p">}</span> + <span class="p">}()</span> + <span class="p">}),</span> + <span class="nx">ssh</span><span class="p">.</span><span class="nf">RequestHandlerFunc</span><span class="p">(</span><span class="kd">func</span><span class="p">(</span><span class="nx">req</span> <span class="o">*</span><span class="nx">ssh</span><span class="p">.</span><span class="nx">Request</span><span class="p">)</span> <span class="p">{</span> + <span class="k">if</span> <span class="nx">req</span><span class="p">.</span><span class="nx">WantReply</span> <span class="p">{</span> + <span class="nx">req</span><span class="p">.</span><span class="nf">Reply</span><span class="p">(</span><span class="kc">false</span><span class="p">,</span> <span class="kc">nil</span><span class="p">)</span> + <span class="p">}</span> + <span class="p">}))</span> +<span class="p">}</span></pre> + </details> + <h4 id="ServerConn.Close">func (*ServerConn) Close</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">c</span> <span class="o">*</span><a href="#ServerConn"><span class="nx">ServerConn</span></a><span class="p">)</span> <span class="nf">Close</span><span class="p">()</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a></pre> + <p>Close closes the underlying network connection. +<h4 id="ServerConn.Handle">func (*ServerConn) Handle</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">c</span> <span class="o">*</span><a href="#ServerConn"><span class="nx">ServerConn</span></a><span class="p">)</span> <span class="nf">Handle</span><span class="p">(</span><span class="nx">channelHandler</span> <a href="#ChannelHandler"><span class="nx">ChannelHandler</span></a><span class="p">,</span> <span class="nx">requestHandler</span> <a href="#RequestHandler"><span class="nx">RequestHandler</span></a><span class="p">)</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a></pre> + <p>Handle must be called to handle requests and channels. Handle blocks. If +channelHandler is nil channels will be rejected. If requestHandler is nil, +requests will be discarded. +<h3 id="Session">type Session</h3> + <pre class="chroma"><span class="kd">type</span> <span class="nx">Session</span> <span class="kd">struct</span> <span class="p">{</span> + <span class="c1">// Stdin specifies the remote process's standard input. +</span><span class="c1"></span> <span class="c1">// If Stdin is nil, the remote process reads from an empty +</span><span class="c1"></span> <span class="c1">// bytes.Buffer. +</span><span class="c1"></span> <span id="Session.Stdin"><span class="nx">Stdin</span></span> <a href="https://pkg.go.dev/io"><span class="nx">io</span></a><span class="p">.</span><a href="https://pkg.go.dev/io#Reader"><span class="nx">Reader</span></a> + + <span class="c1">// Stdout and Stderr specify the remote process's standard +</span><span class="c1"></span> <span class="c1">// output and error. +</span><span class="c1"></span> <span class="c1">// +</span><span class="c1"></span> <span class="c1">// If either is nil, Run connects the corresponding file +</span><span class="c1"></span> <span class="c1">// descriptor to an instance of io.Discard. There is a +</span><span class="c1"></span> <span class="c1">// fixed amount of buffering that is shared for the two streams. +</span><span class="c1"></span> <span class="c1">// If either blocks it may eventually cause the remote +</span><span class="c1"></span> <span class="c1">// command to block. +</span><span class="c1"></span> <span id="Session.Stdout"><span class="nx">Stdout</span></span> <a href="https://pkg.go.dev/io"><span class="nx">io</span></a><span class="p">.</span><a href="https://pkg.go.dev/io#Writer"><span class="nx">Writer</span></a> + <span id="Session.Stderr"><span class="nx">Stderr</span></span> <a href="https://pkg.go.dev/io"><span class="nx">io</span></a><span class="p">.</span><a href="https://pkg.go.dev/io#Writer"><span class="nx">Writer</span></a> + <span class="c1">// contains filtered or unexported fields +</span><span class="c1"></span><span class="p">}</span></pre> + <p>A Session represents a connection to a remote command or shell. +<h4 id="Session.Close">func (*Session) Close</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">s</span> <span class="o">*</span><a href="#Session"><span class="nx">Session</span></a><span class="p">)</span> <span class="nf">Close</span><span class="p">()</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a></pre> + <h4 id="Session.CombinedOutput">func (*Session) CombinedOutput</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">s</span> <span class="o">*</span><a href="#Session"><span class="nx">Session</span></a><span class="p">)</span> <span class="nf">CombinedOutput</span><span class="p">(</span><span class="nx">cmd</span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a><span class="p">)</span> <span class="p">([]</span><a href="https://pkg.go.dev/builtin#byte"><span class="kt">byte</span></a><span class="p">,</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a><span class="p">)</span></pre> + <p>CombinedOutput runs cmd on the remote host and returns its combined +standard output and standard error. +<h4 id="Session.Output">func (*Session) Output</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">s</span> <span class="o">*</span><a href="#Session"><span class="nx">Session</span></a><span class="p">)</span> <span class="nf">Output</span><span class="p">(</span><span class="nx">cmd</span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a><span class="p">)</span> <span class="p">([]</span><a href="https://pkg.go.dev/builtin#byte"><span class="kt">byte</span></a><span class="p">,</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a><span class="p">)</span></pre> + <p>Output runs cmd on the remote host and returns its standard output. +<h4 id="Session.RequestPty">func (*Session) RequestPty</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">s</span> <span class="o">*</span><a href="#Session"><span class="nx">Session</span></a><span class="p">)</span> <span class="nf">RequestPty</span><span class="p">(</span><span class="nx">term</span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a><span class="p">,</span> <span class="nx">h</span><span class="p">,</span> <span class="nx">w</span> <a href="https://pkg.go.dev/builtin#int"><span class="kt">int</span></a><span class="p">,</span> <span class="nx">termmodes</span> <a href="#TerminalModes"><span class="nx">TerminalModes</span></a><span class="p">)</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a></pre> + <p>RequestPty requests the association of a pty with the session on the remote host. +<details id="example-Session.RequestPty" class="example"> + <summary>Example</summary> + <pre class="chroma"><span class="kn">package</span> <span class="nx">main</span> + +<span class="kn">import</span> <span class="p">(</span> + <span class="s">"context"</span> + <span class="s">"log"</span> + + <span class="s">"golang.org/x/crypto/ssh"</span> +<span class="p">)</span> + +<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span> + <span class="kd">var</span> <span class="nx">hostKey</span> <span class="nx">ssh</span><span class="p">.</span><span class="nx">PublicKey</span> + <span class="c1">// Create client config +</span><span class="c1"></span> <span class="nx">config</span> <span class="o">:=</span> <span class="o">&</span><span class="nx">ssh</span><span class="p">.</span><span class="nx">ClientConfig</span><span class="p">{</span> + <span class="nx">User</span><span class="p">:</span> <span class="s">"username"</span><span class="p">,</span> + <span class="nx">Auth</span><span class="p">:</span> <span class="p">[]</span><span class="nx">ssh</span><span class="p">.</span><span class="nx">AuthMethod</span><span class="p">{</span> + <span class="nx">ssh</span><span class="p">.</span><span class="nf">Password</span><span class="p">(</span><span class="s">"password"</span><span class="p">),</span> + <span class="p">},</span> + <span class="nx">HostKey</span><span class="p">:</span> <span class="nx">ssh</span><span class="p">.</span><span class="nf">FixedHostKey</span><span class="p">(</span><span class="nx">hostKey</span><span class="p">),</span> + <span class="p">}</span> + <span class="c1">// Connect to ssh server +</span><span class="c1"></span> <span class="nx">conn</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">ssh</span><span class="p">.</span><span class="nf">Dial</span><span class="p">(</span><span class="nx">context</span><span class="p">.</span><span class="nf">Background</span><span class="p">(),</span> <span class="s">"tcp"</span><span class="p">,</span> <span class="s">"localhost:22"</span><span class="p">,</span> <span class="nx">config</span><span class="p">)</span> + <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span> + <span class="nx">log</span><span class="p">.</span><span class="nf">Fatal</span><span class="p">(</span><span class="s">"unable to connect: "</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span> + <span class="p">}</span> + <span class="k">defer</span> <span class="nx">conn</span><span class="p">.</span><span class="nf">Close</span><span class="p">()</span> + <span class="c1">// Create a session +</span><span class="c1"></span> <span class="nx">session</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">conn</span><span class="p">.</span><span class="nf">NewSession</span><span class="p">()</span> + <span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span> + <span class="nx">log</span><span class="p">.</span><span class="nf">Fatal</span><span class="p">(</span><span class="s">"unable to create session: "</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span> + <span class="p">}</span> + <span class="k">defer</span> <span class="nx">session</span><span class="p">.</span><span class="nf">Close</span><span class="p">()</span> + <span class="c1">// Set up terminal modes +</span><span class="c1"></span> <span class="nx">modes</span> <span class="o">:=</span> <span class="nx">ssh</span><span class="p">.</span><span class="nx">TerminalModes</span><span class="p">{</span> + <span class="nx">ssh</span><span class="p">.</span><span class="nx">ECHO</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span> <span class="c1">// disable echoing +</span><span class="c1"></span> <span class="nx">ssh</span><span class="p">.</span><span class="nx">TTY_OP_ISPEED</span><span class="p">:</span> <span class="mi">14400</span><span class="p">,</span> <span class="c1">// input speed = 14.4kbaud +</span><span class="c1"></span> <span class="nx">ssh</span><span class="p">.</span><span class="nx">TTY_OP_OSPEED</span><span class="p">:</span> <span class="mi">14400</span><span class="p">,</span> <span class="c1">// output speed = 14.4kbaud +</span><span class="c1"></span> <span class="p">}</span> + <span class="c1">// Request pseudo terminal +</span><span class="c1"></span> <span class="k">if</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">session</span><span class="p">.</span><span class="nf">RequestPty</span><span class="p">(</span><span class="s">"xterm"</span><span class="p">,</span> <span class="mi">40</span><span class="p">,</span> <span class="mi">80</span><span class="p">,</span> <span class="nx">modes</span><span class="p">);</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span> + <span class="nx">log</span><span class="p">.</span><span class="nf">Fatal</span><span class="p">(</span><span class="s">"request for pseudo terminal failed: "</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span> + <span class="p">}</span> + <span class="c1">// Start remote shell +</span><span class="c1"></span> <span class="k">if</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">session</span><span class="p">.</span><span class="nf">Shell</span><span class="p">();</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span> + <span class="nx">log</span><span class="p">.</span><span class="nf">Fatal</span><span class="p">(</span><span class="s">"failed to start shell: "</span><span class="p">,</span> <span class="nx">err</span><span class="p">)</span> + <span class="p">}</span> +<span class="p">}</span></pre> + </details> + <h4 id="Session.RequestSubsystem">func (*Session) RequestSubsystem</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">s</span> <span class="o">*</span><a href="#Session"><span class="nx">Session</span></a><span class="p">)</span> <span class="nf">RequestSubsystem</span><span class="p">(</span><span class="nx">subsystem</span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a><span class="p">)</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a></pre> + <p>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 +<h4 id="Session.Run">func (*Session) Run</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">s</span> <span class="o">*</span><a href="#Session"><span class="nx">Session</span></a><span class="p">)</span> <span class="nf">Run</span><span class="p">(</span><span class="nx">cmd</span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a><span class="p">)</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a></pre> + <p>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. +<p>The returned error is nil if the command runs, has no problems +copying stdin, stdout, and stderr, and exits with a zero exit +status. +<p>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. +<h4 id="Session.SendRequest">func (*Session) SendRequest</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">s</span> <span class="o">*</span><a href="#Session"><span class="nx">Session</span></a><span class="p">)</span> <span class="nf">SendRequest</span><span class="p">(</span><span class="nx">name</span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a><span class="p">,</span> <span class="nx">wantReply</span> <a href="https://pkg.go.dev/builtin#bool"><span class="kt">bool</span></a><span class="p">,</span> <span class="nx">payload</span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#byte"><span class="kt">byte</span></a><span class="p">)</span> <span class="p">(</span><a href="https://pkg.go.dev/builtin#bool"><span class="kt">bool</span></a><span class="p">,</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a><span class="p">)</span></pre> + <p>SendRequest sends an out-of-band channel request on the SSH channel +underlying the session. +<h4 id="Session.Setenv">func (*Session) Setenv</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">s</span> <span class="o">*</span><a href="#Session"><span class="nx">Session</span></a><span class="p">)</span> <span class="nf">Setenv</span><span class="p">(</span><span class="nx">name</span><span class="p">,</span> <span class="nx">value</span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a><span class="p">)</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a></pre> + <p>Setenv sets an environment variable that will be applied to any +command executed by Shell or Run. +<h4 id="Session.Shell">func (*Session) Shell</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">s</span> <span class="o">*</span><a href="#Session"><span class="nx">Session</span></a><span class="p">)</span> <span class="nf">Shell</span><span class="p">()</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a></pre> + <p>Shell starts a login shell on the remote host. A Session only +accepts one call to Run, Start, Shell, Output, or CombinedOutput. +<h4 id="Session.Signal">func (*Session) Signal</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">s</span> <span class="o">*</span><a href="#Session"><span class="nx">Session</span></a><span class="p">)</span> <span class="nf">Signal</span><span class="p">(</span><span class="nx">sig</span> <a href="#Signal"><span class="nx">Signal</span></a><span class="p">)</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a></pre> + <p>Signal sends the given signal to the remote process. +sig is one of the SIG* constants. +<h4 id="Session.Start">func (*Session) Start</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">s</span> <span class="o">*</span><a href="#Session"><span class="nx">Session</span></a><span class="p">)</span> <span class="nf">Start</span><span class="p">(</span><span class="nx">cmd</span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a><span class="p">)</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a></pre> + <p>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. +<h4 id="Session.StderrPipe">func (*Session) StderrPipe</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">s</span> <span class="o">*</span><a href="#Session"><span class="nx">Session</span></a><span class="p">)</span> <span class="nf">StderrPipe</span><span class="p">()</span> <span class="p">(</span><a href="https://pkg.go.dev/io"><span class="nx">io</span></a><span class="p">.</span><a href="https://pkg.go.dev/io#Reader"><span class="nx">Reader</span></a><span class="p">,</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a><span class="p">)</span></pre> + <p>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. +<h4 id="Session.StdinPipe">func (*Session) StdinPipe</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">s</span> <span class="o">*</span><a href="#Session"><span class="nx">Session</span></a><span class="p">)</span> <span class="nf">StdinPipe</span><span class="p">()</span> <span class="p">(</span><a href="https://pkg.go.dev/io"><span class="nx">io</span></a><span class="p">.</span><a href="https://pkg.go.dev/io#WriteCloser"><span class="nx">WriteCloser</span></a><span class="p">,</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a><span class="p">)</span></pre> + <p>StdinPipe returns a pipe that will be connected to the +remote command's standard input when the command starts. +<h4 id="Session.StdoutPipe">func (*Session) StdoutPipe</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">s</span> <span class="o">*</span><a href="#Session"><span class="nx">Session</span></a><span class="p">)</span> <span class="nf">StdoutPipe</span><span class="p">()</span> <span class="p">(</span><a href="https://pkg.go.dev/io"><span class="nx">io</span></a><span class="p">.</span><a href="https://pkg.go.dev/io#Reader"><span class="nx">Reader</span></a><span class="p">,</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a><span class="p">)</span></pre> + <p>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. +<h4 id="Session.Wait">func (*Session) Wait</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">s</span> <span class="o">*</span><a href="#Session"><span class="nx">Session</span></a><span class="p">)</span> <span class="nf">Wait</span><span class="p">()</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a></pre> + <p>Wait waits for the remote command to exit. +<p>The returned error is nil if the command runs, has no problems +copying stdin, stdout, and stderr, and exits with a zero exit +status. +<p>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. +<h4 id="Session.WindowChange">func (*Session) WindowChange</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">s</span> <span class="o">*</span><a href="#Session"><span class="nx">Session</span></a><span class="p">)</span> <span class="nf">WindowChange</span><span class="p">(</span><span class="nx">h</span><span class="p">,</span> <span class="nx">w</span> <a href="https://pkg.go.dev/builtin#int"><span class="kt">int</span></a><span class="p">)</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a></pre> + <p>WindowChange informs the remote host about a terminal window dimension change to h rows and w columns. +<h3 id="Signal">type Signal</h3> + <pre class="chroma"><span class="kd">type</span> <span class="nx">Signal</span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a></pre> + <pre class="chroma"><span class="kd">const</span> <span class="p">(</span> + <span id="SIGABRT"><span class="nx">SIGABRT</span></span> <a href="#Signal"><span class="nx">Signal</span></a> <span class="p">=</span> <span class="s">"ABRT"</span> + <span id="SIGALRM"><span class="nx">SIGALRM</span></span> <a href="#Signal"><span class="nx">Signal</span></a> <span class="p">=</span> <span class="s">"ALRM"</span> + <span id="SIGFPE"><span class="nx">SIGFPE</span></span> <a href="#Signal"><span class="nx">Signal</span></a> <span class="p">=</span> <span class="s">"FPE"</span> + <span id="SIGHUP"><span class="nx">SIGHUP</span></span> <a href="#Signal"><span class="nx">Signal</span></a> <span class="p">=</span> <span class="s">"HUP"</span> + <span id="SIGILL"><span class="nx">SIGILL</span></span> <a href="#Signal"><span class="nx">Signal</span></a> <span class="p">=</span> <span class="s">"ILL"</span> + <span id="SIGINT"><span class="nx">SIGINT</span></span> <a href="#Signal"><span class="nx">Signal</span></a> <span class="p">=</span> <span class="s">"INT"</span> + <span id="SIGKILL"><span class="nx">SIGKILL</span></span> <a href="#Signal"><span class="nx">Signal</span></a> <span class="p">=</span> <span class="s">"KILL"</span> + <span id="SIGPIPE"><span class="nx">SIGPIPE</span></span> <a href="#Signal"><span class="nx">Signal</span></a> <span class="p">=</span> <span class="s">"PIPE"</span> + <span id="SIGQUIT"><span class="nx">SIGQUIT</span></span> <a href="#Signal"><span class="nx">Signal</span></a> <span class="p">=</span> <span class="s">"QUIT"</span> + <span id="SIGSEGV"><span class="nx">SIGSEGV</span></span> <a href="#Signal"><span class="nx">Signal</span></a> <span class="p">=</span> <span class="s">"SEGV"</span> + <span id="SIGTERM"><span class="nx">SIGTERM</span></span> <a href="#Signal"><span class="nx">Signal</span></a> <span class="p">=</span> <span class="s">"TERM"</span> + <span id="SIGUSR1"><span class="nx">SIGUSR1</span></span> <a href="#Signal"><span class="nx">Signal</span></a> <span class="p">=</span> <span class="s">"USR1"</span> + <span id="SIGUSR2"><span class="nx">SIGUSR2</span></span> <a href="#Signal"><span class="nx">Signal</span></a> <span class="p">=</span> <span class="s">"USR2"</span> +<span class="p">)</span></pre> + <p>POSIX signals as listed in RFC 4254 Section 6.10. +<h3 id="Signature">type Signature</h3> + <pre class="chroma"><span class="kd">type</span> <span class="nx">Signature</span> <span class="kd">struct</span> <span class="p">{</span> + <span id="Signature.Format"><span class="nx">Format</span></span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a> + <span id="Signature.Blob"><span class="nx">Blob</span></span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#byte"><span class="kt">byte</span></a> + <span id="Signature.Rest"><span class="nx">Rest</span></span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#byte"><span class="kt">byte</span></a> <span class="s">`ssh:"rest"`</span> +<span class="p">}</span></pre> + <p>Signature represents a cryptographic signature. +<h3 id="Signer">type Signer</h3> + <pre class="chroma"><span class="kd">type</span> <span class="nx">Signer</span> <span class="kd">interface</span> <span class="p">{</span> + <span class="c1">// PublicKey returns the associated PublicKey. +</span><span class="c1"></span> <span id="Signer.PublicKey"><span class="nf">PublicKey</span></span><span class="p">()</span> <a href="#PublicKey"><span class="nx">PublicKey</span></a> + + <span class="c1">// Sign returns a signature for the given data. This method will hash the +</span><span class="c1"></span> <span class="c1">// data appropriately first. The signature algorithm is expected to match +</span><span class="c1"></span> <span class="c1">// the key format returned by the PublicKey.Type method (and not to be any +</span><span class="c1"></span> <span class="c1">// alternative algorithm supported by the key format). +</span><span class="c1"></span> <span id="Signer.Sign"><span class="nf">Sign</span></span><span class="p">(</span><span class="nx">rand</span> <a href="https://pkg.go.dev/io"><span class="nx">io</span></a><span class="p">.</span><a href="https://pkg.go.dev/io#Reader"><span class="nx">Reader</span></a><span class="p">,</span> <span class="nx">data</span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#byte"><span class="kt">byte</span></a><span class="p">)</span> <span class="p">(</span><span class="o">*</span><a href="#Signature"><span class="nx">Signature</span></a><span class="p">,</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a><span class="p">)</span> + + <span class="c1">// SignWithAlgorithm is like Signer.Sign, but allows specifying a desired +</span><span class="c1"></span> <span class="c1">// signing algorithm. Callers may pass an empty string for the algorithm in +</span><span class="c1"></span> <span class="c1">// which case the AlgorithmSigner will use a default algorithm. This default +</span><span class="c1"></span> <span class="c1">// doesn't currently control any behavior in this package. +</span><span class="c1"></span> <span id="Signer.SignWithAlgorithm"><span class="nf">SignWithAlgorithm</span></span><span class="p">(</span><span class="nx">rand</span> <a href="https://pkg.go.dev/io"><span class="nx">io</span></a><span class="p">.</span><a href="https://pkg.go.dev/io#Reader"><span class="nx">Reader</span></a><span class="p">,</span> <span class="nx">data</span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#byte"><span class="kt">byte</span></a><span class="p">,</span> <span class="nx">algorithm</span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a><span class="p">)</span> <span class="p">(</span><span class="o">*</span><a href="#Signature"><span class="nx">Signature</span></a><span class="p">,</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a><span class="p">)</span> + + <span class="c1">// Algorithms returns the available algorithms in preference order. The list +</span><span class="c1"></span> <span class="c1">// must not be empty, and it must not include certificate types. +</span><span class="c1"></span> <span id="Signer.Algorithms"><span class="nf">Algorithms</span></span><span class="p">()</span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a> +<span class="p">}</span></pre> + <p>A Signer can create signatures that verify against a public key. +<p>Some Signers provided by this package also implement MultiAlgorithmSigner. +<h4 id="NewCertSigner">func NewCertSigner</h4> + <pre class="chroma"><span class="kd">func</span> <span class="nf">NewCertSigner</span><span class="p">(</span><span class="nx">cert</span> <span class="o">*</span><a href="#Certificate"><span class="nx">Certificate</span></a><span class="p">,</span> <span class="nx">signer</span> <a href="#Signer"><span class="nx">Signer</span></a><span class="p">)</span> <span class="p">(</span><a href="#Signer"><span class="nx">Signer</span></a><span class="p">,</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a><span class="p">)</span></pre> + <p>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. +<h4 id="NewSigner">func NewSigner</h4> + <pre class="chroma"><span class="kd">func</span> <span class="nf">NewSigner</span><span class="p">(</span><span class="nx">signer</span> <a href="https://pkg.go.dev/crypto"><span class="nx">crypto</span></a><span class="p">.</span><a href="https://pkg.go.dev/crypto#Signer"><span class="nx">Signer</span></a><span class="p">)</span> <span class="p">(</span><a href="#Signer"><span class="nx">Signer</span></a><span class="p">,</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a><span class="p">)</span></pre> + <p>NewSigner takes any crypto.Signer implementation and returns a corresponding +Signer interface. This can be used, for example, with keys kept in hardware +modules. +<h4 id="NewSignerWithAlgorithms">func NewSignerWithAlgorithms</h4> + <pre class="chroma"><span class="kd">func</span> <span class="nf">NewSignerWithAlgorithms</span><span class="p">(</span><span class="nx">signer</span> <a href="#Signer"><span class="nx">Signer</span></a><span class="p">,</span> <span class="nx">algorithms</span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a><span class="p">)</span> <span class="p">(</span><a href="#Signer"><span class="nx">Signer</span></a><span class="p">,</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a><span class="p">)</span></pre> + <p>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. +<h4 id="ParsePrivateKey">func ParsePrivateKey</h4> + <pre class="chroma"><span class="kd">func</span> <span class="nf">ParsePrivateKey</span><span class="p">(</span><span class="nx">pemBytes</span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#byte"><span class="kt">byte</span></a><span class="p">)</span> <span class="p">(</span><a href="#Signer"><span class="nx">Signer</span></a><span class="p">,</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a><span class="p">)</span></pre> + <p>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. +<h4 id="ParsePrivateKeyWithPassphrase">func ParsePrivateKeyWithPassphrase</h4> + <pre class="chroma"><span class="kd">func</span> <span class="nf">ParsePrivateKeyWithPassphrase</span><span class="p">(</span><span class="nx">pemBytes</span><span class="p">,</span> <span class="nx">passphrase</span> <span class="p">[]</span><a href="https://pkg.go.dev/builtin#byte"><span class="kt">byte</span></a><span class="p">)</span> <span class="p">(</span><a href="#Signer"><span class="nx">Signer</span></a><span class="p">,</span> <a href="https://pkg.go.dev/builtin#error"><span class="kt">error</span></a><span class="p">)</span></pre> + <p>ParsePrivateKeyWithPassphrase returns a Signer from a PEM encoded private +key and passphrase. It supports the same keys as +ParseRawPrivateKeyWithPassphrase. +<h3 id="TerminalModes">type TerminalModes</h3> + <pre class="chroma"><span class="kd">type</span> <span class="nx">TerminalModes</span> <span class="kd">map</span><span class="p">[</span><a href="https://pkg.go.dev/builtin#uint8"><span class="kt">uint8</span></a><span class="p">]</span><a href="https://pkg.go.dev/builtin#uint32"><span class="kt">uint32</span></a></pre> + <h3 id="Waitmsg">type Waitmsg</h3> + <pre class="chroma"><span class="kd">type</span> <span class="nx">Waitmsg</span> <span class="kd">struct</span> <span class="p">{</span> + <span class="c1">// contains filtered or unexported fields +</span><span class="c1"></span><span class="p">}</span></pre> + <p>Waitmsg stores the information about an exited remote command +as reported by Wait. +<h4 id="Waitmsg.ExitStatus">func (Waitmsg) ExitStatus</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">w</span> <a href="#Waitmsg"><span class="nx">Waitmsg</span></a><span class="p">)</span> <span class="nf">ExitStatus</span><span class="p">()</span> <a href="https://pkg.go.dev/builtin#int"><span class="kt">int</span></a></pre> + <p>ExitStatus returns the exit status of the remote command. +<h4 id="Waitmsg.Lang">func (Waitmsg) Lang</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">w</span> <a href="#Waitmsg"><span class="nx">Waitmsg</span></a><span class="p">)</span> <span class="nf">Lang</span><span class="p">()</span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a></pre> + <p>Lang returns the language tag. See RFC 3066 +<h4 id="Waitmsg.Msg">func (Waitmsg) Msg</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">w</span> <a href="#Waitmsg"><span class="nx">Waitmsg</span></a><span class="p">)</span> <span class="nf">Msg</span><span class="p">()</span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a></pre> + <p>Msg returns the exit message given by the remote command +<h4 id="Waitmsg.Signal">func (Waitmsg) Signal</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">w</span> <a href="#Waitmsg"><span class="nx">Waitmsg</span></a><span class="p">)</span> <span class="nf">Signal</span><span class="p">()</span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a></pre> + <p>Signal returns the exit signal of the remote command if +it was terminated violently. +<h4 id="Waitmsg.String">func (Waitmsg) String</h4> + <pre class="chroma"><span class="kd">func</span> <span class="p">(</span><span class="nx">w</span> <a href="#Waitmsg"><span class="nx">Waitmsg</span></a><span class="p">)</span> <span class="nf">String</span><span class="p">()</span> <a href="https://pkg.go.dev/builtin#string"><span class="kt">string</span></a></pre> + <h3 id="pkg-directories">Directories</h3> + +<table> + <tbody> + <tr> + <td><a href="agent/agent.html">agent</a></td> + <td>Package agent implements the ssh-agent protocol, and provides both a client and a server.</td> + </tr> + <tr> + <td><a href="knownhosts/knownhosts.html">knownhosts</a></td> + <td>Package knownhosts implements a parser for the OpenSSH known_hosts host key database, and provides utility functions for writing OpenSSH compliant known_hosts files.</td> + </tr> + </tbody> +</table> +</main> + <hr> + <footer> + <small id="generated-by-footer"> + Generated with <a href="https://abhinav.github.io/doc2go/">doc2go</a> + </small> + </footer> + <script type="text/javascript"> + // If the page was opened with an anchor (e.g. #foo), + // and the destination is a <details> element, open it. + function openDetailsAnchor() { + let hash = window.location.hash + if (!hash) { + return + } + let el = document.getElementById(hash.slice(1)) // remove leading '#' + if (!el) { + return + } + + let details = el.closest("details") + while (details) { + details.open = true + details = details.parentElement.closest("details") + } + + // New elements may have appeared. + // Set hash again to scroll to the right place. + window.location.hash = hash; + return false; + } + + window.addEventListener('hashchange', openDetailsAnchor) + + window.addEventListener('load', () => { + document.querySelectorAll("h2, h3, h4, h5, h6").forEach((el) => { + if (!el.id) { + return + } + el.innerHTML += ' <a class="permalink" href="#' + el.id + '">¶</a>' + }) + + document.querySelectorAll("details.example > summary").forEach((el) => { + let id = el.parentElement.id; + if (!id) { + return + } + el.innerHTML += ' <a class="permalink" href="#' + id + '">¶</a>' + }) + + openDetailsAnchor() + }) + </script> + </body> +</html> |
