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 }