github.com/mvdan/u-root-coreutils@v0.0.0-20230122170626-c2eef2898555/cmds/exp/ssh/ssh_test.go (about)

     1  // Copyright 2022 the u-root 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 main
     6  
     7  import (
     8  	"crypto/rand"
     9  	"crypto/rsa"
    10  	"crypto/x509"
    11  	"encoding/pem"
    12  	"io"
    13  	"io/ioutil"
    14  	"log"
    15  	"os"
    16  	guser "os/user"
    17  	"path/filepath"
    18  	"strings"
    19  	"testing"
    20  )
    21  
    22  type destTest struct {
    23  	input string
    24  	user  string
    25  	host  string
    26  	port  string
    27  }
    28  
    29  var destTests = []destTest{
    30  	{"example.org", "", "example.org", "22"},
    31  	{"foo@example.org", "foo", "example.org", "22"},
    32  	{"foo@example.org", "foo", "example.org", "22"},
    33  	{"ssh://192.168.0.2:23", "", "192.168.0.2", "23"},
    34  	{"ssh://x@example.org", "x", "example.org", "22"},
    35  }
    36  
    37  func TestParseDest(t *testing.T) {
    38  	for _, x := range destTests {
    39  		if x.user == "" {
    40  			var u *guser.User
    41  			u, _ = guser.Current()
    42  			x.user = u.Username
    43  		}
    44  		user, host, port, err := parseDest(x.input)
    45  		if err != nil {
    46  			t.Fatal(err)
    47  		}
    48  		if user != x.user || host != x.host || port != x.port {
    49  			t.Fatalf("failed on %v: got %v, %v, %v", x, user, host, port)
    50  		}
    51  	}
    52  }
    53  
    54  // Load a config file and ask for the keyfile for a host in it
    55  // By populating a real file & reading it, we get to test loadConfig too
    56  func TestGetKeyFile(t *testing.T) {
    57  	dir := t.TempDir()
    58  	confPath := filepath.Join(dir, "sshconfig")
    59  	conf := []byte(`Host foo
    60  	IdentityFile bar_key`)
    61  	if err := ioutil.WriteFile(confPath, conf, 0600); err != nil {
    62  		t.Fatal(err)
    63  	}
    64  	if err := loadConfig(confPath); err != nil {
    65  		t.Fatal(err)
    66  	}
    67  	if kf := getKeyFile("foo", ""); kf != "bar_key" {
    68  		t.Fatalf(`getKeyFile("foo", "") = %v, want "bar_key"`, kf)
    69  	}
    70  }
    71  
    72  // Test what happens if we pass invalid command-line arguments... should
    73  // return errInvalidArgs
    74  func TestBadArgs(t *testing.T) {
    75  	if err := run([]string{"sshtest"}, os.Stdin, io.Discard, io.Discard); err != errInvalidArgs {
    76  		t.Fatalf(`run(["sshtest"], ...) = %v, want %v`, err, errInvalidArgs)
    77  	}
    78  }
    79  
    80  // This attempts to connect to git@github.com and run a command. It will fail but that's ok.
    81  // TODO: restore this test, but first we need to add better support for locating known_hosts files with this in it:
    82  // github.com,140.82.121.4 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl
    83  func TestSshCommand(t *testing.T) {
    84  	t.Skipf("Skipping for now, until we can relocate the known_hosts file")
    85  	kf := genPrivKey(t)
    86  	if err := run([]string{"sshtest", "-i", kf, "git@github.com", "pwd"}, os.Stdin, io.Discard, io.Discard); err == nil || !strings.Contains(err.Error(), "unable to connect") {
    87  		t.Fatalf(`run(["sshtest"], ...) = %v, want "...unable to connect..."`, err)
    88  	}
    89  }
    90  
    91  // This attempts to connect to git@github.com and start a shell. It will fail but that's ok.
    92  func TestSshShell(t *testing.T) {
    93  	t.Skipf("Skipping for now, until we can relocate the known_hosts file")
    94  	kf := genPrivKey(t)
    95  	if err := run([]string{"sshtest", "-i", kf, "git@github.com"}, os.Stdin, io.Discard, io.Discard); err == nil || !strings.Contains(err.Error(), "unable to connect") {
    96  		t.Fatalf(`run(["sshtest"], ...) = %v, want "...unable to connect..."`, err)
    97  	}
    98  }
    99  
   100  // returns the path containing a private key
   101  func genPrivKey(t *testing.T) string {
   102  	priv, err := rsa.GenerateKey(rand.Reader, 2048)
   103  	if err != nil {
   104  		t.Fatal(err)
   105  	}
   106  	// Trying to throw off simple-minded scanners looking for key files
   107  	x := "PRIVATE"
   108  	block := &pem.Block{
   109  		Type:  "RSA " + x + " KEY",
   110  		Bytes: x509.MarshalPKCS1PrivateKey(priv),
   111  	}
   112  
   113  	dir := t.TempDir()
   114  	kf := filepath.Join(dir, "kf")
   115  	f, err := os.OpenFile(kf, os.O_RDWR|os.O_CREATE, 0600)
   116  	if err != nil {
   117  		t.Fatal(err)
   118  	}
   119  	if err := pem.Encode(f, block); err != nil {
   120  		log.Fatal(err)
   121  	}
   122  	return kf
   123  }