diff --git a/cmd/csaf_checker/processor.go b/cmd/csaf_checker/processor.go index de42e184..38f3e34b 100644 --- a/cmd/csaf_checker/processor.go +++ b/cmd/csaf_checker/processor.go @@ -895,15 +895,7 @@ func (p *processor) checkIndex(base string, mask whereType) error { continue } - SHA256 := p.checkURL(u + ".sha256") - SHA512 := p.checkURL(u + ".sha512") - sign := p.checkURL(u + ".asc") - files = append(files, csaf.PlainAdvisoryFile{ - Path: u, - SHA256: SHA256, - SHA512: SHA512, - Sign: sign, - }) + files = append(files, csaf.DirectoryAdvisoryFile{Path: u}) } return files, scanner.Err() }() @@ -921,15 +913,6 @@ func (p *processor) checkIndex(base string, mask whereType) error { return p.integrity(files, base, mask, p.badIndices.add) } -// checkURL returns the URL if it is accessible. -func (p *processor) checkURL(url string) string { - _, err := p.client.Head(url) - if err != nil { - return url - } - return "" -} - // checkChanges fetches the "changes.csv" and calls the "checkTLS" method for HTTPs checks. // It extracts the file content, tests the column number and the validity of the time format // of the fields' values and if they are sorted properly. Then it passes the files to the @@ -995,13 +978,9 @@ func (p *processor) checkChanges(base string, mask whereType) error { } path := r[pathColumn] - SHA256 := p.checkURL(path + ".sha256") - SHA512 := p.checkURL(path + ".sha512") - sign := p.checkURL(path + ".asc") - times, files = append(times, t), - append(files, csaf.PlainAdvisoryFile{Path: path, SHA256: SHA256, SHA512: SHA512, Sign: sign}) + append(files, csaf.DirectoryAdvisoryFile{Path: path}) } return times, files, nil }() diff --git a/cmd/csaf_downloader/downloader.go b/cmd/csaf_downloader/downloader.go index 025ed65c..3bf36479 100644 --- a/cmd/csaf_downloader/downloader.go +++ b/cmd/csaf_downloader/downloader.go @@ -501,31 +501,31 @@ nextAdvisory: signData []byte ) - if file.SHA256URL() == "" { - slog.Info("SHA256 not present", "file", file.URL()) - } else { - // Only hash when we have a remote counterpart we can compare it with. - if remoteSHA256, s256Data, err = loadHash(client, file.SHA256URL()); err != nil { + // Only hash when we have a remote counterpart we can compare it with. + if remoteSHA256, s256Data, err = loadHash(client, file.SHA256URL()); err != nil { + if !file.IsDirectory() { slog.Warn("Cannot fetch SHA256", "url", file.SHA256URL(), "error", err) } else { - s256 = sha256.New() - writers = append(writers, s256) + slog.Info("SHA256 not present", "file", file.URL()) } + } else { + s256 = sha256.New() + writers = append(writers, s256) } - if file.SHA512URL() == "" { - slog.Info("SHA512 not present", "file", file.URL()) - } else { - if remoteSHA512, s512Data, err = loadHash(client, file.SHA512URL()); err != nil { + if remoteSHA512, s512Data, err = loadHash(client, file.SHA512URL()); err != nil { + if !file.IsDirectory() { slog.Warn("Cannot fetch SHA512", "url", file.SHA512URL(), "error", err) } else { - s512 = sha512.New() - writers = append(writers, s512) + slog.Info("SHA512 not present", "file", file.URL()) } + } else { + s512 = sha512.New() + writers = append(writers, s512) } // Remember the data as we need to store it to file later. @@ -757,6 +757,9 @@ func loadSignature(client util.Client, p string) (*crypto.PGPSignature, []byte, } func loadHash(client util.Client, p string) ([]byte, []byte, error) { + if p == "" { + return nil, nil, fmt.Errorf("no hash path provided") + } resp, err := client.Get(p) if err != nil { return nil, nil, err diff --git a/csaf/advisories.go b/csaf/advisories.go index 4aa7f52f..d05331c2 100644 --- a/csaf/advisories.go +++ b/csaf/advisories.go @@ -29,11 +29,10 @@ type AdvisoryFile interface { SHA256URL() string SHA512URL() string SignURL() string + IsDirectory() bool } -// PlainAdvisoryFile is a simple implementation of checkFile. -// The hash and signature files are directly constructed by extending -// the file name. +// PlainAdvisoryFile contains all relevant urls of a remote file. type PlainAdvisoryFile struct { Path string SHA256 string @@ -53,11 +52,41 @@ func (paf PlainAdvisoryFile) SHA512URL() string { return paf.SHA512 } // SignURL returns the URL of signature file of this advisory. func (paf PlainAdvisoryFile) SignURL() string { return paf.Sign } +// IsDirectory returns true, if was fetched via directory feeds. +func (paf PlainAdvisoryFile) IsDirectory() bool { return false } + // LogValue implements [slog.LogValuer] func (paf PlainAdvisoryFile) LogValue() slog.Value { return slog.GroupValue(slog.String("url", paf.URL())) } +// DirectoryAdvisoryFile only contains the base file path. +// The hash and signature files are directly constructed by extending +// the file name. +type DirectoryAdvisoryFile struct { + Path string +} + +// URL returns the URL of this advisory. +func (daf DirectoryAdvisoryFile) URL() string { return daf.Path } + +// SHA256URL returns the URL of SHA256 hash file of this advisory. +func (daf DirectoryAdvisoryFile) SHA256URL() string { return daf.Path + ".sha256" } + +// SHA512URL returns the URL of SHA512 hash file of this advisory. +func (daf DirectoryAdvisoryFile) SHA512URL() string { return daf.Path + ".sha512" } + +// SignURL returns the URL of signature file of this advisory. +func (daf DirectoryAdvisoryFile) SignURL() string { return daf.Path + ".asc" } + +// IsDirectory returns true, if was fetched via directory feeds. +func (daf DirectoryAdvisoryFile) IsDirectory() bool { return true } + +// LogValue implements [slog.LogValuer] +func (daf DirectoryAdvisoryFile) LogValue() slog.Value { + return slog.GroupValue(slog.String("url", daf.URL())) +} + // AdvisoryFileProcessor implements the extraction of // advisory file names from a given provider metadata. type AdvisoryFileProcessor struct { @@ -69,7 +98,7 @@ type AdvisoryFileProcessor struct { base *url.URL } -// NewAdvisoryFileProcessor constructs an filename extractor +// NewAdvisoryFileProcessor constructs a filename extractor // for a given metadata document. func NewAdvisoryFileProcessor( client util.Client, @@ -176,15 +205,6 @@ func (afp *AdvisoryFileProcessor) Process( return nil } -// checkURL returns the URL if it is accessible. -func (afp *AdvisoryFileProcessor) checkURL(url string) string { - _, err := afp.client.Head(url) - if err != nil { - return url - } - return "" -} - // loadChanges loads baseURL/changes.csv and returns a list of files // prefixed by baseURL/. func (afp *AdvisoryFileProcessor) loadChanges( @@ -242,18 +262,8 @@ func (afp *AdvisoryFileProcessor) loadChanges( continue } - self := base.JoinPath(path).String() - sha256 := afp.checkURL(self + ".sha256") - sha512 := afp.checkURL(self + ".sha512") - sign := afp.checkURL(self + ".asc") - files = append(files, - PlainAdvisoryFile{ - Path: path, - SHA256: sha256, - SHA512: sha512, - Sign: sign, - }) + DirectoryAdvisoryFile{Path: base.JoinPath(path).String()}) } return files, nil }