diff options
| author | Nicola Murino <nicola.murino@gmail.com> | 2025-08-31 20:07:32 +0200 |
|---|---|---|
| committer | Nicola Murino <nicola.murino@gmail.com> | 2025-09-09 02:56:19 -0700 |
| commit | 559e062ce8bfd6a39925294620b50906ca2a6f95 (patch) | |
| tree | 92fcab091e6f45d6205893caf5bd3b131fa39125 | |
| parent | 5307a0ce6db8057c8d7c4378dc4bd715b4985ba1 (diff) | |
| download | go-x-crypto-559e062ce8bfd6a39925294620b50906ca2a6f95.tar.xz | |
ssh/agent: return an error for unexpected message types
Previously, receiving an unexpected message type in response to a key
listing or a signing request could cause a panic due to a failed type
assertion.
This change adds a default case to the type switch in order to detect
and explicitly handle unknown or invalid message types, returning a
descriptive error instead of crashing.
Fixes golang/go#75178
Change-Id: Icbc3432adc79fe3c56b1ff23c6724d7a6f710f3a
Reviewed-on: https://go-review.googlesource.com/c/crypto/+/700295
Reviewed-by: Roland Shoemaker <roland@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
Reviewed-by: Jakub Ciolek <jakub@ciolek.dev>
| -rw-r--r-- | ssh/agent/client.go | 6 | ||||
| -rw-r--r-- | ssh/agent/client_test.go | 48 |
2 files changed, 52 insertions, 2 deletions
diff --git a/ssh/agent/client.go b/ssh/agent/client.go index 37525e1..b357e18 100644 --- a/ssh/agent/client.go +++ b/ssh/agent/client.go @@ -430,8 +430,9 @@ func (c *client) List() ([]*Key, error) { return keys, nil case *failureAgentMsg: return nil, errors.New("agent: failed to list keys") + default: + return nil, fmt.Errorf("agent: failed to list keys, unexpected message type %T", msg) } - panic("unreachable") } // Sign has the agent sign the data using a protocol 2 key as defined @@ -462,8 +463,9 @@ func (c *client) SignWithFlags(key ssh.PublicKey, data []byte, flags SignatureFl return &sig, nil case *failureAgentMsg: return nil, errors.New("agent: failed to sign challenge") + default: + return nil, fmt.Errorf("agent: failed to sign challenge, unexpected message type %T", msg) } - panic("unreachable") } // unmarshal parses an agent message in packet, returning the parsed diff --git a/ssh/agent/client_test.go b/ssh/agent/client_test.go index f0ffd59..0fd284d 100644 --- a/ssh/agent/client_test.go +++ b/ssh/agent/client_test.go @@ -7,6 +7,7 @@ package agent import ( "bytes" "crypto/rand" + "encoding/binary" "errors" "io" "net" @@ -347,6 +348,53 @@ func TestServerResponseTooLarge(t *testing.T) { } } +func TestInvalidResponses(t *testing.T) { + a, b, err := netPipe() + if err != nil { + t.Fatalf("netPipe: %v", err) + } + done := make(chan struct{}) + defer func() { <-done }() + + defer a.Close() + defer b.Close() + + agent := NewClient(a) + go func() { + defer close(done) + + resp := []byte{agentSuccess} + msg := make([]byte, 4+len(resp)) + binary.BigEndian.PutUint32(msg[:4], uint32(len(resp))) + copy(msg[4:], resp) + + if _, err := b.Write(msg); err != nil { + t.Errorf("unexpected error sending agent reply: %v", err) + b.Close() + return + } + + if _, err := b.Write(msg); err != nil { + t.Errorf("unexpected error sending agent reply: %v", err) + b.Close() + } + }() + _, err = agent.List() + if err == nil { + t.Fatal("error expected") + } + if !strings.Contains(err.Error(), "failed to list keys, unexpected message type") { + t.Fatalf("unexpected error: %v", err) + } + _, err = agent.Sign(testPublicKeys["rsa"], []byte("message")) + if err == nil { + t.Fatal("error expected") + } + if !strings.Contains(err.Error(), "failed to sign challenge, unexpected message type") { + t.Fatalf("unexpected error: %v", err) + } +} + func TestAuth(t *testing.T) { agent, _, cleanup := startOpenSSHAgent(t) defer cleanup() |
