Working prototype using RO as a remote Signer for SSH authentication

This commit is contained in:
Andrew Buss
2018-03-12 12:39:32 -07:00
committed by Kyle Isom
parent 5b9a4b2fcb
commit a45f80f613
3 changed files with 241 additions and 5 deletions
+128
View File
@@ -0,0 +1,128 @@
package roagent
import (
"bytes"
"crypto/rand"
"encoding/json"
"errors"
"fmt"
"io"
"log"
"github.com/cloudflare/redoctober/client"
"github.com/cloudflare/redoctober/core"
"golang.org/x/crypto/ssh"
"golang.org/x/crypto/ssh/agent"
)
type ROSigner struct {
server *client.RemoteServer
pub ssh.PublicKey
encryptedKey []byte
user string
pswd string
}
func (signer ROSigner) PublicKey() ssh.PublicKey {
return signer.pub
}
func (signer ROSigner) Sign(rand io.Reader, msg []byte) (signature *ssh.Signature, err error) {
req := core.DecryptSignRequest{
Name: signer.user,
Password: signer.pswd,
Data: signer.encryptedKey,
TBSData: msg,
}
resp, err := signer.server.DecryptSign(req)
if err != nil {
return nil, err
}
if resp.Status != "ok" {
log.Fatal("response status error:", resp.Status)
return nil, errors.New("response status error")
}
fmt.Println("Response Status:", resp.Status)
var respMsg core.DecryptSignWithDelegates
err = json.Unmarshal(resp.Response, &respMsg)
if err != nil {
return nil, err
}
var respSignature ssh.Signature
err = json.Unmarshal(resp.Response, &respSignature)
if err != nil {
return nil, err
}
return &respSignature, nil
}
type ROAgent struct {
signer ROSigner
}
func NewROAgent(server *client.RemoteServer, pubKey ssh.PublicKey, encryptedPrivKey []byte, user, pswd string) agent.Agent {
return &ROAgent{
ROSigner{
server,
pubKey,
encryptedPrivKey,
user,
pswd,
},
}
}
func (r *ROAgent) RemoveAll() error {
return nil
}
// Remove removes all identities with the given public key.
func (r *ROAgent) Remove(key ssh.PublicKey) error {
return nil
}
// Lock locks the agent. Sign and Remove will fail, and List will empty an empty list.
func (r *ROAgent) Lock(passphrase []byte) error {
return nil
}
// Unlock undoes the effect of Lock
func (r *ROAgent) Unlock(passphrase []byte) error {
return nil
}
// List returns the identities known to the agent.
func (r *ROAgent) List() ([]*agent.Key, error) {
return []*agent.Key{
{
Format: r.signer.PublicKey().Type(),
Blob: r.signer.PublicKey().Marshal(),
Comment: "",
},
}, nil
}
// Insert adds a private key to the ROAgent. If a certificate
// is given, that certificate is added as public key. Note that
// any constraints given are ignored.
func (r *ROAgent) Add(key agent.AddedKey) error {
return nil
}
// Sign returns a signature for the data.
func (r *ROAgent) Sign(key ssh.PublicKey, data []byte) (*ssh.Signature, error) {
wanted := key.Marshal()
if bytes.Equal(r.signer.PublicKey().Marshal(), wanted) {
return r.signer.Sign(rand.Reader, data)
}
return nil, errors.New("wrong key requested")
}
// Signers returns signers for all the known keys.
func (r *ROAgent) Signers() ([]ssh.Signer, error) {
return []ssh.Signer{r.signer}, nil
}