From 04d2c96be0809c1307c939bdfd91392b8c51fde0 Mon Sep 17 00:00:00 2001 From: Bernhard Herzog Date: Tue, 25 Apr 2023 17:08:14 +0200 Subject: [PATCH 1/8] Add IDMatchesFilename function --- util/file.go | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/util/file.go b/util/file.go index b4f44cf..266d720 100644 --- a/util/file.go +++ b/util/file.go @@ -9,6 +9,7 @@ package util import ( + "fmt" "io" "math/rand" "os" @@ -38,6 +39,23 @@ func ConformingFileName(fname string) bool { return fname == CleanFileName(fname) } +// IDMatchesFilename checks that filename can be derived from the value +// of document/tracking/id extracted from doc using eval. +// https://docs.oasis-open.org/csaf/csaf/v2.0/os/csaf-v2.0-os.html#51-filename +func IDMatchesFilename(eval *PathEval, doc any, filename string) error { + var id string + if err := eval.Extract(`$.document.tracking.id`, StringMatcher(&id), false, doc); err != nil { + return fmt.Errorf("check that ID matches filename: %v", err) + } + + if CleanFileName(id) != filename { + return fmt.Errorf("document/tracking/id %q does not match filename %s", + id, filename) + } + + return nil +} + // PathExists returns true if path exits. func PathExists(path string) (bool, error) { _, err := os.Stat(path) From a92c033a5e68c451b3b34a0c6e53ded2ea6a4bdd Mon Sep 17 00:00:00 2001 From: Bernhard Herzog Date: Tue, 25 Apr 2023 18:28:07 +0200 Subject: [PATCH 2/8] Check that filename matches ID in csaf_downloader --- cmd/csaf_downloader/downloader.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cmd/csaf_downloader/downloader.go b/cmd/csaf_downloader/downloader.go index 00c4a19..4441805 100644 --- a/cmd/csaf_downloader/downloader.go +++ b/cmd/csaf_downloader/downloader.go @@ -368,6 +368,11 @@ func (d *downloader) downloadFiles(label csaf.TLPLabel, files []csaf.AdvisoryFil continue } + if err := util.IDMatchesFilename(d.eval, doc, filename); err != nil { + log.Printf("Ignoring %s: %s.\n", file.URL(), err) + continue + } + // Validate against remote validator if d.validator != nil { rvr, err := d.validator.Validate(doc) From 900da9168721e216bbfc57dd1066c4cb3a33c531 Mon Sep 17 00:00:00 2001 From: Bernhard Herzog Date: Tue, 25 Apr 2023 18:38:49 +0200 Subject: [PATCH 3/8] Check that filename matches ID in csaf_validator --- cmd/csaf_validator/main.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/cmd/csaf_validator/main.go b/cmd/csaf_validator/main.go index 78708a5..412200a 100644 --- a/cmd/csaf_validator/main.go +++ b/cmd/csaf_validator/main.go @@ -54,6 +54,7 @@ func main() { func run(opts *options, files []string) error { var validator csaf.RemoteValidator + eval := util.NewPathEval() if opts.RemoteValidator != "" { validatorOptions := csaf.RemoteValidatorOptions{ @@ -109,6 +110,13 @@ func run(opts *options, files []string) error { } else { fmt.Printf("%q passes the schema validation.\n", file) } + + // Check filename agains ID + if err := util.IDMatchesFilename(eval, doc, filepath.Base(file)); err != nil { + log.Printf("%s: %s.\n", file, err) + continue + } + // Validate against remote validator. if validator != nil { rvr, err := validator.Validate(doc) From c37b127d820dfe364b20e4355db185fede90371a Mon Sep 17 00:00:00 2001 From: Bernhard Herzog Date: Tue, 25 Apr 2023 19:24:59 +0200 Subject: [PATCH 4/8] Check that filename matches ID in csaf_checker --- cmd/csaf_checker/processor.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/cmd/csaf_checker/processor.go b/cmd/csaf_checker/processor.go index 05dbc60..a9f9e10 100644 --- a/cmd/csaf_checker/processor.go +++ b/cmd/csaf_checker/processor.go @@ -423,6 +423,7 @@ func (p *processor) integrity( client := p.httpClient() var data bytes.Buffer + eval := util.NewPathEval() makeAbs := func(u *url.URL) *url.URL { if u.IsAbs() { @@ -512,6 +513,13 @@ func (p *processor) integrity( p.invalidAdvisories.error("CSAF file %s has %d validation errors.", u, len(errors)) } + if err := util.IDMatchesFilename(eval, doc, filepath.Base(u)); err != nil { + + p.invalidAdvisories.error("%s: %v\n", u, err) + continue + + } + // Validate against remote validator. if p.validator != nil { if rvr, err := p.validator.Validate(doc); err != nil { From 6a91c29baf98d5b344c6622403c0a9a3de25e392 Mon Sep 17 00:00:00 2001 From: Bernhard Herzog Date: Tue, 9 May 2023 18:46:00 +0200 Subject: [PATCH 5/8] Check that filename matches ID in csaf_provider --- cmd/csaf_provider/actions.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cmd/csaf_provider/actions.go b/cmd/csaf_provider/actions.go index 83101d0..084f52f 100644 --- a/cmd/csaf_provider/actions.go +++ b/cmd/csaf_provider/actions.go @@ -196,6 +196,11 @@ func (c *controller) upload(r *http.Request) (any, error) { return nil, err } + if util.CleanFileName(ex.ID) != newCSAF { + return nil, fmt.Errorf("ID %q does not match filename %s", + ex.ID, newCSAF) + } + // Check if we have to search for dynamic categories. var dynamicCategories []string if catExprs := c.cfg.DynamicCategories(); len(catExprs) > 0 { From 5b4c621616323a84e662bb8dfeb79c78f6f939b4 Mon Sep 17 00:00:00 2001 From: Bernhard Herzog Date: Tue, 9 May 2023 20:06:58 +0200 Subject: [PATCH 6/8] Check that filename matches ID in csaf_aggregator --- cmd/csaf_aggregator/mirror.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cmd/csaf_aggregator/mirror.go b/cmd/csaf_aggregator/mirror.go index a6ef984..a17a180 100644 --- a/cmd/csaf_aggregator/mirror.go +++ b/cmd/csaf_aggregator/mirror.go @@ -557,6 +557,11 @@ func (w *worker) mirrorFiles(tlpLabel csaf.TLPLabel, files []csaf.AdvisoryFile) continue } + if util.CleanFileName(sum.ID) != filename { + log.Printf("ID %q does not match filename %s", + sum.ID, filename) + } + if err := w.extractCategories(label, advisory); err != nil { log.Printf("error: %s: %v\n", file, err) continue From 821f018a98e8eaae61418d2baf015f9a3824e8c4 Mon Sep 17 00:00:00 2001 From: Bernhard Herzog Date: Thu, 11 May 2023 13:54:42 +0200 Subject: [PATCH 7/8] Check that filename matches ID in csaf_uploader --- cmd/csaf_uploader/main.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cmd/csaf_uploader/main.go b/cmd/csaf_uploader/main.go index 6ac5027..0b7fe56 100644 --- a/cmd/csaf_uploader/main.go +++ b/cmd/csaf_uploader/main.go @@ -243,6 +243,11 @@ func (p *processor) uploadRequest(filename string) (*http.Request, error) { writeStrings("Errors:", errs) return nil, errors.New("local schema check failed") } + + eval := util.NewPathEval() + if err := util.IDMatchesFilename(eval, doc, filepath.Base(filename)); err != nil { + return nil, err + } } body := new(bytes.Buffer) From c4e9637f2b42a709099fe9acbe9779c4999ff520 Mon Sep 17 00:00:00 2001 From: "Sascha L. Teichmann" Date: Thu, 11 May 2023 15:25:31 +0200 Subject: [PATCH 8/8] Re-use eval of processor. --- cmd/csaf_checker/processor.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/cmd/csaf_checker/processor.go b/cmd/csaf_checker/processor.go index a9f9e10..b82a601 100644 --- a/cmd/csaf_checker/processor.go +++ b/cmd/csaf_checker/processor.go @@ -423,7 +423,6 @@ func (p *processor) integrity( client := p.httpClient() var data bytes.Buffer - eval := util.NewPathEval() makeAbs := func(u *url.URL) *url.URL { if u.IsAbs() { @@ -513,8 +512,7 @@ func (p *processor) integrity( p.invalidAdvisories.error("CSAF file %s has %d validation errors.", u, len(errors)) } - if err := util.IDMatchesFilename(eval, doc, filepath.Base(u)); err != nil { - + if err := util.IDMatchesFilename(p.expr, doc, filepath.Base(u)); err != nil { p.invalidAdvisories.error("%s: %v\n", u, err) continue