1
2
3
4
5 package ssh_test
6
7 import (
8 "bufio"
9 "bytes"
10 "crypto/rand"
11 "crypto/rsa"
12 "fmt"
13 "log"
14 "net"
15 "net/http"
16 "os"
17 "path/filepath"
18 "strings"
19 "sync"
20
21 "golang.org/x/crypto/ssh"
22 "golang.org/x/crypto/ssh/terminal"
23 )
24
25 func ExampleNewServerConn() {
26
27
28
29 authorizedKeysBytes, err := os.ReadFile("authorized_keys")
30 if err != nil {
31 log.Fatalf("Failed to load authorized_keys, err: %v", err)
32 }
33
34 authorizedKeysMap := map[string]bool{}
35 for len(authorizedKeysBytes) > 0 {
36 pubKey, _, _, rest, err := ssh.ParseAuthorizedKey(authorizedKeysBytes)
37 if err != nil {
38 log.Fatal(err)
39 }
40
41 authorizedKeysMap[string(pubKey.Marshal())] = true
42 authorizedKeysBytes = rest
43 }
44
45
46
47 config := &ssh.ServerConfig{
48
49 PasswordCallback: func(c ssh.ConnMetadata, pass []byte) (*ssh.Permissions, error) {
50
51
52 if c.User() == "testuser" && string(pass) == "tiger" {
53 return nil, nil
54 }
55 return nil, fmt.Errorf("password rejected for %q", c.User())
56 },
57
58
59 PublicKeyCallback: func(c ssh.ConnMetadata, pubKey ssh.PublicKey) (*ssh.Permissions, error) {
60 if authorizedKeysMap[string(pubKey.Marshal())] {
61 return &ssh.Permissions{
62
63 Extensions: map[string]string{
64 "pubkey-fp": ssh.FingerprintSHA256(pubKey),
65 },
66 }, nil
67 }
68 return nil, fmt.Errorf("unknown public key for %q", c.User())
69 },
70 }
71
72 privateBytes, err := os.ReadFile("id_rsa")
73 if err != nil {
74 log.Fatal("Failed to load private key: ", err)
75 }
76
77 private, err := ssh.ParsePrivateKey(privateBytes)
78 if err != nil {
79 log.Fatal("Failed to parse private key: ", err)
80 }
81 config.AddHostKey(private)
82
83
84
85 listener, err := net.Listen("tcp", "0.0.0.0:2022")
86 if err != nil {
87 log.Fatal("failed to listen for connection: ", err)
88 }
89 nConn, err := listener.Accept()
90 if err != nil {
91 log.Fatal("failed to accept incoming connection: ", err)
92 }
93
94
95
96 conn, chans, reqs, err := ssh.NewServerConn(nConn, config)
97 if err != nil {
98 log.Fatal("failed to handshake: ", err)
99 }
100 log.Printf("logged in with key %s", conn.Permissions.Extensions["pubkey-fp"])
101
102 var wg sync.WaitGroup
103 defer wg.Wait()
104
105
106 wg.Add(1)
107 go func() {
108 ssh.DiscardRequests(reqs)
109 wg.Done()
110 }()
111
112
113 for newChannel := range chans {
114
115
116
117
118 if newChannel.ChannelType() != "session" {
119 newChannel.Reject(ssh.UnknownChannelType, "unknown channel type")
120 continue
121 }
122 channel, requests, err := newChannel.Accept()
123 if err != nil {
124 log.Fatalf("Could not accept channel: %v", err)
125 }
126
127
128
129
130 wg.Add(1)
131 go func(in <-chan *ssh.Request) {
132 for req := range in {
133 req.Reply(req.Type == "shell", nil)
134 }
135 wg.Done()
136 }(requests)
137
138 term := terminal.NewTerminal(channel, "> ")
139
140 wg.Add(1)
141 go func() {
142 defer func() {
143 channel.Close()
144 wg.Done()
145 }()
146 for {
147 line, err := term.ReadLine()
148 if err != nil {
149 break
150 }
151 fmt.Println(line)
152 }
153 }()
154 }
155 }
156
157 func ExampleServerConfig_AddHostKey() {
158
159 config := &ssh.ServerConfig{
160 PasswordCallback: func(c ssh.ConnMetadata, pass []byte) (*ssh.Permissions, error) {
161
162
163 if c.User() == "testuser" && string(pass) == "tiger" {
164 return nil, nil
165 }
166 return nil, fmt.Errorf("password rejected for %q", c.User())
167 },
168 }
169
170 privateBytes, err := os.ReadFile("id_rsa")
171 if err != nil {
172 log.Fatal("Failed to load private key: ", err)
173 }
174
175 private, err := ssh.ParsePrivateKey(privateBytes)
176 if err != nil {
177 log.Fatal("Failed to parse private key: ", err)
178 }
179
180 signer, err := ssh.NewSignerWithAlgorithms(private.(ssh.AlgorithmSigner), []string{ssh.KeyAlgoRSASHA256, ssh.KeyAlgoRSASHA512})
181 if err != nil {
182 log.Fatal("Failed to create private key with restricted algorithms: ", err)
183 }
184 config.AddHostKey(signer)
185 }
186
187 func ExampleClientConfig_HostKeyCallback() {
188
189
190 host := "hostname"
191 file, err := os.Open(filepath.Join(os.Getenv("HOME"), ".ssh", "known_hosts"))
192 if err != nil {
193 log.Fatal(err)
194 }
195 defer file.Close()
196
197 scanner := bufio.NewScanner(file)
198 var hostKey ssh.PublicKey
199 for scanner.Scan() {
200 fields := strings.Split(scanner.Text(), " ")
201 if len(fields) != 3 {
202 continue
203 }
204 if strings.Contains(fields[0], host) {
205 var err error
206 hostKey, _, _, _, err = ssh.ParseAuthorizedKey(scanner.Bytes())
207 if err != nil {
208 log.Fatalf("error parsing %q: %v", fields[2], err)
209 }
210 break
211 }
212 }
213
214 if hostKey == nil {
215 log.Fatalf("no hostkey for %s", host)
216 }
217
218 config := ssh.ClientConfig{
219 User: os.Getenv("USER"),
220 HostKeyCallback: ssh.FixedHostKey(hostKey),
221 }
222
223 _, err = ssh.Dial("tcp", host+":22", &config)
224 log.Println(err)
225 }
226
227 func ExampleDial() {
228 var hostKey ssh.PublicKey
229
230
231
232
233
234 config := &ssh.ClientConfig{
235 User: "username",
236 Auth: []ssh.AuthMethod{
237 ssh.Password("yourpassword"),
238 },
239 HostKeyCallback: ssh.FixedHostKey(hostKey),
240 }
241 client, err := ssh.Dial("tcp", "yourserver.com:22", config)
242 if err != nil {
243 log.Fatal("Failed to dial: ", err)
244 }
245 defer client.Close()
246
247
248
249 session, err := client.NewSession()
250 if err != nil {
251 log.Fatal("Failed to create session: ", err)
252 }
253 defer session.Close()
254
255
256
257 var b bytes.Buffer
258 session.Stdout = &b
259 if err := session.Run("/usr/bin/whoami"); err != nil {
260 log.Fatal("Failed to run: " + err.Error())
261 }
262 fmt.Println(b.String())
263 }
264
265 func ExamplePublicKeys() {
266 var hostKey ssh.PublicKey
267
268
269
270
271
272 key, err := os.ReadFile("/home/user/.ssh/id_rsa")
273 if err != nil {
274 log.Fatalf("unable to read private key: %v", err)
275 }
276
277
278 signer, err := ssh.ParsePrivateKey(key)
279 if err != nil {
280 log.Fatalf("unable to parse private key: %v", err)
281 }
282
283 config := &ssh.ClientConfig{
284 User: "user",
285 Auth: []ssh.AuthMethod{
286
287 ssh.PublicKeys(signer),
288 },
289 HostKeyCallback: ssh.FixedHostKey(hostKey),
290 }
291
292
293 client, err := ssh.Dial("tcp", "host.com:22", config)
294 if err != nil {
295 log.Fatalf("unable to connect: %v", err)
296 }
297 defer client.Close()
298 }
299
300 func ExampleClient_Listen() {
301 var hostKey ssh.PublicKey
302 config := &ssh.ClientConfig{
303 User: "username",
304 Auth: []ssh.AuthMethod{
305 ssh.Password("password"),
306 },
307 HostKeyCallback: ssh.FixedHostKey(hostKey),
308 }
309
310 conn, err := ssh.Dial("tcp", "localhost:22", config)
311 if err != nil {
312 log.Fatal("unable to connect: ", err)
313 }
314 defer conn.Close()
315
316
317 l, err := conn.Listen("tcp", "0.0.0.0:8080")
318 if err != nil {
319 log.Fatal("unable to register tcp forward: ", err)
320 }
321 defer l.Close()
322
323
324 http.Serve(l, http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
325 fmt.Fprintf(resp, "Hello world!\n")
326 }))
327 }
328
329 func ExampleSession_RequestPty() {
330 var hostKey ssh.PublicKey
331
332 config := &ssh.ClientConfig{
333 User: "username",
334 Auth: []ssh.AuthMethod{
335 ssh.Password("password"),
336 },
337 HostKeyCallback: ssh.FixedHostKey(hostKey),
338 }
339
340 conn, err := ssh.Dial("tcp", "localhost:22", config)
341 if err != nil {
342 log.Fatal("unable to connect: ", err)
343 }
344 defer conn.Close()
345
346 session, err := conn.NewSession()
347 if err != nil {
348 log.Fatal("unable to create session: ", err)
349 }
350 defer session.Close()
351
352 modes := ssh.TerminalModes{
353 ssh.ECHO: 0,
354 ssh.TTY_OP_ISPEED: 14400,
355 ssh.TTY_OP_OSPEED: 14400,
356 }
357
358 if err := session.RequestPty("xterm", 40, 80, modes); err != nil {
359 log.Fatal("request for pseudo terminal failed: ", err)
360 }
361
362 if err := session.Shell(); err != nil {
363 log.Fatal("failed to start shell: ", err)
364 }
365 }
366
367 func ExampleCertificate_SignCert() {
368
369 privateKey, err := rsa.GenerateKey(rand.Reader, 3072)
370 if err != nil {
371 log.Fatal("unable to generate RSA key: ", err)
372 }
373 publicKey, err := ssh.NewPublicKey(&privateKey.PublicKey)
374 if err != nil {
375 log.Fatal("unable to get RSA public key: ", err)
376 }
377 caKey, err := rsa.GenerateKey(rand.Reader, 3072)
378 if err != nil {
379 log.Fatal("unable to generate CA key: ", err)
380 }
381 signer, err := ssh.NewSignerFromKey(caKey)
382 if err != nil {
383 log.Fatal("unable to generate signer from key: ", err)
384 }
385 mas, err := ssh.NewSignerWithAlgorithms(signer.(ssh.AlgorithmSigner), []string{ssh.KeyAlgoRSASHA256})
386 if err != nil {
387 log.Fatal("unable to create signer with algoritms: ", err)
388 }
389 certificate := ssh.Certificate{
390 Key: publicKey,
391 CertType: ssh.UserCert,
392 }
393 if err := certificate.SignCert(rand.Reader, mas); err != nil {
394 log.Fatal("unable to sign certificate: ", err)
395 }
396
397
398
399 fmt.Println(string(ssh.MarshalAuthorizedKey(&certificate)))
400 }
401
View as plain text