diff --git a/example-ssh/Makefile b/example-ssh/Makefile index ac0151f..35f6334 100644 --- a/example-ssh/Makefile +++ b/example-ssh/Makefile @@ -1,2 +1,5 @@ -all: +scp: + go run scp.go + +ps: go run ssh-ed25519.go diff --git a/example-ssh/scp.go b/example-ssh/scp.go new file mode 100644 index 0000000..c19f144 --- /dev/null +++ b/example-ssh/scp.go @@ -0,0 +1,132 @@ +package main + +import "bufio" +import "log" +import "fmt" +import "os" +import "os/user" +import "io/ioutil" +import "path/filepath" +import "strings" +import "time" + +import "golang.org/x/crypto/ssh" +import "github.com/tmc/scp" + +func main() { + + host := "mirrors.wit.com" + port := "22" + username := "jcarr" + pass := "tryme" + // cmd := "ps" + + // get host public key + // hostKey := getHostKey(host) + // log.Println("hostkey =", hostKey) + + user, _ := user.Current() + + publicKey, err := PublicKeyFile(user.HomeDir + "/.ssh/id_ed25519") + if (err != nil) { + log.Println("PublicKeyFile() error =", err) + } + + // ssh client config + config := ssh.ClientConfig{ + User: username, + Auth: []ssh.AuthMethod{ + ssh.Password(pass), + publicKey, + }, + // allow any host key to be used (non-prod) + HostKeyCallback: ssh.InsecureIgnoreHostKey(), + + // verify host public key + // HostKeyCallback: ssh.FixedHostKey(hostKey), + // optional host key algo list + HostKeyAlgorithms: []string{ + ssh.KeyAlgoRSA, + ssh.KeyAlgoDSA, + ssh.KeyAlgoECDSA256, + ssh.KeyAlgoECDSA384, + ssh.KeyAlgoECDSA521, + ssh.KeyAlgoED25519, + }, + // optional tcp connect timeout + Timeout: 5 * time.Second, + } + + // connect + client, err := ssh.Dial("tcp", host+":"+port, &config) + if err != nil { + log.Fatal(err) + } + defer client.Close() + + // start session + sess, err := client.NewSession() + if err != nil { + log.Fatal(err) + } + defer sess.Close() + + f, _ := ioutil.TempFile("", "") + fmt.Fprintln(f, "hello world") + f.Close() + dest := f.Name() + "-copy" + err = scp.CopyPath(f.Name(), dest, sess) + log.Println("scp.CopyPath() err =", err) +} + +func getHostKey(host string) ssh.PublicKey { + // parse OpenSSH known_hosts file + // ssh or use ssh-keyscan to get initial key + file, err := os.Open(filepath.Join(os.Getenv("HOME"), ".ssh", "known_hosts")) + if err != nil { + log.Fatal(err) + } + defer file.Close() + + scanner := bufio.NewScanner(file) + var hostKey ssh.PublicKey + for scanner.Scan() { + fields := strings.Split(scanner.Text(), " ") + if len(fields) != 3 { + continue + } + if strings.Contains(fields[0], host) { + var err error + hostKey, _, _, _, err = ssh.ParseAuthorizedKey(scanner.Bytes()) + if err != nil { + log.Fatalf("error parsing %q: %v", fields[2], err) + } + break + } + } + + // 9enFJdMhb8eHN/6qfHSU/jww2Mo=|pcsWQCvAyve9QXBhjL+w/LhkcHU= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBMQx8BJXxD+vk3wyjy7Irzw4FA6xxJvqUP7Hb+Z+ygpOuidYj9G8x6gHEXFUnABn5YirePrWh5tNsk4Rqs48VwU= + hostKey, _, _, _, err = ssh.ParseAuthorizedKey([]byte("9enFJdMhb8eHN/6qfHSU/jww2Mo=|pcsWQCvAyve9QXBhjL+w/LhkcHU= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBMQx8BJXxD+vk3wyjy7Irzw4FA6xxJvqUP7Hb+Z+ygpOuidYj9G8x6gHEXFUnABn5YirePrWh5tNsk4Rqs48VwU=")) + log.Println("hostkey err =", err) + log.Println("hostkey =", hostKey) + if hostKey == nil { + log.Println("no hostkey found err =", err) + log.Fatalf("no hostkey found for %s", host) + } + + return hostKey +} + +func PublicKeyFile(file string) (ssh.AuthMethod, error) { + buffer, err := ioutil.ReadFile(file) + log.Println("buffer =", string(buffer)) + if err != nil { + return nil, err + } + + key, err := ssh.ParsePrivateKey(buffer) + if err != nil { + return nil, err + } + return ssh.PublicKeys(key), nil +}