12 "github.com/mjl-/mox/config"
13 "github.com/mjl-/mox/dns"
14 "github.com/mjl-/mox/mlog"
15 "github.com/mjl-/mox/mox-"
16 "github.com/mjl-/mox/tlsrpt"
19var ctxbg = context.Background()
20var pkglog = mlog.New("tlsrptdb", nil)
23 "organization-name": "Company-X",
25 "start-datetime": "2016-04-01T00:00:00Z",
26 "end-datetime": "2016-04-01T23:59:59Z"
28 "contact-info": "sts-reporting@company-x.example",
29 "report-id": "5065427c-23d3-47ca-b6e0-946ea0e8c4be",
33 "policy-string": ["version: STSv1","mode: testing",
34 "mx: *.mail.company-y.example","max_age: 86400"],
35 "policy-domain": "test.xmox.nl",
36 "mx-host": ["*.mail.company-y.example"]
39 "total-successful-session-count": 5326,
40 "total-failure-session-count": 303
43 "result-type": "certificate-expired",
44 "sending-mta-ip": "2001:db8:abcd:0012::1",
45 "receiving-mx-hostname": "mx1.mail.company-y.example",
46 "failed-session-count": 100
48 "result-type": "starttls-not-supported",
49 "sending-mta-ip": "2001:db8:abcd:0013::1",
50 "receiving-mx-hostname": "mx2.mail.company-y.example",
51 "receiving-ip": "203.0.113.56",
52 "failed-session-count": 200,
53 "additional-information": "https://reports.company-x.example/report_info ? id = 5065427 c - 23 d3# StarttlsNotSupported "
55 "result-type": "validation-failure",
56 "sending-mta-ip": "198.51.100.62",
57 "receiving-ip": "203.0.113.58",
58 "receiving-mx-hostname": "mx-backup.mail.company-y.example",
59 "failed-session-count": 3,
60 "failure-reason-code": "X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED"
65const reportMultipleJSON = `{
66 "organization-name": "remote.example",
68 "start-datetime": "2024-02-25T00:00:00Z",
69 "end-datetime": "2024-02-25T23:59:59Z"
71 "contact-info": "postmaster@remote.example",
72 "report-id": "20240225.mail.mox.example@remote.example",
76 "policy-type": "tlsa",
78 "3 1 1 206d5f55ecb9f8389bc57b5ba14716dd5b23d0834fd2c99fd402f0bda32e9523",
79 "3 1 1 4201e4b741c746b62ff806c142158c35ecbbbd9ac56b6d791f760e272736f8d0"
81 "policy-domain": "test2.xmox.nl",
87 "total-successful-session-count": 1,
88 "total-failure-session-count": 0
94 "policy-type": "tlsa",
96 "3 1 1 206d5f55ecb9f8389bc57b5ba14716dd5b23d0834fd2c99fd402f0bda32e9523",
97 "3 1 1 4201e4b741c746b62ff806c142158c35ecbbbd9ac56b6d791f760e272736f8d0"
99 "policy-domain": "test.xmox.nl",
105 "total-successful-session-count": 1,
106 "total-failure-session-count": 0
108 "failure-details": []
114const reportMixedJSON = `{
115 "organization-name": "remote.example",
117 "start-datetime": "2024-02-25T00:00:00Z",
118 "end-datetime": "2024-02-25T23:59:59Z"
120 "contact-info": "postmaster@remote.example",
121 "report-id": "20240225.test.xmox.nl@remote.example",
125 "policy-type": "tlsa",
127 "3 1 1 206d5f55ecb9f8389bc57b5ba14716dd5b23d0834fd2c99fd402f0bda32e9523",
128 "3 1 1 4201e4b741c746b62ff806c142158c35ecbbbd9ac56b6d791f760e272736f8d0"
130 "policy-domain": "mail.mox.example",
134 "total-successful-session-count": 1,
135 "total-failure-session-count": 0
137 "failure-details": []
141 "policy-type": "sts",
146 "mx: mail.mox.example"
148 "policy-domain": "unknown.xmox.nl",
154 "total-successful-session-count": 1,
155 "total-failure-session-count": 0
157 "failure-details": []
161 "policy-type": "sts",
166 "mx: mail.mox.example"
168 "policy-domain": "test.xmox.nl",
174 "total-successful-session-count": 1,
175 "total-failure-session-count": 0
177 "failure-details": []
183const reportUnknownJSON = `{
184 "organization-name": "remote.example",
186 "start-datetime": "2024-02-25T00:00:00Z",
187 "end-datetime": "2024-02-25T23:59:59Z"
189 "contact-info": "postmaster@remote.example",
190 "report-id": "20240225.test.xmox.nl@remote.example",
194 "policy-type": "tlsa",
196 "3 1 1 206d5f55ecb9f8389bc57b5ba14716dd5b23d0834fd2c99fd402f0bda32e9523",
197 "3 1 1 4201e4b741c746b62ff806c142158c35ecbbbd9ac56b6d791f760e272736f8d0"
199 "policy-domain": "unknown.mox.example",
203 "total-successful-session-count": 1,
204 "total-failure-session-count": 0
206 "failure-details": []
210 "policy-type": "sts",
215 "mx: mail.mox.example"
217 "policy-domain": "unknown.xmox.nl",
219 "unknown.mox.example"
223 "total-successful-session-count": 1,
224 "total-failure-session-count": 0
226 "failure-details": []
232func TestReport(t *testing.T) {
234 mox.Shutdown, mox.ShutdownCancel = context.WithCancel(ctxbg)
235 mox.ConfigStaticPath = filepath.FromSlash("../testdata/tlsrpt/fake.conf")
236 mox.Conf.Static.HostnameDomain = dns.Domain{ASCII: "mail.mox.example"}
237 mox.Conf.Static.DataDir = "."
238 // Recognize as configured domain.
239 mox.Conf.Dynamic.Domains = map[string]config.Domain{
244 dbpath := mox.DataDirPath("tlsrpt.db")
245 os.MkdirAll(filepath.Dir(dbpath), 0770)
246 defer os.Remove(dbpath)
247 defer os.Remove(mox.DataDirPath("tlsrptresult.db"))
249 if err := Init(); err != nil {
250 t.Fatalf("init database: %s", err)
254 files, err := os.ReadDir("../testdata/tlsreports")
256 t.Fatalf("listing reports: %s", err)
258 for _, file := range files {
259 f, err := os.Open("../testdata/tlsreports/" + file.Name())
261 t.Fatalf("open %q: %s", file, err)
263 reportJSON, err := tlsrpt.ParseMessage(pkglog.Logger, f)
266 t.Fatalf("parsing TLSRPT from message %q: %s", file.Name(), err)
268 report := reportJSON.Convert()
269 if err := AddReport(ctxbg, pkglog, dns.Domain{ASCII: "mox.example"}, "tlsrpt@mox.example", false, &report); err != nil {
270 t.Fatalf("adding report to database: %s", err)
274 reportJSON, err := tlsrpt.Parse(strings.NewReader(reportJSON))
276 t.Fatalf("parsing report: %v", err)
278 report := reportJSON.Convert()
279 if err := AddReport(ctxbg, pkglog, dns.Domain{ASCII: "company-y.example"}, "tlsrpt@company-y.example", false, &report); err != nil {
280 t.Fatalf("adding report to database: %s", err)
283 records, err := Records(ctxbg)
285 t.Fatalf("fetching records: %s", err)
287 for _, r := range records {
288 if r.FromDomain != "company-y.example" {
291 if !reflect.DeepEqual(r.Report, report) {
292 t.Fatalf("report, got %#v, expected %#v", r.Report, report)
294 if _, err := RecordID(ctxbg, r.ID); err != nil {
295 t.Fatalf("get record by id: %v", err)
299 start, _ := time.Parse(time.RFC3339, "2016-04-01T00:00:00Z")
300 end, _ := time.Parse(time.RFC3339, "2016-04-01T23:59:59Z")
301 records, err = RecordsPeriodDomain(ctxbg, start, end, dns.Domain{ASCII: "test.xmox.nl"})
302 if err != nil || len(records) != 1 {
303 t.Fatalf("got err %v, records %#v, expected no error with 1 record", err, records)
306 // Add report with multiple recipient domains.
307 reportJSON, err = tlsrpt.Parse(strings.NewReader(reportMultipleJSON))
309 t.Fatalf("parsing report: %v", err)
311 report = reportJSON.Convert()
312 if err := AddReport(ctxbg, pkglog, dns.Domain{ASCII: "remote.example"}, "postmaster@remote.example", false, &report); err != nil {
313 t.Errorf("adding report to database: %s", err)
316 // Add report with mixed host and domain policies. The unknown domain is ignored.
317 reportJSON, err = tlsrpt.Parse(strings.NewReader(reportMixedJSON))
319 t.Fatalf("parsing report: %v", err)
321 report = reportJSON.Convert()
322 if err := AddReport(ctxbg, pkglog, dns.Domain{ASCII: "remote.example"}, "postmaster@remote.example", false, &report); err != nil {
323 t.Errorf("adding report to database: %s", err)
326 // All unknown domains in report should cause error.
327 reportJSON, err = tlsrpt.Parse(strings.NewReader(reportUnknownJSON))
329 t.Fatalf("parsing report: %v", err)
331 report = reportJSON.Convert()
332 if err := AddReport(ctxbg, pkglog, dns.Domain{ASCII: "remote.example"}, "postmaster@remote.example", false, &report); err == nil {
333 t.Errorf("adding report with all unknown domains, expected error")