Switch to using the dep tool and update all the dependencies
This commit is contained in:
+1
-1
@@ -9,7 +9,7 @@
|
||||
//
|
||||
// References:
|
||||
// [PROTOCOL.agent]: http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.agent?rev=HEAD
|
||||
package agent
|
||||
package agent // import "golang.org/x/crypto/ssh/agent"
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
+348
@@ -0,0 +1,348 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package agent
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"errors"
|
||||
"net"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
// startAgent executes ssh-agent, and returns a Agent interface to it.
|
||||
func startAgent(t *testing.T) (client Agent, socket string, cleanup func()) {
|
||||
if testing.Short() {
|
||||
// ssh-agent is not always available, and the key
|
||||
// types supported vary by platform.
|
||||
t.Skip("skipping test due to -short")
|
||||
}
|
||||
|
||||
bin, err := exec.LookPath("ssh-agent")
|
||||
if err != nil {
|
||||
t.Skip("could not find ssh-agent")
|
||||
}
|
||||
|
||||
cmd := exec.Command(bin, "-s")
|
||||
out, err := cmd.Output()
|
||||
if err != nil {
|
||||
t.Fatalf("cmd.Output: %v", err)
|
||||
}
|
||||
|
||||
/* Output looks like:
|
||||
|
||||
SSH_AUTH_SOCK=/tmp/ssh-P65gpcqArqvH/agent.15541; export SSH_AUTH_SOCK;
|
||||
SSH_AGENT_PID=15542; export SSH_AGENT_PID;
|
||||
echo Agent pid 15542;
|
||||
*/
|
||||
fields := bytes.Split(out, []byte(";"))
|
||||
line := bytes.SplitN(fields[0], []byte("="), 2)
|
||||
line[0] = bytes.TrimLeft(line[0], "\n")
|
||||
if string(line[0]) != "SSH_AUTH_SOCK" {
|
||||
t.Fatalf("could not find key SSH_AUTH_SOCK in %q", fields[0])
|
||||
}
|
||||
socket = string(line[1])
|
||||
|
||||
line = bytes.SplitN(fields[2], []byte("="), 2)
|
||||
line[0] = bytes.TrimLeft(line[0], "\n")
|
||||
if string(line[0]) != "SSH_AGENT_PID" {
|
||||
t.Fatalf("could not find key SSH_AGENT_PID in %q", fields[2])
|
||||
}
|
||||
pidStr := line[1]
|
||||
pid, err := strconv.Atoi(string(pidStr))
|
||||
if err != nil {
|
||||
t.Fatalf("Atoi(%q): %v", pidStr, err)
|
||||
}
|
||||
|
||||
conn, err := net.Dial("unix", string(socket))
|
||||
if err != nil {
|
||||
t.Fatalf("net.Dial: %v", err)
|
||||
}
|
||||
|
||||
ac := NewClient(conn)
|
||||
return ac, socket, func() {
|
||||
proc, _ := os.FindProcess(pid)
|
||||
if proc != nil {
|
||||
proc.Kill()
|
||||
}
|
||||
conn.Close()
|
||||
os.RemoveAll(filepath.Dir(socket))
|
||||
}
|
||||
}
|
||||
|
||||
func testAgent(t *testing.T, key interface{}, cert *ssh.Certificate, lifetimeSecs uint32) {
|
||||
agent, _, cleanup := startAgent(t)
|
||||
defer cleanup()
|
||||
|
||||
testAgentInterface(t, agent, key, cert, lifetimeSecs)
|
||||
}
|
||||
|
||||
func testKeyring(t *testing.T, key interface{}, cert *ssh.Certificate, lifetimeSecs uint32) {
|
||||
a := NewKeyring()
|
||||
testAgentInterface(t, a, key, cert, lifetimeSecs)
|
||||
}
|
||||
|
||||
func testAgentInterface(t *testing.T, agent Agent, key interface{}, cert *ssh.Certificate, lifetimeSecs uint32) {
|
||||
signer, err := ssh.NewSignerFromKey(key)
|
||||
if err != nil {
|
||||
t.Fatalf("NewSignerFromKey(%T): %v", key, err)
|
||||
}
|
||||
// The agent should start up empty.
|
||||
if keys, err := agent.List(); err != nil {
|
||||
t.Fatalf("RequestIdentities: %v", err)
|
||||
} else if len(keys) > 0 {
|
||||
t.Fatalf("got %d keys, want 0: %v", len(keys), keys)
|
||||
}
|
||||
|
||||
// Attempt to insert the key, with certificate if specified.
|
||||
var pubKey ssh.PublicKey
|
||||
if cert != nil {
|
||||
err = agent.Add(AddedKey{
|
||||
PrivateKey: key,
|
||||
Certificate: cert,
|
||||
Comment: "comment",
|
||||
LifetimeSecs: lifetimeSecs,
|
||||
})
|
||||
pubKey = cert
|
||||
} else {
|
||||
err = agent.Add(AddedKey{PrivateKey: key, Comment: "comment", LifetimeSecs: lifetimeSecs})
|
||||
pubKey = signer.PublicKey()
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("insert(%T): %v", key, err)
|
||||
}
|
||||
|
||||
// Did the key get inserted successfully?
|
||||
if keys, err := agent.List(); err != nil {
|
||||
t.Fatalf("List: %v", err)
|
||||
} else if len(keys) != 1 {
|
||||
t.Fatalf("got %v, want 1 key", keys)
|
||||
} else if keys[0].Comment != "comment" {
|
||||
t.Fatalf("key comment: got %v, want %v", keys[0].Comment, "comment")
|
||||
} else if !bytes.Equal(keys[0].Blob, pubKey.Marshal()) {
|
||||
t.Fatalf("key mismatch")
|
||||
}
|
||||
|
||||
// Can the agent make a valid signature?
|
||||
data := []byte("hello")
|
||||
sig, err := agent.Sign(pubKey, data)
|
||||
if err != nil {
|
||||
t.Fatalf("Sign(%s): %v", pubKey.Type(), err)
|
||||
}
|
||||
|
||||
if err := pubKey.Verify(data, sig); err != nil {
|
||||
t.Fatalf("Verify(%s): %v", pubKey.Type(), err)
|
||||
}
|
||||
|
||||
// If the key has a lifetime, is it removed when it should be?
|
||||
if lifetimeSecs > 0 {
|
||||
time.Sleep(time.Second*time.Duration(lifetimeSecs) + 100*time.Millisecond)
|
||||
keys, err := agent.List()
|
||||
if err != nil {
|
||||
t.Fatalf("List: %v", err)
|
||||
}
|
||||
if len(keys) > 0 {
|
||||
t.Fatalf("key not expired")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestAgent(t *testing.T) {
|
||||
for _, keyType := range []string{"rsa", "dsa", "ecdsa", "ed25519"} {
|
||||
testAgent(t, testPrivateKeys[keyType], nil, 0)
|
||||
testKeyring(t, testPrivateKeys[keyType], nil, 1)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCert(t *testing.T) {
|
||||
cert := &ssh.Certificate{
|
||||
Key: testPublicKeys["rsa"],
|
||||
ValidBefore: ssh.CertTimeInfinity,
|
||||
CertType: ssh.UserCert,
|
||||
}
|
||||
cert.SignCert(rand.Reader, testSigners["ecdsa"])
|
||||
|
||||
testAgent(t, testPrivateKeys["rsa"], cert, 0)
|
||||
testKeyring(t, testPrivateKeys["rsa"], cert, 1)
|
||||
}
|
||||
|
||||
// netPipe is analogous to net.Pipe, but it uses a real net.Conn, and
|
||||
// therefore is buffered (net.Pipe deadlocks if both sides start with
|
||||
// a write.)
|
||||
func netPipe() (net.Conn, net.Conn, error) {
|
||||
listener, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
if err != nil {
|
||||
listener, err = net.Listen("tcp", "[::1]:0")
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
defer listener.Close()
|
||||
c1, err := net.Dial("tcp", listener.Addr().String())
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
c2, err := listener.Accept()
|
||||
if err != nil {
|
||||
c1.Close()
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return c1, c2, nil
|
||||
}
|
||||
|
||||
func TestAuth(t *testing.T) {
|
||||
agent, _, cleanup := startAgent(t)
|
||||
defer cleanup()
|
||||
|
||||
a, b, err := netPipe()
|
||||
if err != nil {
|
||||
t.Fatalf("netPipe: %v", err)
|
||||
}
|
||||
|
||||
defer a.Close()
|
||||
defer b.Close()
|
||||
|
||||
if err := agent.Add(AddedKey{PrivateKey: testPrivateKeys["rsa"], Comment: "comment"}); err != nil {
|
||||
t.Errorf("Add: %v", err)
|
||||
}
|
||||
|
||||
serverConf := ssh.ServerConfig{}
|
||||
serverConf.AddHostKey(testSigners["rsa"])
|
||||
serverConf.PublicKeyCallback = func(c ssh.ConnMetadata, key ssh.PublicKey) (*ssh.Permissions, error) {
|
||||
if bytes.Equal(key.Marshal(), testPublicKeys["rsa"].Marshal()) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return nil, errors.New("pubkey rejected")
|
||||
}
|
||||
|
||||
go func() {
|
||||
conn, _, _, err := ssh.NewServerConn(a, &serverConf)
|
||||
if err != nil {
|
||||
t.Fatalf("Server: %v", err)
|
||||
}
|
||||
conn.Close()
|
||||
}()
|
||||
|
||||
conf := ssh.ClientConfig{
|
||||
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
|
||||
}
|
||||
conf.Auth = append(conf.Auth, ssh.PublicKeysCallback(agent.Signers))
|
||||
conn, _, _, err := ssh.NewClientConn(b, "", &conf)
|
||||
if err != nil {
|
||||
t.Fatalf("NewClientConn: %v", err)
|
||||
}
|
||||
conn.Close()
|
||||
}
|
||||
|
||||
func TestLockClient(t *testing.T) {
|
||||
agent, _, cleanup := startAgent(t)
|
||||
defer cleanup()
|
||||
testLockAgent(agent, t)
|
||||
}
|
||||
|
||||
func testLockAgent(agent Agent, t *testing.T) {
|
||||
if err := agent.Add(AddedKey{PrivateKey: testPrivateKeys["rsa"], Comment: "comment 1"}); err != nil {
|
||||
t.Errorf("Add: %v", err)
|
||||
}
|
||||
if err := agent.Add(AddedKey{PrivateKey: testPrivateKeys["dsa"], Comment: "comment dsa"}); err != nil {
|
||||
t.Errorf("Add: %v", err)
|
||||
}
|
||||
if keys, err := agent.List(); err != nil {
|
||||
t.Errorf("List: %v", err)
|
||||
} else if len(keys) != 2 {
|
||||
t.Errorf("Want 2 keys, got %v", keys)
|
||||
}
|
||||
|
||||
passphrase := []byte("secret")
|
||||
if err := agent.Lock(passphrase); err != nil {
|
||||
t.Errorf("Lock: %v", err)
|
||||
}
|
||||
|
||||
if keys, err := agent.List(); err != nil {
|
||||
t.Errorf("List: %v", err)
|
||||
} else if len(keys) != 0 {
|
||||
t.Errorf("Want 0 keys, got %v", keys)
|
||||
}
|
||||
|
||||
signer, _ := ssh.NewSignerFromKey(testPrivateKeys["rsa"])
|
||||
if _, err := agent.Sign(signer.PublicKey(), []byte("hello")); err == nil {
|
||||
t.Fatalf("Sign did not fail")
|
||||
}
|
||||
|
||||
if err := agent.Remove(signer.PublicKey()); err == nil {
|
||||
t.Fatalf("Remove did not fail")
|
||||
}
|
||||
|
||||
if err := agent.RemoveAll(); err == nil {
|
||||
t.Fatalf("RemoveAll did not fail")
|
||||
}
|
||||
|
||||
if err := agent.Unlock(nil); err == nil {
|
||||
t.Errorf("Unlock with wrong passphrase succeeded")
|
||||
}
|
||||
if err := agent.Unlock(passphrase); err != nil {
|
||||
t.Errorf("Unlock: %v", err)
|
||||
}
|
||||
|
||||
if err := agent.Remove(signer.PublicKey()); err != nil {
|
||||
t.Fatalf("Remove: %v", err)
|
||||
}
|
||||
|
||||
if keys, err := agent.List(); err != nil {
|
||||
t.Errorf("List: %v", err)
|
||||
} else if len(keys) != 1 {
|
||||
t.Errorf("Want 1 keys, got %v", keys)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAgentLifetime(t *testing.T) {
|
||||
agent, _, cleanup := startAgent(t)
|
||||
defer cleanup()
|
||||
|
||||
for _, keyType := range []string{"rsa", "dsa", "ecdsa"} {
|
||||
// Add private keys to the agent.
|
||||
err := agent.Add(AddedKey{
|
||||
PrivateKey: testPrivateKeys[keyType],
|
||||
Comment: "comment",
|
||||
LifetimeSecs: 1,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("add: %v", err)
|
||||
}
|
||||
// Add certs to the agent.
|
||||
cert := &ssh.Certificate{
|
||||
Key: testPublicKeys[keyType],
|
||||
ValidBefore: ssh.CertTimeInfinity,
|
||||
CertType: ssh.UserCert,
|
||||
}
|
||||
cert.SignCert(rand.Reader, testSigners[keyType])
|
||||
err = agent.Add(AddedKey{
|
||||
PrivateKey: testPrivateKeys[keyType],
|
||||
Certificate: cert,
|
||||
Comment: "comment",
|
||||
LifetimeSecs: 1,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("add: %v", err)
|
||||
}
|
||||
}
|
||||
time.Sleep(1100 * time.Millisecond)
|
||||
if keys, err := agent.List(); err != nil {
|
||||
t.Errorf("List: %v", err)
|
||||
} else if len(keys) != 0 {
|
||||
t.Errorf("Want 0 keys, got %v", len(keys))
|
||||
}
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
// Copyright 2016 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package agent_test
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net"
|
||||
"os"
|
||||
|
||||
"golang.org/x/crypto/ssh"
|
||||
"golang.org/x/crypto/ssh/agent"
|
||||
)
|
||||
|
||||
func ExampleClientAgent() {
|
||||
// ssh-agent has a UNIX socket under $SSH_AUTH_SOCK
|
||||
socket := os.Getenv("SSH_AUTH_SOCK")
|
||||
conn, err := net.Dial("unix", socket)
|
||||
if err != nil {
|
||||
log.Fatalf("net.Dial: %v", err)
|
||||
}
|
||||
agentClient := agent.NewClient(conn)
|
||||
config := &ssh.ClientConfig{
|
||||
User: "username",
|
||||
Auth: []ssh.AuthMethod{
|
||||
// Use a callback rather than PublicKeys
|
||||
// so we only consult the agent once the remote server
|
||||
// wants it.
|
||||
ssh.PublicKeysCallback(agentClient.Signers),
|
||||
},
|
||||
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
|
||||
}
|
||||
|
||||
sshc, err := ssh.Dial("tcp", "localhost:22", config)
|
||||
if err != nil {
|
||||
log.Fatalf("Dial: %v", err)
|
||||
}
|
||||
// .. use sshc
|
||||
sshc.Close()
|
||||
}
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
// Copyright 2015 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package agent
|
||||
|
||||
import "testing"
|
||||
|
||||
func addTestKey(t *testing.T, a Agent, keyName string) {
|
||||
err := a.Add(AddedKey{
|
||||
PrivateKey: testPrivateKeys[keyName],
|
||||
Comment: keyName,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("failed to add key %q: %v", keyName, err)
|
||||
}
|
||||
}
|
||||
|
||||
func removeTestKey(t *testing.T, a Agent, keyName string) {
|
||||
err := a.Remove(testPublicKeys[keyName])
|
||||
if err != nil {
|
||||
t.Fatalf("failed to remove key %q: %v", keyName, err)
|
||||
}
|
||||
}
|
||||
|
||||
func validateListedKeys(t *testing.T, a Agent, expectedKeys []string) {
|
||||
listedKeys, err := a.List()
|
||||
if err != nil {
|
||||
t.Fatalf("failed to list keys: %v", err)
|
||||
return
|
||||
}
|
||||
actualKeys := make(map[string]bool)
|
||||
for _, key := range listedKeys {
|
||||
actualKeys[key.Comment] = true
|
||||
}
|
||||
|
||||
matchedKeys := make(map[string]bool)
|
||||
for _, expectedKey := range expectedKeys {
|
||||
if !actualKeys[expectedKey] {
|
||||
t.Fatalf("expected key %q, but was not found", expectedKey)
|
||||
} else {
|
||||
matchedKeys[expectedKey] = true
|
||||
}
|
||||
}
|
||||
|
||||
for actualKey := range actualKeys {
|
||||
if !matchedKeys[actualKey] {
|
||||
t.Fatalf("key %q was found, but was not expected", actualKey)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestKeyringAddingAndRemoving(t *testing.T) {
|
||||
keyNames := []string{"dsa", "ecdsa", "rsa", "user"}
|
||||
|
||||
// add all test private keys
|
||||
k := NewKeyring()
|
||||
for _, keyName := range keyNames {
|
||||
addTestKey(t, k, keyName)
|
||||
}
|
||||
validateListedKeys(t, k, keyNames)
|
||||
|
||||
// remove a key in the middle
|
||||
keyToRemove := keyNames[1]
|
||||
keyNames = append(keyNames[:1], keyNames[2:]...)
|
||||
|
||||
removeTestKey(t, k, keyToRemove)
|
||||
validateListedKeys(t, k, keyNames)
|
||||
|
||||
// remove all keys
|
||||
err := k.RemoveAll()
|
||||
if err != nil {
|
||||
t.Fatalf("failed to remove all keys: %v", err)
|
||||
}
|
||||
validateListedKeys(t, k, []string{})
|
||||
}
|
||||
+209
@@ -0,0 +1,209 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package agent
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
|
||||
func TestServer(t *testing.T) {
|
||||
c1, c2, err := netPipe()
|
||||
if err != nil {
|
||||
t.Fatalf("netPipe: %v", err)
|
||||
}
|
||||
defer c1.Close()
|
||||
defer c2.Close()
|
||||
client := NewClient(c1)
|
||||
|
||||
go ServeAgent(NewKeyring(), c2)
|
||||
|
||||
testAgentInterface(t, client, testPrivateKeys["rsa"], nil, 0)
|
||||
}
|
||||
|
||||
func TestLockServer(t *testing.T) {
|
||||
testLockAgent(NewKeyring(), t)
|
||||
}
|
||||
|
||||
func TestSetupForwardAgent(t *testing.T) {
|
||||
a, b, err := netPipe()
|
||||
if err != nil {
|
||||
t.Fatalf("netPipe: %v", err)
|
||||
}
|
||||
|
||||
defer a.Close()
|
||||
defer b.Close()
|
||||
|
||||
_, socket, cleanup := startAgent(t)
|
||||
defer cleanup()
|
||||
|
||||
serverConf := ssh.ServerConfig{
|
||||
NoClientAuth: true,
|
||||
}
|
||||
serverConf.AddHostKey(testSigners["rsa"])
|
||||
incoming := make(chan *ssh.ServerConn, 1)
|
||||
go func() {
|
||||
conn, _, _, err := ssh.NewServerConn(a, &serverConf)
|
||||
if err != nil {
|
||||
t.Fatalf("Server: %v", err)
|
||||
}
|
||||
incoming <- conn
|
||||
}()
|
||||
|
||||
conf := ssh.ClientConfig{
|
||||
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
|
||||
}
|
||||
conn, chans, reqs, err := ssh.NewClientConn(b, "", &conf)
|
||||
if err != nil {
|
||||
t.Fatalf("NewClientConn: %v", err)
|
||||
}
|
||||
client := ssh.NewClient(conn, chans, reqs)
|
||||
|
||||
if err := ForwardToRemote(client, socket); err != nil {
|
||||
t.Fatalf("SetupForwardAgent: %v", err)
|
||||
}
|
||||
|
||||
server := <-incoming
|
||||
ch, reqs, err := server.OpenChannel(channelType, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("OpenChannel(%q): %v", channelType, err)
|
||||
}
|
||||
go ssh.DiscardRequests(reqs)
|
||||
|
||||
agentClient := NewClient(ch)
|
||||
testAgentInterface(t, agentClient, testPrivateKeys["rsa"], nil, 0)
|
||||
conn.Close()
|
||||
}
|
||||
|
||||
func TestV1ProtocolMessages(t *testing.T) {
|
||||
c1, c2, err := netPipe()
|
||||
if err != nil {
|
||||
t.Fatalf("netPipe: %v", err)
|
||||
}
|
||||
defer c1.Close()
|
||||
defer c2.Close()
|
||||
c := NewClient(c1)
|
||||
|
||||
go ServeAgent(NewKeyring(), c2)
|
||||
|
||||
testV1ProtocolMessages(t, c.(*client))
|
||||
}
|
||||
|
||||
func testV1ProtocolMessages(t *testing.T, c *client) {
|
||||
reply, err := c.call([]byte{agentRequestV1Identities})
|
||||
if err != nil {
|
||||
t.Fatalf("v1 request all failed: %v", err)
|
||||
}
|
||||
if msg, ok := reply.(*agentV1IdentityMsg); !ok || msg.Numkeys != 0 {
|
||||
t.Fatalf("invalid request all response: %#v", reply)
|
||||
}
|
||||
|
||||
reply, err = c.call([]byte{agentRemoveAllV1Identities})
|
||||
if err != nil {
|
||||
t.Fatalf("v1 remove all failed: %v", err)
|
||||
}
|
||||
if _, ok := reply.(*successAgentMsg); !ok {
|
||||
t.Fatalf("invalid remove all response: %#v", reply)
|
||||
}
|
||||
}
|
||||
|
||||
func verifyKey(sshAgent Agent) error {
|
||||
keys, err := sshAgent.List()
|
||||
if err != nil {
|
||||
return fmt.Errorf("listing keys: %v", err)
|
||||
}
|
||||
|
||||
if len(keys) != 1 {
|
||||
return fmt.Errorf("bad number of keys found. expected 1, got %d", len(keys))
|
||||
}
|
||||
|
||||
buf := make([]byte, 128)
|
||||
if _, err := rand.Read(buf); err != nil {
|
||||
return fmt.Errorf("rand: %v", err)
|
||||
}
|
||||
|
||||
sig, err := sshAgent.Sign(keys[0], buf)
|
||||
if err != nil {
|
||||
return fmt.Errorf("sign: %v", err)
|
||||
}
|
||||
|
||||
if err := keys[0].Verify(buf, sig); err != nil {
|
||||
return fmt.Errorf("verify: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func addKeyToAgent(key crypto.PrivateKey) error {
|
||||
sshAgent := NewKeyring()
|
||||
if err := sshAgent.Add(AddedKey{PrivateKey: key}); err != nil {
|
||||
return fmt.Errorf("add: %v", err)
|
||||
}
|
||||
return verifyKey(sshAgent)
|
||||
}
|
||||
|
||||
func TestKeyTypes(t *testing.T) {
|
||||
for k, v := range testPrivateKeys {
|
||||
if err := addKeyToAgent(v); err != nil {
|
||||
t.Errorf("error adding key type %s, %v", k, err)
|
||||
}
|
||||
if err := addCertToAgentSock(v, nil); err != nil {
|
||||
t.Errorf("error adding key type %s, %v", k, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func addCertToAgentSock(key crypto.PrivateKey, cert *ssh.Certificate) error {
|
||||
a, b, err := netPipe()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
agentServer := NewKeyring()
|
||||
go ServeAgent(agentServer, a)
|
||||
|
||||
agentClient := NewClient(b)
|
||||
if err := agentClient.Add(AddedKey{PrivateKey: key, Certificate: cert}); err != nil {
|
||||
return fmt.Errorf("add: %v", err)
|
||||
}
|
||||
return verifyKey(agentClient)
|
||||
}
|
||||
|
||||
func addCertToAgent(key crypto.PrivateKey, cert *ssh.Certificate) error {
|
||||
sshAgent := NewKeyring()
|
||||
if err := sshAgent.Add(AddedKey{PrivateKey: key, Certificate: cert}); err != nil {
|
||||
return fmt.Errorf("add: %v", err)
|
||||
}
|
||||
return verifyKey(sshAgent)
|
||||
}
|
||||
|
||||
func TestCertTypes(t *testing.T) {
|
||||
for keyType, key := range testPublicKeys {
|
||||
cert := &ssh.Certificate{
|
||||
ValidPrincipals: []string{"gopher1"},
|
||||
ValidAfter: 0,
|
||||
ValidBefore: ssh.CertTimeInfinity,
|
||||
Key: key,
|
||||
Serial: 1,
|
||||
CertType: ssh.UserCert,
|
||||
SignatureKey: testPublicKeys["rsa"],
|
||||
Permissions: ssh.Permissions{
|
||||
CriticalOptions: map[string]string{},
|
||||
Extensions: map[string]string{},
|
||||
},
|
||||
}
|
||||
if err := cert.SignCert(rand.Reader, testSigners["rsa"]); err != nil {
|
||||
t.Fatalf("signcert: %v", err)
|
||||
}
|
||||
if err := addCertToAgent(testPrivateKeys[keyType], cert); err != nil {
|
||||
t.Fatalf("%v", err)
|
||||
}
|
||||
if err := addCertToAgentSock(testPrivateKeys[keyType], cert); err != nil {
|
||||
t.Fatalf("%v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// IMPLEMENTATION NOTE: To avoid a package loop, this file is in three places:
|
||||
// ssh/, ssh/agent, and ssh/test/. It should be kept in sync across all three
|
||||
// instances.
|
||||
|
||||
package agent
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
|
||||
"golang.org/x/crypto/ssh"
|
||||
"golang.org/x/crypto/ssh/testdata"
|
||||
)
|
||||
|
||||
var (
|
||||
testPrivateKeys map[string]interface{}
|
||||
testSigners map[string]ssh.Signer
|
||||
testPublicKeys map[string]ssh.PublicKey
|
||||
)
|
||||
|
||||
func init() {
|
||||
var err error
|
||||
|
||||
n := len(testdata.PEMBytes)
|
||||
testPrivateKeys = make(map[string]interface{}, n)
|
||||
testSigners = make(map[string]ssh.Signer, n)
|
||||
testPublicKeys = make(map[string]ssh.PublicKey, n)
|
||||
for t, k := range testdata.PEMBytes {
|
||||
testPrivateKeys[t], err = ssh.ParseRawPrivateKey(k)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Unable to parse test key %s: %v", t, err))
|
||||
}
|
||||
testSigners[t], err = ssh.NewSignerFromKey(testPrivateKeys[t])
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Unable to create signer for test key %s: %v", t, err))
|
||||
}
|
||||
testPublicKeys[t] = testSigners[t].PublicKey()
|
||||
}
|
||||
|
||||
// Create a cert and sign it for use in tests.
|
||||
testCert := &ssh.Certificate{
|
||||
Nonce: []byte{}, // To pass reflect.DeepEqual after marshal & parse, this must be non-nil
|
||||
ValidPrincipals: []string{"gopher1", "gopher2"}, // increases test coverage
|
||||
ValidAfter: 0, // unix epoch
|
||||
ValidBefore: ssh.CertTimeInfinity, // The end of currently representable time.
|
||||
Reserved: []byte{}, // To pass reflect.DeepEqual after marshal & parse, this must be non-nil
|
||||
Key: testPublicKeys["ecdsa"],
|
||||
SignatureKey: testPublicKeys["rsa"],
|
||||
Permissions: ssh.Permissions{
|
||||
CriticalOptions: map[string]string{},
|
||||
Extensions: map[string]string{},
|
||||
},
|
||||
}
|
||||
testCert.SignCert(rand.Reader, testSigners["rsa"])
|
||||
testPrivateKeys["cert"] = testPrivateKeys["ecdsa"]
|
||||
testSigners["cert"], err = ssh.NewCertSigner(testCert, testSigners["ecdsa"])
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Unable to create certificate signer: %v", err))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user