1
0
Fork 0
mirror of https://github.com/gocsaf/csaf.git synced 2025-12-22 05:40:11 +01:00

Improve hash fetching and logging

This commit is contained in:
koplas 2024-11-22 16:31:56 +01:00
parent c0de0c2b6d
commit d18d2c3bf1
2 changed files with 85 additions and 28 deletions

View file

@ -44,8 +44,8 @@ const (
type hashAlgorithm string type hashAlgorithm string
const ( const (
algSha256 = hashAlgorithm("SHA256") algSha256 = hashAlgorithm("SHA256")
algSha2512 = hashAlgorithm("SHA512") algSha512 = hashAlgorithm("SHA512")
) )
type config struct { type config struct {

View file

@ -25,6 +25,7 @@ import (
"os" "os"
"path" "path"
"path/filepath" "path/filepath"
"slices"
"strconv" "strconv"
"strings" "strings"
"sync" "sync"
@ -37,6 +38,13 @@ import (
"github.com/csaf-poc/csaf_distribution/v3/util" "github.com/csaf-poc/csaf_distribution/v3/util"
) )
type hashFetchInfo struct {
url string
preferred bool
warn bool
hashType hashAlgorithm
}
type downloader struct { type downloader struct {
cfg *config cfg *config
keys *crypto.KeyRing keys *crypto.KeyRing
@ -496,35 +504,39 @@ nextAdvisory:
signData []byte signData []byte
) )
if (d.cfg.PreferredHash != "sha512" || file.SHA512URL() == "") && file.SHA256URL() != "" { hashToFetch := []hashFetchInfo{}
// Only hash when we have a remote counterpart we can compare it with. if file.SHA512URL() != "" {
if remoteSHA256, s256Data, err = loadHash(client, file.SHA256URL()); err != nil { hashToFetch = append(hashToFetch, hashFetchInfo{
if !file.IsDirectory() { url: file.SHA512URL(),
slog.Warn("Cannot fetch SHA256", warn: true,
"url", file.SHA256URL(), hashType: algSha512,
"error", err) preferred: strings.EqualFold(string(d.cfg.PreferredHash), string(algSha512))})
} else { } else {
slog.Info("SHA256 not present", "file", file.URL()) slog.Info("SHA512 not present")
} }
} else { if file.SHA256URL() != "" {
s256 = sha256.New() hashToFetch = append(hashToFetch, hashFetchInfo{
writers = append(writers, s256) url: file.SHA256URL(),
warn: true,
hashType: algSha256,
preferred: strings.EqualFold(string(d.cfg.PreferredHash), string(algSha256))})
} else {
slog.Info("SHA256 not present")
}
if file.IsDirectory() {
for i := range hashToFetch {
hashToFetch[i].warn = false
} }
} }
if (d.cfg.PreferredHash != "sha256" || file.SHA256URL() == "") && file.SHA512URL() != "" { remoteSHA256, s256Data, remoteSHA512, s512Data = loadHashes(client, hashToFetch)
if remoteSHA512, s512Data, err = loadHash(client, file.SHA512URL()); err != nil { if remoteSHA512 != nil {
if !file.IsDirectory() { s512 = sha512.New()
slog.Warn("Cannot fetch SHA512", writers = append(writers, s512)
"url", file.SHA512URL(), }
"error", err) if remoteSHA256 != nil {
} else { s256 = sha256.New()
slog.Info("SHA512 not present", "file", file.URL()) writers = append(writers, s256)
}
} else {
s512 = sha512.New()
writers = append(writers, s512)
}
} }
// Remember the data as we need to store it to file later. // Remember the data as we need to store it to file later.
@ -755,6 +767,51 @@ func loadSignature(client util.Client, p string) (*crypto.PGPSignature, []byte,
return sign, data, nil return sign, data, nil
} }
func loadHashes(client util.Client, hashes []hashFetchInfo) ([]byte, []byte, []byte, []byte) {
var remoteSha256, remoteSha512, sha256Data, sha512Data []byte
// Load preferred hashes first
slices.SortStableFunc(hashes, func(a, b hashFetchInfo) int {
if a.preferred == b.preferred {
return 0
}
if a.preferred && !b.preferred {
return -1
} else {
return 1
}
})
for _, h := range hashes {
if remote, data, err := loadHash(client, h.url); err != nil {
if h.warn {
slog.Warn("Cannot fetch hash",
"hash", h.hashType,
"url", h.url,
"error", err)
} else {
slog.Info("Hash not present", "hash", h.hashType, "file", h.url)
}
} else {
switch h.hashType {
case algSha512:
{
remoteSha512 = remote
sha512Data = data
}
case algSha256:
{
remoteSha256 = remote
sha256Data = data
}
}
if h.preferred {
break
}
}
}
return remoteSha256, sha256Data, remoteSha512, sha512Data
}
func loadHash(client util.Client, p string) ([]byte, []byte, error) { func loadHash(client util.Client, p string) ([]byte, []byte, error) {
resp, err := client.Get(p) resp, err := client.Get(p)
if err != nil { if err != nil {