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  }