1package auth
2
3import (
4 "bytes"
5 "encoding/binary"
6 "errors"
7 "io"
8 "testing"
9
10 "github.com/bnema/neferafk/internal/ports"
11)
12
13func TestCodecBoundsAndTruncation(t *testing.T) {
14 f := ports.AuthFrame{Kind: ports.AuthSecret, Generation: 7, Attempt: ^uint64(0), Payload: bytes.Repeat([]byte{'x'}, 512)}
15 var wire bytes.Buffer
16 if err := WriteFrame(&wire, f); err != nil {
17 t.Fatal(err)
18 }
19 encoded := bytes.Clone(wire.Bytes())
20 got, err := ReadFrame(&wire)
21 if err != nil || got.Generation != 7 || got.Attempt != f.Attempt || !bytes.Equal(got.Payload, f.Payload) {
22 t.Fatalf("roundtrip %v", err)
23 }
24 clear(got.Payload)
25 for _, n := range []int{1, 4, 10, 26, len(encoded) - 1} {
26 if _, err := ReadFrame(bytes.NewReader(encoded[:n])); err == nil {
27 t.Fatalf("truncation %d accepted", n)
28 }
29 }
30 for _, corrupt := range []string{"magic", "kind", "generation", "secret-length", "huge"} {
31 b := bytes.Clone(encoded)
32 switch corrupt {
33 case "magic":
34 b[4] = 'X'
35 case "kind":
36 b[8] = 255
37 case "generation":
38 clear(b[10:18])
39 case "secret-length":
40 binary.BigEndian.PutUint32(b[:4], frameHeader+513)
41 case "huge":
42 binary.BigEndian.PutUint32(b[:4], ^uint32(0))
43 }
44 if _, err := ReadFrame(bytes.NewReader(b)); !errors.Is(err, ErrProtocol) {
45 t.Fatalf("%s error %v", corrupt, err)
46 }
47 }
48 f.Payload = append(f.Payload, 1)
49 if err := WriteFrame(io.Discard, f); !errors.Is(err, ErrProtocol) {
50 t.Fatal("oversize secret accepted")
51 }
52}