Skip to content

Instantly share code, notes, and snippets.

@kelseyhightower
Last active July 5, 2018 05:20
Show Gist options
  • Save kelseyhightower/6191348 to your computer and use it in GitHub Desktop.
Save kelseyhightower/6191348 to your computer and use it in GitHub Desktop.
go.crypto/ssh example
package main
import (
"bytes"
"code.google.com/p/go.crypto/ssh"
"code.google.com/p/go.crypto/ssh/terminal"
"crypto"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"errors"
"fmt"
"io"
"io/ioutil"
"log"
"os"
)
var (
server = "127.0.0.1"
username = "kelsey"
)
type keyring struct {
keys []*rsa.PrivateKey
}
func (k *keyring) Key(i int) (interface{}, error) {
if i < 0 || i >= len(k.keys) {
return nil, nil
}
return &k.keys[i].PublicKey, nil
}
func (k *keyring) Sign(i int, rand io.Reader, data []byte) (sig []byte, err error) {
hashFunc := crypto.SHA1
h := hashFunc.New()
h.Write(data)
digest := h.Sum(nil)
return rsa.SignPKCS1v15(rand, k.keys[i], hashFunc, digest)
}
func (k *keyring) loadPEM(file string) error {
buf, err := ioutil.ReadFile(file)
if err != nil {
return err
}
block, _ := pem.Decode(buf)
if block == nil {
return errors.New("ssh: no key found")
}
var key []byte
if x509.IsEncryptedPEMBlock(block) {
fmt.Print("passpharase: ")
fd := os.Stdin.Fd()
pass, _ := terminal.ReadPassword(fd)
fmt.Println("")
key, _ = x509.DecryptPEMBlock(block, pass)
} else {
key = block.Bytes
}
r, err := x509.ParsePKCS1PrivateKey(key)
if err != nil {
return err
}
k.keys = append(k.keys, r)
return nil
}
type TerminalModes map[uint8]uint32
func main() {
k := new(keyring)
err := k.loadPEM("/tmp/id_rsa")
if err != nil {
panic(err)
}
config := &ssh.ClientConfig{
User: username,
Auth: []ssh.ClientAuth{
ssh.ClientAuthKeyring(k),
},
}
client, err := ssh.Dial("tcp", "127.0.0.1", config)
if err != nil {
panic("Failed to dail: " + err.Error())
}
defer client.Close()
session, err := client.NewSession()
if err != nil {
log.Fatalf("unable to create session: %s", err)
}
defer session.Close()
modes := ssh.TerminalModes{
ssh.ECHO: 0,
ssh.TTY_OP_ISPEED: 14400,
ssh.TTY_OP_OSPEED: 14400,
}
if err := session.RequestPty("xterm", 80, 40, modes); err != nil {
log.Fatalf("request for pseudo terminal failed: %s", err)
}
var b bytes.Buffer
session.Stdout = &b
if err := session.Run("machine -a"); err != nil {
panic("Failed to run: " + err.Error())
}
fmt.Println(b.String())
}
@kelseyhightower
Copy link
Author

This fails with:

# command-line-arguments
./ssh.go:58: cannot use fd (type uintptr) as type int in function argument

Quickly looking through the standard library, seems are fd's are uintptr vs in.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment