Skip to content

Instantly share code, notes, and snippets.

@dojiong
Created October 23, 2012 13:19
Show Gist options
  • Save dojiong/3938689 to your computer and use it in GitHub Desktop.
Save dojiong/3938689 to your computer and use it in GitHub Desktop.
ssh sample
package main
import (
"code.google.com/p/go.crypto/ssh"
"code.google.com/p/go.crypto/ssh/terminal"
"crypto"
"crypto/x509"
"crypto/rsa"
"encoding/pem"
"io"
"os"
"fmt"
"errors"
)
type Password struct {
}
func (pwd *Password) Password(user string) (string, error) {
fmt.Printf("%s's password: ", user)
passwd, err := terminal.ReadPassword(0)
if err != nil {
panic("read password fail: " + err.Error())
}
return string(passwd), nil
}
type Keychain struct {
keys []*rsa.PrivateKey
}
func (kc *Keychain) Key(i int) (key interface{}, err error) {
if i < len(kc.keys) {
return &kc.keys[i].PublicKey, nil
}
return nil, nil
}
func (kc *Keychain) Sign(i int, rand io.Reader, data []byte) (
sig []byte, err error) {
if i >= len(kc.keys) {
return nil, errors.New("no such key")
}
h := crypto.SHA1.New()
h.Write(data)
ds := h.Sum(nil)
return rsa.SignPKCS1v15(rand, kc.keys[i], crypto.SHA1, ds)
}
func (kc *Keychain) AddFile(path string) error {
key, err := readPrivateKey(path)
if err != nil {
return err
}
kc.keys = append(kc.keys, key)
return nil
}
func readPrivateKey(path string) (*rsa.PrivateKey, error) {
file, err := os.Open(path)
if err != nil {
return nil, err
}
stat, err := file.Stat()
if err != nil {
return nil, err
}
buf := make([]byte, stat.Size())
_, err = file.Read(buf)
if err != nil {
return nil, err
}
block, _ := pem.Decode(buf)
return x509.ParsePKCS1PrivateKey(block.Bytes)
}
func getAuths() (auths []ssh.ClientAuth) {
kc := Keychain{}
if err := kc.AddFile(os.ExpandEnv("$HOME/.ssh/id_rsa")); err == nil {
auths = append(auths, ssh.ClientAuthKeyring(&kc))
}
auths = append(auths, ssh.ClientAuthPassword(&Password{}))
return auths
}
func main() {
cfg := ssh.ClientConfig {
User: "user",
Auth: getAuths(),
}
conn, err := ssh.Dial("tcp", "host:22", &cfg)
if err != nil {
fmt.Printf("\n%s\n", err.Error())
return
}
defer conn.Close()
session, err := conn.NewSession()
if err != nil {
panic("get session fail: " + err.Error())
}
defer session.Close()
modes := ssh.TerminalModes{
ssh.ECHO: 0,
}
if err := session.RequestPty("bash", 80, 40, modes); err != nil {
panic("requestpty fail: " + err.Error())
}
stdin, err := session.StdinPipe()
if err != nil {
panic("get stdin fail: "+ err.Error())
}
defer stdin.Close()
stdout, err := session.StdoutPipe()
if err != nil {
panic("get stdout fail: "+ err.Error())
}
if err := session.Shell(); err != nil {
panic("shell fail: " + err.Error())
}
go io.Copy(os.Stdout, stdout)
io.Copy(stdin, os.Stdin)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment