internal/mailin/fuzz_test.go
71 lines · 2381 bytes
1package mailin
2
3import (
4 "bytes"
5 "net/mail"
6 "net/textproto"
7 "strings"
8 "testing"
9 "time"
10
11 "github.com/emersion/go-msgauth/dkim"
12
13 "gitbay.org/gitbay/internal/mailreply"
14)
15
16// FuzzReply runs what an inbound message goes through before any
17// account is looked up: header parsing, token extraction and
18// verification, body extraction and quote stripping.
19func FuzzReply(f *testing.F) {
20 f.Add([]byte("From: a@b\r\nTo: reply+abc@x.example\r\nContent-Type: multipart/alternative; boundary=b\r\n\r\n--b\r\nContent-Type: text/plain\r\nContent-Transfer-Encoding: quoted-printable\r\n\r\nhi=\r\n\r\n> q\r\n--b--\r\n"))
21 f.Add([]byte("Subject: x\r\n\r\nOn Mon wrote:\r\n> a\r\n-- \r\nsig\r\n"))
22 key := [][]byte{[]byte("0123456789abcdef0123456789abcdef")}
23 f.Fuzz(func(t *testing.T, raw []byte) {
24 parseRawHeader(raw)
25 msg, err := mail.ReadMessage(bytes.NewReader(raw))
26 if err != nil {
27 return
28 }
29 automatic(msg.Header)
30 if tok, _ := findToken(msg.Header, "reply@x.example", recipientFields); tok != "" {
31 mailreply.Verify(key, tok, fuzzNow)
32 }
33 if s, err := textBody(textproto.MIMEHeader(msg.Header), msg.Body, 1<<16); err == nil {
34 stripQuoted(s)
35 }
36 })
37}
38
39var fuzzNow = time.Date(2026, 9, 29, 0, 0, 0, 0, time.UTC)
40
41// FuzzDKIM runs the DKIM check, the dkim package's signature and key
42// record parsing included, on arbitrary messages: no input panics.
43func FuzzDKIM(f *testing.F) {
44 msg := "From: bob@example.test\r\nTo: x@y\r\nSubject: s\r\n\r\nhi\r\n"
45 for _, canon := range []dkim.Canonicalization{dkim.CanonicalizationSimple, dkim.CanonicalizationRelaxed} {
46 var b bytes.Buffer
47 o := dkim.SignOptions{Domain: "example.test", Selector: "rsa", Signer: rsaKey,
48 HeaderCanonicalization: canon, BodyCanonicalization: canon}
49 if err := dkim.Sign(&b, strings.NewReader(msg), &o); err != nil {
50 f.Fatal(err)
51 }
52 f.Add(b.Bytes())
53 }
54 f.Add([]byte("DKIM-Signature: v=1; a=ed25519-sha256; d=example.test; s=temp; h=from; bh=; b=\r\nFrom: a@example.test\r\n\r\n"))
55 f.Fuzz(func(t *testing.T, raw []byte) {
56 msg, err := mail.ReadMessage(bytes.NewReader(raw))
57 if err != nil {
58 return
59 }
60 from, err := msg.Header.AddressList("From")
61 if err != nil || len(from) != 1 {
62 return
63 }
64 rh, reason := parseRawHeader(raw)
65 if reason != "" {
66 return
67 }
68 p := &Processor{LookupTXT: (&fakeDNS{}).lookup}
69 p.dkimVerified(raw, rh, from[0].Address, "to")
70 })
71}