rpm/checker.go (64 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 rpm
import (
"fmt"
"github.com/facebookincubator/nvdtools/wfn"
)
// Checker knows how to verify whether some package has been fixed or not
type Checker interface {
// Check should return whether a given package on distribution is fixed for some CVE
Check(pkg *Package, distro *wfn.Attributes, cve string) bool
}
// CheckAny returns a Checker which will return true if any of the underlying checkers returns true
func CheckAny(chks ...Checker) Checker {
return anyChecker(chks)
}
type anyChecker []Checker
// Check is part of the Checker interface
func (c anyChecker) Check(pkg *Package, distro *wfn.Attributes, cve string) bool {
for _, chk := range c {
if chk.Check(pkg, distro, cve) {
return true
}
}
return false
}
// CheckAll returns a Checker which will return true if all of the underlying checkers returns true
func CheckAll(chks ...Checker) Checker {
return allChecker(chks)
}
type allChecker []Checker
// Check is part of the Checker interface
func (c allChecker) Check(pkg *Package, distro *wfn.Attributes, cve string) bool {
if len(c) == 0 {
return false
}
for _, chk := range c {
if !chk.Check(pkg, distro, cve) {
return false
}
}
return true
}
// Check will parse package and distro and call given checker to return
func Check(chk Checker, pkg, distro, cve string) (bool, error) {
p, err := Parse(pkg)
if err != nil {
return false, fmt.Errorf("can't parse package %q: %v", pkg, err)
}
d, err := wfn.Parse(distro)
if err != nil {
return false, fmt.Errorf("can't parse distro cpe %q: %v", distro, err)
}
return chk.Check(p, d, cve), nil
}
// FilterFixedPackages will return those packages which haven't been fixed already on the given distro and for a given cve
// if some package can't be parsed as an rpm package, it will not be checked and will be included in the output list
func FilterFixedPackages(chk Checker, pkgs []string, distro, cve string) ([]string, error) {
d, err := wfn.Parse(distro)
if err != nil {
return nil, fmt.Errorf("can't parse distro cpe %q: %v", distro, err)
}
var filtered []string
for _, pkg := range pkgs {
p, err := Parse(pkg)
if err != nil {
filtered = append(filtered, pkg)
continue
}
if !chk.Check(p, d, cve) {
// if it hasn't been fixed for the given checker, append it
filtered = append(filtered, pkg)
}
}
return filtered, nil
}