From 8aaf3a4de76d8c91e11f4bc1aae0268a2d71ec93 Mon Sep 17 00:00:00 2001
From: ale <ale@incal.net>
Date: Sat, 24 Oct 2020 13:43:49 +0100
Subject: [PATCH] Log incoming requests, even when they result in zero events

---
 browser.go   |  2 ++
 collector.go | 70 ++++++++++++++++++++--------------------------------
 csp.go       |  2 ++
 dmarc.go     |  2 ++
 tlsrpt.go    |  2 ++
 5 files changed, 35 insertions(+), 43 deletions(-)

diff --git a/browser.go b/browser.go
index 09e506b..e4c546d 100644
--- a/browser.go
+++ b/browser.go
@@ -21,6 +21,8 @@ type report struct {
 
 type ReportHandler struct{}
 
+func (h *ReportHandler) Name() string { return "report-api" }
+
 func (h *ReportHandler) Parse(contentType string, req *http.Request) ([]Event, error) {
 	if contentType != "application/reports+json" {
 		return nil, ErrNoMatch
diff --git a/collector.go b/collector.go
index 24e3a9a..aefe291 100644
--- a/collector.go
+++ b/collector.go
@@ -16,6 +16,7 @@ import (
 var ErrNoMatch = errors.New("no match")
 
 type Handler interface {
+	Name() string
 	Parse(string, *http.Request) ([]Event, error)
 	ParseMIME(*enmime.Part) ([]Event, error)
 }
@@ -60,19 +61,22 @@ func (c *Collector) ServeHTTP(w http.ResponseWriter, req *http.Request) {
 
 	// Find a handler that can successfully parse the request, and
 	// get a list of Events.
-	var events []Event
-	matched := false
-hloop:
 	for _, h := range c.handlers {
-		var err error
-		events, err = h.Parse(ct, req)
+		events, err := h.Parse(ct, req)
 		switch err {
-		case ErrNoMatch:
-			continue
 		case nil:
-			matched = true
+			// Send the parsed events to the Sink.
+			for _, e := range events {
+				c.sink.Send(e)
+				reportsByType.WithLabelValues(
+					e.GetString("type"), e.GetString("domain")).Inc()
+			}
+
+			log.Printf("http: %s: received %d events from %s", h.Name(), len(events), getRemoteIP(req))
 			w.WriteHeader(http.StatusOK)
-			break hloop
+			return
+		case ErrNoMatch:
+			continue
 		default:
 			log.Printf("error parsing report (%s): %v", ct, err)
 			http.Error(w, err.Error(), http.StatusBadRequest)
@@ -80,19 +84,8 @@ hloop:
 		}
 	}
 
-	if !matched {
-		log.Printf("no matching handlers for \"%s\"", ct)
-		http.Error(w, "No matching handlers", http.StatusBadRequest)
-		return
-	}
-
-	// Augment the Events with additional information obtained
-	// from the HTTP request, and send them to the forwarder.
-	for _, e := range events {
-		c.sink.Send(e)
-		reportsByType.WithLabelValues(
-			e.GetString("type"), e.GetString("domain")).Inc()
-	}
+	log.Printf("no matching handlers for \"%s\"", ct)
+	http.Error(w, "No matching handlers", http.StatusBadRequest)
 }
 
 func (c *Collector) ServeSMTP(peer smtpd.Peer, env smtpd.Envelope) error {
@@ -104,18 +97,20 @@ func (c *Collector) ServeSMTP(peer smtpd.Peer, env smtpd.Envelope) error {
 
 	// Find a handler that can successfully parse the request, and
 	// get a list of Events.
-	var events []Event
-	matched := false
-hloop:
 	for _, h := range c.handlers {
-		var err error
-		events, err = h.ParseMIME(msgParts)
+		events, err := h.ParseMIME(msgParts)
 		switch err {
+		case nil:
+			// Send the parsed events to the Sink.
+			for _, e := range events {
+				c.sink.Send(e)
+				reportsByType.WithLabelValues(
+					e.GetString("type"), e.GetString("domain")).Inc()
+			}
+			log.Printf("smtp: %s: received %d events from %s", h.Name(), len(events), env.Sender)
+			return nil
 		case ErrNoMatch:
 			continue
-		case nil:
-			matched = true
-			break hloop
 		default:
 			log.Printf("smtp: error handling report: %v", err)
 			// Discard the message.
@@ -123,19 +118,8 @@ hloop:
 		}
 	}
 
-	if !matched {
-		log.Printf("smtp: no matching handlers")
-		// Discard the message.
-		return nil
-	}
-
-	// Augment the Events with additional information obtained
-	// from the HTTP request, and send them to the forwarder.
-	for _, e := range events {
-		c.sink.Send(e)
-		reportsByType.WithLabelValues(
-			e.GetString("type"), e.GetString("domain")).Inc()
-	}
+	log.Printf("smtp: no matching handlers")
+	// Discard the message.
 	return nil
 }
 
diff --git a/csp.go b/csp.go
index 698c38e..a694457 100644
--- a/csp.go
+++ b/csp.go
@@ -27,6 +27,8 @@ type legacyCSPReportContainer struct {
 
 type LegacyCSPHandler struct{}
 
+func (h *LegacyCSPHandler) Name() string { return "legacy-csp" }
+
 func (h *LegacyCSPHandler) Parse(contentType string, req *http.Request) ([]Event, error) {
 	if contentType != "application/csp-report" {
 		return nil, ErrNoMatch
diff --git a/dmarc.go b/dmarc.go
index 064036c..152a110 100644
--- a/dmarc.go
+++ b/dmarc.go
@@ -75,6 +75,8 @@ type dmarcReport struct {
 
 type DMARCHandler struct{}
 
+func (h *DMARCHandler) Name() string { return "dmarc" }
+
 func (h *DMARCHandler) parseDMARC(r io.Reader) ([]Event, error) {
 	var report dmarcReport
 	if err := xml.NewDecoder(r).Decode(&report); err != nil {
diff --git a/tlsrpt.go b/tlsrpt.go
index 3f169e7..d293b0d 100644
--- a/tlsrpt.go
+++ b/tlsrpt.go
@@ -51,6 +51,8 @@ type tlsrpt struct {
 
 type TLSRPTHandler struct{}
 
+func (h *TLSRPTHandler) Name() string { return "tls-rpt" }
+
 func (h *TLSRPTHandler) Parse(contentType string, req *http.Request) ([]Event, error) {
 	var r io.Reader
 	switch contentType {
-- 
GitLab