github.com/devops-filetransfer/sshego@v7.0.4+incompatible/_vendor/golang.org/x/crypto/ssh/example_test.go (about) 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 nil, nil 60 } 61 return nil, fmt.Errorf("unknown public key for %q", c.User()) 62 }, 63 } 64 65 privateBytes, err := ioutil.ReadFile("id_rsa") 66 if err != nil { 67 log.Fatal("Failed to load private key: ", err) 68 } 69 70 private, err := ssh.ParsePrivateKey(privateBytes) 71 if err != nil { 72 log.Fatal("Failed to parse private key: ", err) 73 } 74 75 config.AddHostKey(private) 76 77 // Once a ServerConfig has been configured, connections can be 78 // accepted. 79 listener, err := net.Listen("tcp", "0.0.0.0:2022") 80 if err != nil { 81 log.Fatal("failed to listen for connection: ", err) 82 } 83 nConn, err := listener.Accept() 84 if err != nil { 85 log.Fatal("failed to accept incoming connection: ", err) 86 } 87 88 // Before use, a handshake must be performed on the incoming 89 // net.Conn. 90 _, chans, reqs, err := ssh.NewServerConn(nConn, config) 91 if err != nil { 92 log.Fatal("failed to handshake: ", err) 93 } 94 // The incoming Request channel must be serviced. 95 go ssh.DiscardRequests(reqs) 96 97 // Service the incoming Channel channel. 98 for newChannel := range chans { 99 // Channels have a type, depending on the application level 100 // protocol intended. In the case of a shell, the type is 101 // "session" and ServerShell may be used to present a simple 102 // terminal interface. 103 if newChannel.ChannelType() != "session" { 104 newChannel.Reject(ssh.UnknownChannelType, "unknown channel type") 105 continue 106 } 107 channel, requests, err := newChannel.Accept() 108 if err != nil { 109 log.Fatalf("Could not accept channel: %v", err) 110 } 111 112 // Sessions have out-of-band requests such as "shell", 113 // "pty-req" and "env". Here we handle only the 114 // "shell" request. 115 go func(in <-chan *ssh.Request) { 116 for req := range in { 117 req.Reply(req.Type == "shell", nil) 118 } 119 }(requests) 120 121 term := terminal.NewTerminal(channel, "> ") 122 123 go func() { 124 defer channel.Close() 125 for { 126 line, err := term.ReadLine() 127 if err != nil { 128 break 129 } 130 fmt.Println(line) 131 } 132 }() 133 } 134 } 135 136 func ExampleHostKeyCheck() { 137 // Every client must provide a host key check. Here is a 138 // simple-minded parse of OpenSSH's known_hosts file 139 host := "hostname" 140 file, err := os.Open(filepath.Join(os.Getenv("HOME"), ".ssh", "known_hosts")) 141 if err != nil { 142 log.Fatal(err) 143 } 144 defer file.Close() 145 146 scanner := bufio.NewScanner(file) 147 var hostKey ssh.PublicKey 148 for scanner.Scan() { 149 fields := strings.Split(scanner.Text(), " ") 150 if len(fields) != 3 { 151 continue 152 } 153 if strings.Contains(fields[0], host) { 154 var err error 155 hostKey, _, _, _, err = ssh.ParseAuthorizedKey(scanner.Bytes()) 156 if err != nil { 157 log.Fatalf("error parsing %q: %v", fields[2], err) 158 } 159 break 160 } 161 } 162 163 if hostKey == nil { 164 log.Fatalf("no hostkey for %s", host) 165 } 166 167 config := ssh.ClientConfig{ 168 User: os.Getenv("USER"), 169 HostKeyCallback: ssh.FixedHostKey(hostKey), 170 } 171 172 _, err = ssh.Dial("tcp", host+":22", &config) 173 log.Println(err) 174 } 175 176 func ExampleDial() { 177 var hostKey ssh.PublicKey 178 // An SSH client is represented with a ClientConn. 179 // 180 // To authenticate with the remote server you must pass at least one 181 // implementation of AuthMethod via the Auth field in ClientConfig, 182 // and provide a HostKeyCallback. 183 config := &ssh.ClientConfig{ 184 User: "username", 185 Auth: []ssh.AuthMethod{ 186 ssh.Password("yourpassword"), 187 }, 188 HostKeyCallback: ssh.FixedHostKey(hostKey), 189 } 190 client, err := ssh.Dial("tcp", "yourserver.com:22", config) 191 if err != nil { 192 log.Fatal("Failed to dial: ", err) 193 } 194 195 // Each ClientConn can support multiple interactive sessions, 196 // represented by a Session. 197 session, err := client.NewSession() 198 if err != nil { 199 log.Fatal("Failed to create session: ", err) 200 } 201 defer session.Close() 202 203 // Once a Session is created, you can execute a single command on 204 // the remote side using the Run method. 205 var b bytes.Buffer 206 session.Stdout = &b 207 if err := session.Run("/usr/bin/whoami"); err != nil { 208 log.Fatal("Failed to run: " + err.Error()) 209 } 210 fmt.Println(b.String()) 211 } 212 213 func ExamplePublicKeys() { 214 var hostKey ssh.PublicKey 215 // A public key may be used to authenticate against the remote 216 // server by using an unencrypted PEM-encoded private key file. 217 // 218 // If you have an encrypted private key, the crypto/x509 package 219 // can be used to decrypt it. 220 key, err := ioutil.ReadFile("/home/user/.ssh/id_rsa") 221 if err != nil { 222 log.Fatalf("unable to read private key: %v", err) 223 } 224 225 // Create the Signer for this private key. 226 signer, err := ssh.ParsePrivateKey(key) 227 if err != nil { 228 log.Fatalf("unable to parse private key: %v", err) 229 } 230 231 config := &ssh.ClientConfig{ 232 User: "user", 233 Auth: []ssh.AuthMethod{ 234 // Use the PublicKeys method for remote authentication. 235 ssh.PublicKeys(signer), 236 }, 237 HostKeyCallback: ssh.FixedHostKey(hostKey), 238 } 239 240 // Connect to the remote server and perform the SSH handshake. 241 client, err := ssh.Dial("tcp", "host.com:22", config) 242 if err != nil { 243 log.Fatalf("unable to connect: %v", err) 244 } 245 defer client.Close() 246 } 247 248 func ExampleClient_Listen() { 249 var hostKey ssh.PublicKey 250 config := &ssh.ClientConfig{ 251 User: "username", 252 Auth: []ssh.AuthMethod{ 253 ssh.Password("password"), 254 }, 255 HostKeyCallback: ssh.FixedHostKey(hostKey), 256 } 257 // Dial your ssh server. 258 conn, err := ssh.Dial("tcp", "localhost:22", config) 259 if err != nil { 260 log.Fatal("unable to connect: ", err) 261 } 262 defer conn.Close() 263 264 // Request the remote side to open port 8080 on all interfaces. 265 l, err := conn.Listen("tcp", "0.0.0.0:8080") 266 if err != nil { 267 log.Fatal("unable to register tcp forward: ", err) 268 } 269 defer l.Close() 270 271 // Serve HTTP with your SSH server acting as a reverse proxy. 272 http.Serve(l, http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { 273 fmt.Fprintf(resp, "Hello world!\n") 274 })) 275 } 276 277 func ExampleSession_RequestPty() { 278 var hostKey ssh.PublicKey 279 // Create client config 280 config := &ssh.ClientConfig{ 281 User: "username", 282 Auth: []ssh.AuthMethod{ 283 ssh.Password("password"), 284 }, 285 HostKeyCallback: ssh.FixedHostKey(hostKey), 286 } 287 // Connect to ssh server 288 conn, err := ssh.Dial("tcp", "localhost:22", config) 289 if err != nil { 290 log.Fatal("unable to connect: ", err) 291 } 292 defer conn.Close() 293 // Create a session 294 session, err := conn.NewSession() 295 if err != nil { 296 log.Fatal("unable to create session: ", err) 297 } 298 defer session.Close() 299 // Set up terminal modes 300 modes := ssh.TerminalModes{ 301 ssh.ECHO: 0, // disable echoing 302 ssh.TTY_OP_ISPEED: 14400, // input speed = 14.4kbaud 303 ssh.TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud 304 } 305 // Request pseudo terminal 306 if err := session.RequestPty("xterm", 40, 80, modes); err != nil { 307 log.Fatal("request for pseudo terminal failed: ", err) 308 } 309 // Start remote shell 310 if err := session.Shell(); err != nil { 311 log.Fatal("failed to start shell: ", err) 312 } 313 }