-
-
Save csobankesmarki/61250bee4016d2966fc64bcfeb6f71ca to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"crypto" | |
"fmt" | |
"os" | |
"os/signal" | |
"syscall" | |
"github.com/ThalesIgnite/crypto11" | |
"github.com/miekg/pkcs11" | |
"golang.org/x/crypto/ssh" | |
"golang.org/x/crypto/ssh/terminal" | |
) | |
where ( | |
// ↓ These two need to be specified | |
pkcs11Path = "/usr/local/lib/opensc-pkcs11.so" | |
tokenLabel = "tokenLabel" | |
// The key ID is fixed. (It corresponds to "01" when it is output by p11tool) | |
// If you want to get it automatically, you can get it by specifying it with "pkcs11.NewAttribute". | |
// ↓ Sample | |
// ------ | |
// findTemplate := []*pkcs11.Attribute{ | |
// pkcs11.NewAttribute(pkcs11.CKA_CLASS, pkcs11.CKO_PRIVATE_KEY), | |
// pkcs11.NewAttribute(pkcs11.CKA_PRIVATE, true), | |
// pkcs11.NewAttribute(pkcs11.CKA_ID, true), | |
// pkcs11.NewAttribute(pkcs11.CKA_KEY_TYPE, pkcs11.CKK_RSA), | |
// } | |
// p.FindObjectsInit(session, findTemplate) | |
// ------ | |
keyID = []byte{'\x01'} | |
// ssh connection information | |
host = "target.host" | |
port = "22" | |
user = "user" | |
) | |
func main() { | |
// Accept PIN code input | |
fmt.Printf("PIN: ") | |
tokenPin, err := terminal.ReadPassword(int(syscall.Stdin)) | |
if err != nil { | |
fmt.Println("err: {}", err) | |
os.Exit (1) | |
} | |
// Create pkcs11 Config | |
config := &crypto11.PKCS11Config{ | |
Path: pkcs11Path, | |
TokenLabel: tokenLabel, | |
Pin: string(tokenPin), | |
} | |
// Create ctx using pkcs11 Config | |
ctx, err := crypto11.Configure(config) | |
if err != nil { | |
fmt.Println("err: {}", err) | |
os.Exit (1) | |
} | |
// Create a session for pkcs11 | |
keysession, err := ctx.OpenSession(0, pkcs11.CKF_SERIAL_SESSION) | |
if err != nil { | |
fmt.Println("err: {}", err) | |
os.Exit (1) | |
} | |
pkcs11Session := &crypto11.PKCS11Session{ctx, keysession} | |
// Create a PIV Signer (slot, id are fixed) | |
prv, err := crypto11.FindKeyPairOnSession(pkcs11Session, 0, keyID, nil) | |
if err != nil { | |
fmt.Println("err: {}", err) | |
os.Exit (1) | |
} | |
signer := prv.(crypto.Signer) | |
// Create a Signer for ssh from the PIV Signer | |
sshSigner, err := ssh.NewSignerFromSigner(signer) | |
if err != nil { | |
fmt.Println("err: {}", err) | |
os.Exit (1) | |
} | |
auth := []ssh.AuthMethod{} | |
auth = append(auth, ssh.PublicKeys(sshSigner)) | |
// --------------------- | |
// | |
// Below is the copy and paste guy | |
// | |
// --------------------- | |
// Create sshClientConfig | |
sshConfig := &ssh.ClientConfig{ | |
User: user, | |
Auth: auth, | |
HostKeyCallback: ssh.InsecureIgnoreHostKey(), | |
BannerCallback: ssh.BannerDisplayStderr(), | |
} | |
// SSH connect. | |
client, err := ssh.Dial("tcp", host+":"+port, sshConfig) | |
if err != nil { | |
fmt.Println("client: {}", err) | |
os.Exit (0) | |
} | |
// Create Session | |
session, err := client.NewSession() | |
defer session.Close() | |
// Convert the key input to a format that the connection destination can recognize (this is the key) | |
fd := int(os.Stdin.Fd()) | |
state, err := terminal.MakeRaw(fd) | |
if err != nil { | |
fmt.Println(err) | |
} | |
defer terminal.Restore(fd, state) | |
// Get terminal size | |
w, h, err := terminal.GetSize(fd) | |
if err != nil { | |
fmt.Println(err) | |
} | |
modes := ssh.TerminalModes{ | |
ssh.ECHO: 1, | |
ssh.TTY_OP_ISPEED: 14400, | |
ssh.TTY_OP_OSPEED: 14400, | |
} | |
err = session.RequestPty("xterm", h, w, modes) | |
if err != nil { | |
fmt.Println(err) | |
} | |
session.Stdout = os.Stdout | |
session.Stderr = os.Stderr | |
session.Stdin = os.Stdin | |
err = session.Shell() | |
if err != nil { | |
fmt.Println(err) | |
} | |
// Terminal size change detection / processing | |
signal_chan := make(chan os.Signal, 1) | |
signal.Notify(signal_chan, syscall.SIGWINCH) | |
go func() { | |
for { | |
s := <-signal_chan | |
switch s { | |
case syscall.SIGWINCH: | |
fd := int(os.Stdout.Fd()) | |
w, h, _ = terminal.GetSize(fd) | |
session.WindowChange(h, w) | |
} | |
} | |
}() | |
err = session.Wait() | |
if err != nil { | |
fmt.Println(err) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment