From ed8cec77ab40fe2a803c15d8446cb28904f65f73 Mon Sep 17 00:00:00 2001 From: Andrew Ayer Date: Fri, 4 Jul 2025 12:37:51 -0400 Subject: [PATCH] loglist/mozilla: handle static-ct-api logs --- loglist/mozilla/ctlogs.go | 23 ++++++++++------------- loglist/mozilla/ctlogs_test.go | 3 +++ loglist/mozilla/example_test.go | 6 +++--- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/loglist/mozilla/ctlogs.go b/loglist/mozilla/ctlogs.go index 46d502a..1236386 100644 --- a/loglist/mozilla/ctlogs.go +++ b/loglist/mozilla/ctlogs.go @@ -24,6 +24,7 @@ import ( type CTLogInfo struct { Name string State string // Admissible or Retired + Protocol string // RFC6962 or Tiled Timestamp time.Time OperatorIndex int Key []byte @@ -116,7 +117,7 @@ func readLogEntry(firstLine string, s *bufio.Scanner) (CTLogInfo, error) { var log CTLogInfo // Example first line: - // {"Name", CTLogState::Admissible, + // {"Name", CTLogState::Admissible, CTLogFormat::RFC6962, firstLine = strings.TrimSpace(firstLine) if !strings.HasPrefix(firstLine, "{") { return log, errors.New("invalid log entry start") @@ -125,22 +126,18 @@ func readLogEntry(firstLine string, s *bufio.Scanner) (CTLogInfo, error) { firstLine = strings.TrimSuffix(firstLine, ",") parts := splitCSV(firstLine) - var statePart string - switch len(parts) { - case 2: - log.Name = trimQuotes(parts[0]) - statePart = parts[1] - case 1: - log.Name = trimQuotes(parts[0]) + + for len(parts) < 3 { if !s.Scan() { return log, io.ErrUnexpectedEOF } - statePart = strings.TrimSpace(s.Text()) - default: - return log, errors.New("invalid log entry header") + next := strings.TrimSpace(strings.TrimSuffix(s.Text(), ",")) + parts = append(parts, splitCSV(next)...) } - statePart = strings.TrimSuffix(strings.TrimSpace(statePart), ",") - log.State = strings.TrimPrefix(statePart, "CTLogState::") + + log.Name = trimQuotes(parts[0]) + log.State = strings.TrimPrefix(strings.TrimSpace(parts[1]), "CTLogState::") + log.Protocol = strings.TrimPrefix(strings.TrimSpace(parts[2]), "CTLogFormat::") // Next line: timestamp if !s.Scan() { diff --git a/loglist/mozilla/ctlogs_test.go b/loglist/mozilla/ctlogs_test.go index 8c62590..3cc212e 100644 --- a/loglist/mozilla/ctlogs_test.go +++ b/loglist/mozilla/ctlogs_test.go @@ -73,6 +73,9 @@ func TestParseFromURL(t *testing.T) { if l.State != "Admissible" && l.State != "Retired" { t.Errorf("unexpected state %q", l.State) } + if l.Protocol != "RFC6962" && l.Protocol != "Tiled" { + t.Errorf("unexpected protocol %q", l.Protocol) + } hash := sha256.Sum256(l.Key) if base64.StdEncoding.EncodeToString(hash[:]) == targetHash { foundHash = true diff --git a/loglist/mozilla/example_test.go b/loglist/mozilla/example_test.go index aa7c679..80888b5 100644 --- a/loglist/mozilla/example_test.go +++ b/loglist/mozilla/example_test.go @@ -44,12 +44,12 @@ func ExampleParse() { tw.Flush() tw = tabwriter.NewWriter(os.Stdout, 0, 8, 1, ' ', 0) - fmt.Fprintln(tw, "LogID\tState\tTimestamp\tOperator\tName") + fmt.Fprintln(tw, "LogID\tProtocol\tState\tTimestamp\tOperator\tName") for _, l := range logs { hash := sha256.Sum256(l.Key) - fmt.Fprintf(tw, "%s\t%s\t%s\t%d\t%s\n", + fmt.Fprintf(tw, "%s\t%s\t%s\t%s\t%d\t%s\n", base64.StdEncoding.EncodeToString(hash[:]), - l.State, l.Timestamp.UTC().Format(time.RFC3339), l.OperatorIndex, l.Name) + l.Protocol, l.State, l.Timestamp.UTC().Format(time.RFC3339), l.OperatorIndex, l.Name) } tw.Flush() }