diff --git a/cmd/csaf_checker/processor.go b/cmd/csaf_checker/processor.go index 7b94660..c883fd2 100644 --- a/cmd/csaf_checker/processor.go +++ b/cmd/csaf_checker/processor.go @@ -54,22 +54,24 @@ type processor struct { keys *crypto.KeyRing labelChecker *rolieLabelChecker - invalidAdvisories topicMessages - badFilenames topicMessages - badIntegrities topicMessages - badPGPs topicMessages - badSignatures topicMessages - badProviderMetadata topicMessages - badSecurity topicMessages - badIndices topicMessages - badChanges topicMessages - badFolders topicMessages - badWellknownMetadata topicMessages - badDNSPath topicMessages - badDirListings topicMessages - badROLIEFeed topicMessages - badROLIEService topicMessages - badROLIECategory topicMessages + invalidAdvisories topicMessages + badFilenames topicMessages + badIntegrities topicMessages + badPGPs topicMessages + badSignatures topicMessages + badProviderMetadata topicMessages + badSecurity topicMessages + badIndices topicMessages + badChanges topicMessages + badFolders topicMessages + badWellknownMetadata topicMessages + badDNSPath topicMessages + badDirListings topicMessages + badROLIEFeed topicMessages + badROLIEService topicMessages + badROLIECategory topicMessages + badWhitePermissions topicMessages + badAmberRedPermissions topicMessages expr *util.PathEval } @@ -238,6 +240,8 @@ func (p *processor) clean() { p.badROLIEFeed.reset() p.badROLIEService.reset() p.badROLIECategory.reset() + p.badWhitePermissions.reset() + p.badAmberRedPermissions.reset() p.labelChecker = nil } diff --git a/cmd/csaf_checker/reporters.go b/cmd/csaf_checker/reporters.go index bce05c4..dfafc6c 100644 --- a/cmd/csaf_checker/reporters.go +++ b/cmd/csaf_checker/reporters.go @@ -152,16 +152,34 @@ func (r *tlsReporter) report(p *processor, domain *Domain) { // report tests if a document labeled TLP:WHITE // is freely accessible and sets the "message" field value // of the "Requirement" struct as a result of that. -func (r *tlpWhiteReporter) report(_ *processor, _ *Domain) { - // TODO +func (r *tlpWhiteReporter) report(p *processor, domain *Domain) { + req := r.requirement(domain) + if !p.badWhitePermissions.used() { + req.message(InfoType, "No advisories labeled TLP:WHITE tested for accessibility.") + return + } + if len(p.badWhitePermissions) == 0 { + req.message(InfoType, "All advisories labeled TLP:WHITE were freely accessible.") + return + } + req.Messages = p.badWhitePermissions } // report tests if a document labeled TLP:AMBER // or TLP:RED is access protected // and sets the "message" field value // of the "Requirement" struct as a result of that. -func (r *tlpAmberRedReporter) report(_ *processor, _ *Domain) { - // TODO +func (r *tlpAmberRedReporter) report(p *processor, domain *Domain) { + req := r.requirement(domain) + if !p.badAmberRedPermissions.used() { + req.message(InfoType, "No advisories labeled TLP:AMBER or TLP:RED tested for accessibility.") + return + } + if len(p.badAmberRedPermissions) == 0 { + req.message(InfoType, "All tested advisories labeled TLP:WHITE or TLP:RED were access-protected.") + return + } + req.Messages = p.badAmberRedPermissions } // report tests if redirects are used and sets the "message" field value diff --git a/cmd/csaf_checker/roliecheck.go b/cmd/csaf_checker/roliecheck.go index 19b0c29..96f6618 100644 --- a/cmd/csaf_checker/roliecheck.go +++ b/cmd/csaf_checker/roliecheck.go @@ -9,6 +9,7 @@ package main import ( + "crypto/tls" "net/http" "net/url" "sort" @@ -24,10 +25,12 @@ type rolieLabelChecker struct { feedURL string feedLabel csaf.TLPLabel - advisories map[csaf.TLPLabel]util.Set[string] + advisories map[csaf.TLPLabel]util.Set[string] + basicClient *http.Client } // tlpLevel returns an inclusion order of TLP colors. +// TODO: Is this the right location to put the p.[...].use()? func tlpLevel(label csaf.TLPLabel) int { switch label { case csaf.TLPLabelWhite: @@ -52,6 +55,17 @@ func tlpLabel(label *csaf.TLPLabel) csaf.TLPLabel { return csaf.TLPLabelUnlabeled } +// createBasicClient creates and returns a http Client +func (p *processor) createBasicClient() *http.Client { + if p.opts.Insecure { + tr := &http.Transport{ + TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, + } + return &http.Client{Transport: tr} + } + return &http.Client{} +} + // check tests if in advisory is in the right TLP color of the // currently tested feed. func (ca *rolieLabelChecker) check( @@ -94,6 +108,34 @@ func (ca *rolieLabelChecker) check( "%s of TLP level %s must not be listed in feed %s of TLP level %s", advisory, advisoryLabel, ca.feedURL, ca.feedLabel) } + + switch { + case advisoryRank == 1: + p.badWhitePermissions.use() + case advisoryRank > 2: + p.badAmberRedPermissions.use() + } + + res, err := ca.basicClient.Get(advisory) + if err != nil { + switch { + case advisoryRank == 1: + p.badWhitePermissions.error("Unexpected Error %v when trying to fetch: %s", err, advisory) + case advisoryRank > 2: + p.badAmberRedPermissions.error("Unexpected Error %v when trying to fetch: %s", err, advisory) + } + } + switch res.StatusCode { + case http.StatusOK: + if advisoryRank > 2 { + p.badAmberRedPermissions.error("Advisory %s of TLP level %v is not properly access protected.", advisory, advisoryLabel) + } + case http.StatusForbidden: + if advisoryRank == 1 { + // TODO: Differentiate between error and warning based on whether the advisory appears in a not access protected location as well. + p.badWhitePermissions.warn("Advisory %s of TLP level WHITE is access protected.", advisory) + } + } } // processROLIEFeeds goes through all ROLIE feeds and checks their @@ -135,7 +177,8 @@ func (p *processor) processROLIEFeeds(feeds [][]csaf.Feed) error { } } p.labelChecker = &rolieLabelChecker{ - advisories: map[csaf.TLPLabel]util.Set[string]{}, + advisories: map[csaf.TLPLabel]util.Set[string]{}, + basicClient: p.createBasicClient(), } // Phase 2: check for integrity.