diff --git a/ssh/agent/client.go b/ssh/agent/client.go index 2cb9248..f0935e5 100644 --- a/ssh/agent/client.go +++ b/ssh/agent/client.go @@ -76,7 +76,8 @@ type AddedKey struct { // See [PROTOCOL.agent], section 3. const ( - agentRequestV1Identities = 1 + agentRequestV1Identities = 1 + agentRemoveAllV1Identities = 9 // 3.2 Requests from client to agent for protocol 2 key operations agentAddIdentity = 17 @@ -376,6 +377,8 @@ func unmarshal(packet []byte) (interface{}, error) { msg = new(identitiesAnswerAgentMsg) case agentSignResponse: msg = new(signResponseAgentMsg) + case agentV1IdentitiesAnswer: + msg = new(agentV1IdentityMsg) default: return nil, fmt.Errorf("agent: unknown type tag %d", packet[0]) } diff --git a/ssh/agent/server.go b/ssh/agent/server.go index b21a201..0a80d36 100644 --- a/ssh/agent/server.go +++ b/ssh/agent/server.go @@ -49,6 +49,9 @@ func marshalKey(k *Key) []byte { return ssh.Marshal(&record) } +// See [PROTOCOL.agent], section 2.5.1. +const agentV1IdentitiesAnswer = 2 + type agentV1IdentityMsg struct { Numkeys uint32 `sshtype:"2"` } @@ -69,6 +72,10 @@ func (s *server) processRequest(data []byte) (interface{}, error) { switch data[0] { case agentRequestV1Identities: return &agentV1IdentityMsg{0}, nil + + case agentRemoveAllV1Identities: + return nil, nil + case agentRemoveIdentity: var req agentRemoveIdentityMsg if err := ssh.Unmarshal(data, &req); err != nil { diff --git a/ssh/agent/server_test.go b/ssh/agent/server_test.go index ef0ab29..fd7848e 100644 --- a/ssh/agent/server_test.go +++ b/ssh/agent/server_test.go @@ -75,3 +75,35 @@ func TestSetupForwardAgent(t *testing.T) { 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) + } +}