internal/mailin/fuzz_test.go

v1.42.0
gitbay/internal/mailin/fuzz_test.go history · blame · raw

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}