diff --git a/oval/debian.go b/oval/debian.go index f2cd8760..7756bd79 100644 --- a/oval/debian.go +++ b/oval/debian.go @@ -96,7 +96,7 @@ func (o DebianBase) update(r *models.ScanResult, defPacks defPacks) { for _, pack := range vinfo.AffectedPackages { defPacks.actuallyAffectedPackNames[pack.Name] = true } - vinfo.AffectedPackages = defPacks.toPackStatuses() + vinfo.AffectedPackages = defPacks.toPackStatuses(r.Family, r.Packages) vinfo.AffectedPackages.Sort() r.ScannedCves[defPacks.def.Debian.CveID] = vinfo } diff --git a/oval/redhat.go b/oval/redhat.go index 1b24e91a..cd5c28f5 100644 --- a/oval/redhat.go +++ b/oval/redhat.go @@ -100,7 +100,7 @@ func (o RedHatBase) update(r *models.ScanResult, defPacks defPacks) { for _, pack := range vinfo.AffectedPackages { defPacks.actuallyAffectedPackNames[pack.Name] = true } - vinfo.AffectedPackages = defPacks.toPackStatuses() + vinfo.AffectedPackages = defPacks.toPackStatuses(r.Family, r.Packages) vinfo.AffectedPackages.Sort() r.ScannedCves[cve.CveID] = vinfo } diff --git a/oval/util.go b/oval/util.go index ca2b553a..0527756b 100644 --- a/oval/util.go +++ b/oval/util.go @@ -44,17 +44,77 @@ type defPacks struct { actuallyAffectedPackNames map[string]bool } -func (e defPacks) toPackStatuses() (ps models.PackageStatuses) { - packNotFixedYet := map[string]bool{} - for _, p := range e.def.AffectedPacks { - packNotFixedYet[p.Name] = p.NotFixedYet - } - for k := range e.actuallyAffectedPackNames { - ps = append(ps, models.PackageStatus{ - Name: k, - NotFixedYet: packNotFixedYet[k], - }) +func (e defPacks) toPackStatuses(family string, packs models.Packages) (ps models.PackageStatuses) { + switch family { + case config.Ubuntu: + packNotFixedYet := map[string]bool{} + for _, p := range e.def.AffectedPacks { + packNotFixedYet[p.Name] = p.NotFixedYet + } + for k := range e.actuallyAffectedPackNames { + ps = append(ps, models.PackageStatus{ + Name: k, + NotFixedYet: packNotFixedYet[k], + }) + } + + case config.CentOS: + // There are many packages that has been fixed in RedHat, but not been fixed in CentOS + for name := range e.actuallyAffectedPackNames { + pack, ok := packs[name] + if !ok { + util.Log.Warnf("Faild to find in Package list: %s", name) + return + } + + ovalPackVer := "" + for _, p := range e.def.AffectedPacks { + if p.Name == name { + ovalPackVer = p.Version + break + } + } + if ovalPackVer == "" { + util.Log.Warnf("Faild to find in Oval Package list: %s", name) + return + } + + packNewVer := fmt.Sprintf("%s-%s", pack.NewVersion, pack.NewRelease) + if packNewVer == "" { + // compare version: installed vs oval + vera := rpmver.NewVersion(fmt.Sprintf("%s-%s", pack.Version, pack.Release)) + verb := rpmver.NewVersion(ovalPackVer) + notFixedYet := false + if vera.LessThan(verb) { + notFixedYet = true + } + ps = append(ps, models.PackageStatus{ + Name: name, + NotFixedYet: notFixedYet, + }) + } else { + // compare version: newVer vs oval + vera := rpmver.NewVersion(packNewVer) + verb := rpmver.NewVersion(ovalPackVer) + notFixedYet := false + if vera.LessThan(verb) { + notFixedYet = true + } + ps = append(ps, models.PackageStatus{ + Name: name, + NotFixedYet: notFixedYet, + }) + } + } + + default: + for k := range e.actuallyAffectedPackNames { + ps = append(ps, models.PackageStatus{ + Name: k, + }) + } } + return } diff --git a/oval/util_test.go b/oval/util_test.go index 6c8879ef..241b16af 100644 --- a/oval/util_test.go +++ b/oval/util_test.go @@ -100,27 +100,37 @@ func TestUpsert(t *testing.T) { } func TestDefpacksToPackStatuses(t *testing.T) { + type in struct { + dp defPacks + family string + packs models.Packages + } var tests = []struct { - in defPacks + in in out models.PackageStatuses }{ + // Ubuntu { - in: defPacks{ - def: ovalmodels.Definition{ - AffectedPacks: []ovalmodels.Package{ - { - Name: "a", - NotFixedYet: true, - }, - { - Name: "b", - NotFixedYet: false, + in: in{ + family: "ubuntu", + packs: models.Packages{}, + dp: defPacks{ + def: ovalmodels.Definition{ + AffectedPacks: []ovalmodels.Package{ + { + Name: "a", + NotFixedYet: true, + }, + { + Name: "b", + NotFixedYet: false, + }, }, }, - }, - actuallyAffectedPackNames: map[string]bool{ - "a": true, - "b": false, + actuallyAffectedPackNames: map[string]bool{ + "a": true, + "b": true, + }, }, }, out: models.PackageStatuses{ @@ -134,9 +144,98 @@ func TestDefpacksToPackStatuses(t *testing.T) { }, }, }, + + // RedHat, Amazon, Debian + { + in: in{ + family: "redhat", + packs: models.Packages{}, + dp: defPacks{ + def: ovalmodels.Definition{ + AffectedPacks: []ovalmodels.Package{ + { + Name: "a", + }, + { + Name: "b", + }, + }, + }, + actuallyAffectedPackNames: map[string]bool{ + "a": true, + "b": true, + }, + }, + }, + out: models.PackageStatuses{ + { + Name: "a", + NotFixedYet: false, + }, + { + Name: "b", + NotFixedYet: false, + }, + }, + }, + + // CentOS + { + in: in{ + family: "centos", + packs: models.Packages{ + "a": {Version: "1.0.0"}, + "b": { + Version: "1.0.0", + NewVersion: "2.0.0", + }, + "c": { + Version: "1.0.0", + NewVersion: "1.5.0", + }, + }, + dp: defPacks{ + def: ovalmodels.Definition{ + AffectedPacks: []ovalmodels.Package{ + { + Name: "a", + Version: "1.0.1", + }, + { + Name: "b", + Version: "1.5.0", + }, + { + Name: "c", + Version: "2.0.0", + }, + }, + }, + actuallyAffectedPackNames: map[string]bool{ + "a": true, + "b": true, + "c": true, + }, + }, + }, + out: models.PackageStatuses{ + { + Name: "a", + NotFixedYet: true, + }, + { + Name: "b", + NotFixedYet: false, + }, + { + Name: "c", + NotFixedYet: true, + }, + }, + }, } for i, tt := range tests { - actual := tt.in.toPackStatuses() + actual := tt.in.dp.toPackStatuses(tt.in.family, tt.in.packs) sort.Slice(actual, func(i, j int) bool { return actual[i].Name < actual[j].Name })