// Copyright 2011 The Go Authors. All rights reserved.// Use of this source code is governed by a BSD-style// license that can be found in the LICENSE file.package sshimport ()// Client implements a traditional SSH client that supports shells,// subprocesses, TCP port/streamlocal forwarding and tunneled dialing.typeClientstruct {Conn handleForwardsOnce sync.Once// guards calling (*Client).handleForwards forwards forwardList// forwarded tcpip connections from the remote side mu sync.Mutex channelHandlers map[string]chanNewChannel}// HandleChannelOpen returns a channel on which NewChannel requests// for the given type are sent. If the type already is being handled,// nil is returned. The channel is closed when the connection is closed.func ( *Client) ( string) <-chanNewChannel { .mu.Lock()defer .mu.Unlock()if .channelHandlers == nil {// The SSH channel has been closed. := make(chanNewChannel)close()return } := .channelHandlers[]if != nil {returnnil } = make(chanNewChannel, chanSize) .channelHandlers[] = return}// NewClient creates a Client on top of the given connection.func ( Conn, <-chanNewChannel, <-chan *Request) *Client { := &Client{Conn: ,channelHandlers: make(map[string]chanNewChannel, 1), }go .handleGlobalRequests()go .handleChannelOpens()gofunc() { .Wait() .forwards.closeAll() }()return}// NewClientConn establishes an authenticated SSH connection using c// as the underlying transport. The Request and NewChannel channels// must be serviced or the connection will hang.func ( net.Conn, string, *ClientConfig) (Conn, <-chanNewChannel, <-chan *Request, error) { := * .SetDefaults()if .HostKeyCallback == nil { .Close()returnnil, nil, nil, errors.New("ssh: must specify HostKeyCallback") } := &connection{sshConn: sshConn{conn: , user: .User}, }if := .clientHandshake(, &); != nil { .Close()returnnil, nil, nil, fmt.Errorf("ssh: handshake failed: %v", ) } .mux = newMux(.transport)return , .mux.incomingChannels, .mux.incomingRequests, nil}// clientHandshake performs the client side key exchange. See RFC 4253 Section// 7.func ( *connection) ( string, *ClientConfig) error {if .ClientVersion != "" { .clientVersion = []byte(.ClientVersion) } else { .clientVersion = []byte(packageVersion) }varerror .serverVersion, = exchangeVersions(.sshConn.conn, .clientVersion)if != nil {return } .transport = newClientTransport(newTransport(.sshConn.conn, .Rand, true/* is client */), .clientVersion, .serverVersion, , , .sshConn.RemoteAddr())if := .transport.waitSession(); != nil {return } .sessionID = .transport.getSessionID()return .clientAuthenticate()}// verifyHostKeySignature verifies the host key obtained in the key exchange.// algo is the negotiated algorithm, and may be a certificate type.func verifyHostKeySignature( PublicKey, string, *kexResult) error { , , := parseSignatureBody(.Signature)iflen() > 0 || ! {returnerrors.New("ssh: signature parse error") }if := underlyingAlgo(); .Format != {returnfmt.Errorf("ssh: invalid signature algorithm %q, expected %q", .Format, ) }return .Verify(.H, )}// NewSession opens a new Session for this client. (A session is a remote// execution of a program.)func ( *Client) () (*Session, error) { , , := .OpenChannel("session", nil)if != nil {returnnil, }returnnewSession(, )}func ( *Client) ( <-chan *Request) {for := range {// This handles keepalive messages and matches // the behaviour of OpenSSH. .Reply(false, nil) }}// handleChannelOpens channel open messages from the remote side.func ( *Client) ( <-chanNewChannel) {for := range { .mu.Lock() := .channelHandlers[.ChannelType()] .mu.Unlock()if != nil { <- } else { .Reject(UnknownChannelType, fmt.Sprintf("unknown channel type: %v", .ChannelType())) } } .mu.Lock()for , := range .channelHandlers {close() } .channelHandlers = nil .mu.Unlock()}// 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.func (, string, *ClientConfig) (*Client, error) { , := net.DialTimeout(, , .Timeout)if != nil {returnnil, } , , , := NewClientConn(, , )if != nil {returnnil, }returnNewClient(, , ), nil}// 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.typeHostKeyCallbackfunc(hostname string, remote net.Addr, key PublicKey) error// BannerCallback is the function type used for treat the banner sent by// the server. A BannerCallback receives the message sent by the remote server.typeBannerCallbackfunc(message string) error// A ClientConfig structure is used to configure a Client. It must not be// modified after having been passed to an SSH function.typeClientConfigstruct {// Config contains configuration that is shared between clients and // servers.Config// User contains the username to authenticate as. User string// Auth contains possible authentication methods to use with the // server. Only the first instance of a particular RFC 4252 method will // be used during authentication. Auth []AuthMethod// HostKeyCallback is called during the cryptographic // handshake to validate the server's host key. The client // configuration must supply this callback for the connection // to succeed. The functions InsecureIgnoreHostKey or // FixedHostKey can be used for simplistic host key checks. HostKeyCallback HostKeyCallback// BannerCallback is called during the SSH dance to display a custom // server's message. The client configuration can supply this callback to // handle it as wished. The function BannerDisplayStderr can be used for // simplistic display on Stderr. BannerCallback BannerCallback// ClientVersion contains the version identification string that will // be used for the connection. If empty, a reasonable default is used. ClientVersion string// HostKeyAlgorithms lists the public key algorithms that the client will // accept from the server for host key authentication, in order of // preference. If empty, a reasonable default is used. Any // string returned from a PublicKey.Type method may be used, or // any of the CertAlgo and KeyAlgo constants. HostKeyAlgorithms []string// Timeout is the maximum amount of time for the TCP connection to establish. // // A Timeout of zero means no timeout. Timeout time.Duration}// InsecureIgnoreHostKey returns a function that can be used for// ClientConfig.HostKeyCallback to accept any host key. It should// not be used for production code.func () HostKeyCallback {returnfunc( string, net.Addr, PublicKey) error {returnnil }}type fixedHostKey struct { key PublicKey}func ( *fixedHostKey) ( string, net.Addr, PublicKey) error {if .key == nil {returnfmt.Errorf("ssh: required host key was nil") }if !bytes.Equal(.Marshal(), .key.Marshal()) {returnfmt.Errorf("ssh: host key mismatch") }returnnil}// FixedHostKey returns a function for use in// ClientConfig.HostKeyCallback to accept only a specific host key.func ( PublicKey) HostKeyCallback { := &fixedHostKey{}return .check}// BannerDisplayStderr returns a function that can be used for// ClientConfig.BannerCallback to display banners on os.Stderr.func () BannerCallback {returnfunc( string) error { , := os.Stderr.WriteString()return }}
The pages are generated with Goldsv0.6.7. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds.