providers/redhat/check/check_cve.go (84 lines of code) (raw):

// Copyright (c) Facebook, Inc. and its affiliates. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package check import ( "errors" "fmt" "github.com/facebookincubator/nvdtools/providers/redhat/schema" "github.com/facebookincubator/nvdtools/rpm" "github.com/facebookincubator/nvdtools/wfn" ) var ErrCheckers = errors.New("no applicable checkers") func CVEChecker(cve *schema.CVE) (rpm.Checker, error) { var chks []rpm.Checker archks, err := affectedReleaseCheckers(cve) if err != nil { return nil, fmt.Errorf("can't construct checkers for affected release: %v", err) } chks = archks pschks, err := packageStateCheckers(cve) if err != nil { return nil, fmt.Errorf("can't construct checkers for package state: %v", err) } chks = append(chks, pschks...) if len(chks) == 0 { return nil, ErrCheckers } return &cveChecker{cve.Name, chks}, nil } func affectedReleaseCheckers(cve *schema.CVE) ([]rpm.Checker, error) { var chks []rpm.Checker for _, ar := range cve.AffectedRelease { if ar.CPE == "" { continue } d, err := wfn.Parse(ar.CPE) if err != nil { return nil, fmt.Errorf("can't parse distro cpe %q: %v", ar.CPE, err) } // XXX we need to do this because RedHat sometimes sets `a` as part for RHEL-X, when it should be `o` d.Part = wfn.Any var pc pkgCheck = constPkgChecker(true) // match all packages if ar.Package != "" { // add .src to parse it correctly, they're all src rpms if p, err := rpm.Parse(ar.Package + ".src"); err == nil { pc = affectedReleasePkgChecker(*p) } } chks = append(chks, &singleChecker{d, pc}) } return chks, nil } func packageStateCheckers(cve *schema.CVE) ([]rpm.Checker, error) { var chks []rpm.Checker for _, ps := range cve.PackageState { if ps.FixState != "" && !schema.IsFixed(ps.FixState) { // if the package hasn't been fixed, continue continue } if ps.CPE == "" { continue } d, err := wfn.Parse(ps.CPE) if err != nil { return nil, fmt.Errorf("can't parse distro cpe %q: %v", ps.CPE, err) } // XXX we need to do this because RedHat sometimes sets `a` as part for RHEL-X, when it should be `o` d.Part = wfn.Any var pc pkgCheck = constPkgChecker(true) // match all packages if ps.PackageName != "" { pc = packageStatePkgChecker(ps.PackageName) } chks = append(chks, &singleChecker{d, pc}) } return chks, nil } // this is an or checker, if any of checkers returns true, result is true type cveChecker struct { cve string chks []rpm.Checker } // Check is part of the rpm.Check interface func (c *cveChecker) Check(pkg *rpm.Package, distro *wfn.Attributes, cve string) bool { if cve != c.cve { return false } for _, chk := range c.chks { if chk.Check(pkg, distro, cve) { return true } } return false }