Fix OVAL detection on Debian and Ubuntu (#509)

* Add filter options to tui subcommand (#508)

* Capture version of source packages on Debian based linux

* Change makefile, gofmt -s

* Refactoring

* Implement OVAL detection of source packages for Debian, Ubuntu
This commit is contained in:
Kota Kanbe
2017-10-13 17:22:11 +09:00
committed by GitHub
parent 8e15b9ce1c
commit 5a0a6abf11
17 changed files with 492 additions and 315 deletions

View File

@@ -176,7 +176,6 @@ func (o *debian) checkDependencies() error {
}
for _, name := range packNames {
//TODO --show-format
cmd := "dpkg-query -W " + name
if r := o.exec(cmd, noSudo); !r.isSuccess() {
msg := fmt.Sprintf("%s is not installed", name)
@@ -206,12 +205,13 @@ func (o *debian) scanPackages() error {
RebootRequired: rebootRequired,
}
installed, updatable, err := o.scanInstalledPackages()
installed, updatable, srcPacks, err := o.scanInstalledPackages()
if err != nil {
o.log.Errorf("Failed to scan installed packages: %s", err)
return err
}
o.Packages = installed
o.SrcPackages = srcPacks
if config.Conf.Deep || o.Distro.Family == config.Raspbian {
unsecures, err := o.scanUnsecurePackages(updatable)
@@ -238,20 +238,26 @@ func (o *debian) rebootRequired() (bool, error) {
}
}
func (o *debian) scanInstalledPackages() (models.Packages, models.Packages, error) {
installed, updatable := models.Packages{}, models.Packages{}
r := o.exec(`dpkg-query -W -f='${binary:Package}\t${db:Status-Abbrev}\t${Version}\n'`, noSudo)
func (o *debian) scanInstalledPackages() (models.Packages, models.Packages, models.SrcPackages, error) {
installed, updatable, srcPacks := models.Packages{}, models.Packages{}, models.SrcPackages{}
r := o.exec(`dpkg-query -W -f='${binary:Package},${db:Status-Abbrev},${Version},${Source},${source:Version}\n'`, noSudo)
if !r.isSuccess() {
return nil, nil, fmt.Errorf("Failed to SSH: %s", r)
return nil, nil, nil, fmt.Errorf("Failed to SSH: %s", r)
}
// e.g.
// curl ii 7.47.0-1ubuntu2.2
// openssh-server rc 1:7.2p2-4ubuntu2.2
// e.g.
// curl,ii ,7.38.0-4+deb8u2,,7.38.0-4+deb8u2
// openssh-server,ii ,1:6.7p1-5+deb8u3,openssh,1:6.7p1-5+deb8u3
// tar,ii ,1.27.1-2+b1,tar (1.27.1-2),1.27.1-2
lines := strings.Split(r.Stdout, "\n")
for _, line := range lines {
if trimmed := strings.TrimSpace(line); len(trimmed) != 0 {
name, status, version, err := o.parseScannedPackagesLine(trimmed)
name, status, version, srcName, srcVersion, err := o.parseScannedPackagesLine(trimmed)
if err != nil {
return nil, nil, nil, fmt.Errorf(
"Debian: Failed to parse package line: %s", line)
}
packageStatus := status[1]
// Package status:
// n = Not-installed
@@ -266,20 +272,38 @@ func (o *debian) scanInstalledPackages() (models.Packages, models.Packages, erro
o.log.Debugf("%s package status is '%c', ignoring", name, packageStatus)
continue
}
if err != nil {
return nil, nil, fmt.Errorf(
"Debian: Failed to parse package line: %s", line)
}
installed[name] = models.Package{
Name: name,
Version: version,
}
if srcName != "" && srcName != name {
if pack, ok := srcPacks[srcName]; ok {
pack.AddBinaryName(name)
srcPacks[srcName] = pack
} else {
srcPacks[srcName] = models.SrcPackage{
Name: srcName,
Version: srcVersion,
BinaryNames: []string{name},
}
}
}
}
}
// Remove "linux"
// kernel-related packages are showed "linux" as source package name
// If "linux" is left, oval detection will cause trouble, so delete.
delete(srcPacks, "linux")
// Remove duplicate
for name := range installed {
delete(srcPacks, name)
}
updatableNames, err := o.getUpdatablePackNames()
if err != nil {
return nil, nil, err
return nil, nil, nil, err
}
for _, name := range updatableNames {
for _, pack := range installed {
@@ -293,29 +317,30 @@ func (o *debian) scanInstalledPackages() (models.Packages, models.Packages, erro
// Fill the candidate versions of upgradable packages
err = o.fillCandidateVersion(updatable)
if err != nil {
return nil, nil, fmt.Errorf("Failed to fill candidate versions. err: %s", err)
return nil, nil, nil, fmt.Errorf("Failed to fill candidate versions. err: %s", err)
}
installed.MergeNewVersion(updatable)
return installed, updatable, nil
return installed, updatable, srcPacks, nil
}
var packageLinePattern = regexp.MustCompile(`^([^\t']+)\t(.+)\t(.+)$`)
func (o *debian) parseScannedPackagesLine(line string) (name, status, version string, err error) {
result := packageLinePattern.FindStringSubmatch(line)
if len(result) == 4 {
func (o *debian) parseScannedPackagesLine(line string) (name, status, version, srcName, srcVersion string, err error) {
ss := strings.Split(line, ",")
if len(ss) == 5 {
// remove :amd64, i386...
name = result[1]
name = ss[0]
if i := strings.IndexRune(name, ':'); i >= 0 {
name = name[:i]
}
status = result[2]
version = result[3]
status = ss[1]
version = ss[2]
// remove version. ex: tar (1.27.1-2)
srcName = strings.Split(ss[3], " ")[0]
srcVersion = ss[4]
return
}
return "", "", "", fmt.Errorf("Unknown format: %s", line)
return "", "", "", "", "", fmt.Errorf("Unknown format: %s", line)
}
func (o *debian) aptGetUpdate() error {