OSDN Git Service

Hulk did something
[bytom/vapor.git] / vendor / golang.org / x / crypto / ssh / example_test.go
1 // Copyright 2011 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 package ssh_test
6
7 import (
8         "bufio"
9         "bytes"
10         "fmt"
11         "io/ioutil"
12         "log"
13         "net"
14         "net/http"
15         "os"
16         "path/filepath"
17         "strings"
18
19         "golang.org/x/crypto/ssh"
20         "golang.org/x/crypto/ssh/terminal"
21 )
22
23 func ExampleNewServerConn() {
24         // Public key authentication is done by comparing
25         // the public key of a received connection
26         // with the entries in the authorized_keys file.
27         authorizedKeysBytes, err := ioutil.ReadFile("authorized_keys")
28         if err != nil {
29                 log.Fatalf("Failed to load authorized_keys, err: %v", err)
30         }
31
32         authorizedKeysMap := map[string]bool{}
33         for len(authorizedKeysBytes) > 0 {
34                 pubKey, _, _, rest, err := ssh.ParseAuthorizedKey(authorizedKeysBytes)
35                 if err != nil {
36                         log.Fatal(err)
37                 }
38
39                 authorizedKeysMap[string(pubKey.Marshal())] = true
40                 authorizedKeysBytes = rest
41         }
42
43         // An SSH server is represented by a ServerConfig, which holds
44         // certificate details and handles authentication of ServerConns.
45         config := &ssh.ServerConfig{
46                 // Remove to disable password auth.
47                 PasswordCallback: func(c ssh.ConnMetadata, pass []byte) (*ssh.Permissions, error) {
48                         // Should use constant-time compare (or better, salt+hash) in
49                         // a production setting.
50                         if c.User() == "testuser" && string(pass) == "tiger" {
51                                 return nil, nil
52                         }
53                         return nil, fmt.Errorf("password rejected for %q", c.User())
54                 },
55
56                 // Remove to disable public key auth.
57                 PublicKeyCallback: func(c ssh.ConnMetadata, pubKey ssh.PublicKey) (*ssh.Permissions, error) {
58                         if authorizedKeysMap[string(pubKey.Marshal())] {
59                                 return &ssh.Permissions{
60                                         // Record the public key used for authentication.
61                                         Extensions: map[string]string{
62                                                 "pubkey-fp": ssh.FingerprintSHA256(pubKey),
63                                         },
64                                 }, nil
65                         }
66                         return nil, fmt.Errorf("unknown public key for %q", c.User())
67                 },
68         }
69
70         privateBytes, err := ioutil.ReadFile("id_rsa")
71         if err != nil {
72                 log.Fatal("Failed to load private key: ", err)
73         }
74
75         private, err := ssh.ParsePrivateKey(privateBytes)
76         if err != nil {
77                 log.Fatal("Failed to parse private key: ", err)
78         }
79
80         config.AddHostKey(private)
81
82         // Once a ServerConfig has been configured, connections can be
83         // accepted.
84         listener, err := net.Listen("tcp", "0.0.0.0:2022")
85         if err != nil {
86                 log.Fatal("failed to listen for connection: ", err)
87         }
88         nConn, err := listener.Accept()
89         if err != nil {
90                 log.Fatal("failed to accept incoming connection: ", err)
91         }
92
93         // Before use, a handshake must be performed on the incoming
94         // net.Conn.
95         conn, chans, reqs, err := ssh.NewServerConn(nConn, config)
96         if err != nil {
97                 log.Fatal("failed to handshake: ", err)
98         }
99         log.Printf("logged in with key %s", conn.Permissions.Extensions["pubkey-fp"])
100
101         // The incoming Request channel must be serviced.
102         go ssh.DiscardRequests(reqs)
103
104         // Service the incoming Channel channel.
105         for newChannel := range chans {
106                 // Channels have a type, depending on the application level
107                 // protocol intended. In the case of a shell, the type is
108                 // "session" and ServerShell may be used to present a simple
109                 // terminal interface.
110                 if newChannel.ChannelType() != "session" {
111                         newChannel.Reject(ssh.UnknownChannelType, "unknown channel type")
112                         continue
113                 }
114                 channel, requests, err := newChannel.Accept()
115                 if err != nil {
116                         log.Fatalf("Could not accept channel: %v", err)
117                 }
118
119                 // Sessions have out-of-band requests such as "shell",
120                 // "pty-req" and "env".  Here we handle only the
121                 // "shell" request.
122                 go func(in <-chan *ssh.Request) {
123                         for req := range in {
124                                 req.Reply(req.Type == "shell", nil)
125                         }
126                 }(requests)
127
128                 term := terminal.NewTerminal(channel, "> ")
129
130                 go func() {
131                         defer channel.Close()
132                         for {
133                                 line, err := term.ReadLine()
134                                 if err != nil {
135                                         break
136                                 }
137                                 fmt.Println(line)
138                         }
139                 }()
140         }
141 }
142
143 func ExampleHostKeyCheck() {
144         // Every client must provide a host key check.  Here is a
145         // simple-minded parse of OpenSSH's known_hosts file
146         host := "hostname"
147         file, err := os.Open(filepath.Join(os.Getenv("HOME"), ".ssh", "known_hosts"))
148         if err != nil {
149                 log.Fatal(err)
150         }
151         defer file.Close()
152
153         scanner := bufio.NewScanner(file)
154         var hostKey ssh.PublicKey
155         for scanner.Scan() {
156                 fields := strings.Split(scanner.Text(), " ")
157                 if len(fields) != 3 {
158                         continue
159                 }
160                 if strings.Contains(fields[0], host) {
161                         var err error
162                         hostKey, _, _, _, err = ssh.ParseAuthorizedKey(scanner.Bytes())
163                         if err != nil {
164                                 log.Fatalf("error parsing %q: %v", fields[2], err)
165                         }
166                         break
167                 }
168         }
169
170         if hostKey == nil {
171                 log.Fatalf("no hostkey for %s", host)
172         }
173
174         config := ssh.ClientConfig{
175                 User:            os.Getenv("USER"),
176                 HostKeyCallback: ssh.FixedHostKey(hostKey),
177         }
178
179         _, err = ssh.Dial("tcp", host+":22", &config)
180         log.Println(err)
181 }
182
183 func ExampleDial() {
184         var hostKey ssh.PublicKey
185         // An SSH client is represented with a ClientConn.
186         //
187         // To authenticate with the remote server you must pass at least one
188         // implementation of AuthMethod via the Auth field in ClientConfig,
189         // and provide a HostKeyCallback.
190         config := &ssh.ClientConfig{
191                 User: "username",
192                 Auth: []ssh.AuthMethod{
193                         ssh.Password("yourpassword"),
194                 },
195                 HostKeyCallback: ssh.FixedHostKey(hostKey),
196         }
197         client, err := ssh.Dial("tcp", "yourserver.com:22", config)
198         if err != nil {
199                 log.Fatal("Failed to dial: ", err)
200         }
201
202         // Each ClientConn can support multiple interactive sessions,
203         // represented by a Session.
204         session, err := client.NewSession()
205         if err != nil {
206                 log.Fatal("Failed to create session: ", err)
207         }
208         defer session.Close()
209
210         // Once a Session is created, you can execute a single command on
211         // the remote side using the Run method.
212         var b bytes.Buffer
213         session.Stdout = &b
214         if err := session.Run("/usr/bin/whoami"); err != nil {
215                 log.Fatal("Failed to run: " + err.Error())
216         }
217         fmt.Println(b.String())
218 }
219
220 func ExamplePublicKeys() {
221         var hostKey ssh.PublicKey
222         // A public key may be used to authenticate against the remote
223         // server by using an unencrypted PEM-encoded private key file.
224         //
225         // If you have an encrypted private key, the crypto/x509 package
226         // can be used to decrypt it.
227         key, err := ioutil.ReadFile("/home/user/.ssh/id_rsa")
228         if err != nil {
229                 log.Fatalf("unable to read private key: %v", err)
230         }
231
232         // Create the Signer for this private key.
233         signer, err := ssh.ParsePrivateKey(key)
234         if err != nil {
235                 log.Fatalf("unable to parse private key: %v", err)
236         }
237
238         config := &ssh.ClientConfig{
239                 User: "user",
240                 Auth: []ssh.AuthMethod{
241                         // Use the PublicKeys method for remote authentication.
242                         ssh.PublicKeys(signer),
243                 },
244                 HostKeyCallback: ssh.FixedHostKey(hostKey),
245         }
246
247         // Connect to the remote server and perform the SSH handshake.
248         client, err := ssh.Dial("tcp", "host.com:22", config)
249         if err != nil {
250                 log.Fatalf("unable to connect: %v", err)
251         }
252         defer client.Close()
253 }
254
255 func ExampleClient_Listen() {
256         var hostKey ssh.PublicKey
257         config := &ssh.ClientConfig{
258                 User: "username",
259                 Auth: []ssh.AuthMethod{
260                         ssh.Password("password"),
261                 },
262                 HostKeyCallback: ssh.FixedHostKey(hostKey),
263         }
264         // Dial your ssh server.
265         conn, err := ssh.Dial("tcp", "localhost:22", config)
266         if err != nil {
267                 log.Fatal("unable to connect: ", err)
268         }
269         defer conn.Close()
270
271         // Request the remote side to open port 8080 on all interfaces.
272         l, err := conn.Listen("tcp", "0.0.0.0:8080")
273         if err != nil {
274                 log.Fatal("unable to register tcp forward: ", err)
275         }
276         defer l.Close()
277
278         // Serve HTTP with your SSH server acting as a reverse proxy.
279         http.Serve(l, http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
280                 fmt.Fprintf(resp, "Hello world!\n")
281         }))
282 }
283
284 func ExampleSession_RequestPty() {
285         var hostKey ssh.PublicKey
286         // Create client config
287         config := &ssh.ClientConfig{
288                 User: "username",
289                 Auth: []ssh.AuthMethod{
290                         ssh.Password("password"),
291                 },
292                 HostKeyCallback: ssh.FixedHostKey(hostKey),
293         }
294         // Connect to ssh server
295         conn, err := ssh.Dial("tcp", "localhost:22", config)
296         if err != nil {
297                 log.Fatal("unable to connect: ", err)
298         }
299         defer conn.Close()
300         // Create a session
301         session, err := conn.NewSession()
302         if err != nil {
303                 log.Fatal("unable to create session: ", err)
304         }
305         defer session.Close()
306         // Set up terminal modes
307         modes := ssh.TerminalModes{
308                 ssh.ECHO:          0,     // disable echoing
309                 ssh.TTY_OP_ISPEED: 14400, // input speed = 14.4kbaud
310                 ssh.TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud
311         }
312         // Request pseudo terminal
313         if err := session.RequestPty("xterm", 40, 80, modes); err != nil {
314                 log.Fatal("request for pseudo terminal failed: ", err)
315         }
316         // Start remote shell
317         if err := session.Shell(); err != nil {
318                 log.Fatal("failed to start shell: ", err)
319         }
320 }