1
0
Fork 0
mirror of https://github.com/gocsaf/csaf.git synced 2025-12-22 18:15:42 +01:00

Rfactoring to processor started.

This commit is contained in:
Sascha L. Teichmann 2021-12-15 17:44:13 +01:00
parent 145f9b77a8
commit d8ccf9ff41
2 changed files with 122 additions and 31 deletions

View file

@ -12,7 +12,6 @@ import (
"bufio" "bufio"
"bytes" "bytes"
"crypto/sha256" "crypto/sha256"
"encoding/json"
"fmt" "fmt"
"io" "io"
"net/http" "net/http"
@ -155,38 +154,10 @@ func (rc *redirectsCheck) run(p *processor, domain string) error {
} }
func (pmdc *providerMetadataCheck) run(p *processor, domain string) error { func (pmdc *providerMetadataCheck) run(p *processor, domain string) error {
url := "https://" + domain + "/.well-known/csaf/provider-metadata.json"
client := p.httpClient() if err := p.checkProviderMetadata(domain, pmdc.sprintf); err != nil {
req, err := http.NewRequest(http.MethodGet, url, nil)
if err != nil {
return err return err
} }
res, err := client.Do(req)
if err != nil {
pmdc.sprintf("Fetching provider metadata failed: %s.", err.Error())
return nil
}
defer res.Body.Close()
if res.StatusCode != http.StatusOK {
pmdc.sprintf("Status: %d (%s).", res.StatusCode, res.Status)
}
// Calculate checksum for later comparison.
hash := sha256.New()
if err := json.NewDecoder(io.TeeReader(res.Body, hash)).Decode(&p.pmd); err != nil {
pmdc.sprintf("Decoding JSON failed: %s.", err.Error())
}
p.pmd256 = hash.Sum(nil)
errors, err := csaf.ValidateProviderMetadata(p.pmd)
if err != nil {
return err
}
if len(errors) > 0 {
pmdc.add("Validating against JSON schema failed:")
pmdc.add(errors...)
}
pmdc.ok("No problems with provider metadata.") pmdc.ok("No problems with provider metadata.")
return nil return nil

View file

@ -9,6 +9,7 @@
package main package main
import ( import (
"bufio"
"bytes" "bytes"
"context" "context"
"crypto/sha256" "crypto/sha256"
@ -413,3 +414,122 @@ func (p *processor) checkCSAFs(domain string, lg func(string, ...interface{})) e
return nil return nil
} }
func (p *processor) checkProviderMetadata(domain string, lg func(string, ...interface{})) error {
client := p.httpClient()
url := "https://" + domain + "/.well-known/csaf/provider-metadata.json"
res, err := client.Get(url)
if err != nil {
lg("Fetching %s: %v.", url, err)
return err
}
if res.StatusCode != http.StatusOK {
lg("Fetching %s failed. Status code: %d (%s).",
url, res.StatusCode, res.Status)
return errors.New("Cannot load provider-metadata.json")
}
// Calculate checksum for later comparison.
hash := sha256.New()
if err := func() error {
defer res.Body.Close()
tee := io.TeeReader(res.Body, hash)
return json.NewDecoder(tee).Decode(&p.pmd)
}(); err != nil {
lg("Decoding JSON failed: %v.", err)
return err
}
p.pmd256 = hash.Sum(nil)
errors, err := csaf.ValidateProviderMetadata(p.pmd)
if err != nil {
return err
}
if len(errors) > 0 {
lg("Validating against JSON schema failed:")
for _, msg := range errors {
lg(strings.ReplaceAll(msg, `%`, `%%`))
}
}
return nil
}
func (p *processor) checkSecurity(domain string, lg func(string, ...interface{})) error {
client := p.httpClient()
path := "https://" + domain + "/.well-known/security.txt"
res, err := client.Get(path)
if err != nil {
return err
}
if res.StatusCode != http.StatusOK {
lg("Fetching %s failed. Status code %d (%s)",
path, res.StatusCode, res.Status)
return errors.New("fetching security.txt failed")
}
u, err := func() (string, error) {
defer res.Body.Close()
lines := bufio.NewScanner(res.Body)
for lines.Scan() {
line := lines.Text()
if strings.HasPrefix(line, "CSAF:") {
return strings.TrimSpace(line[6:]), nil
}
}
return "", lines.Err()
}()
if err != nil {
lg("Error while reading security.txt: %v", err)
return err
}
if u == "" {
lg("No CSAF line found in security.txt.")
return errors.New("no CSAF line in security.txt")
}
// Try to load
up, err := url.Parse(u)
if err != nil {
lg("CSAF URL '%s' invalid: %v.", u, err.Error())
return err
}
base, err := url.Parse("https://" + domain + "/.well-known/")
if err != nil {
return err
}
ur := base.ResolveReference(up)
u = ur.String()
p.checkTLS(u)
if res, err = client.Get(u); err != nil {
lg("Cannot fetch %s from security.txt: %v", u, err)
return nil
}
if res.StatusCode != http.StatusOK {
lg("Fetching %s failed. Status code %d (%s).",
u, res.StatusCode, res.Status)
return nil
}
defer res.Body.Close()
// Compare checksums to already read provider-metadata.json.
h := sha256.New()
if _, err := io.Copy(h, res.Body); err != nil {
lg("Reading %s failed: %v.", u, err)
return nil
}
if !bytes.Equal(h.Sum(nil), p.pmd256) {
lg("Content of %s from security.txt is not identical to .well-known/csaf/provider-metadata.json", u)
}
return nil
}