Change structure of ScanResult.[]VulnInfo to Map
This commit is contained in:
		@@ -504,15 +504,19 @@ func fillCveDetail(r *models.ScanResult) error {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	for _, d := range ds {
 | 
			
		||||
		nvd := *r.ConvertNvdToModel(d.CveID, d.Nvd)
 | 
			
		||||
		jvn := *r.ConvertJvnToModel(d.CveID, d.Jvn)
 | 
			
		||||
		for i, sc := range r.ScannedCves {
 | 
			
		||||
			if sc.CveID == d.CveID {
 | 
			
		||||
				for _, con := range []models.CveContent{nvd, jvn} {
 | 
			
		||||
		nvd := r.ConvertNvdToModel(d.CveID, d.Nvd)
 | 
			
		||||
		jvn := r.ConvertJvnToModel(d.CveID, d.Jvn)
 | 
			
		||||
		for cveID, vinfo := range r.ScannedCves {
 | 
			
		||||
			if vinfo.CveID == d.CveID {
 | 
			
		||||
				if vinfo.CveContents == nil {
 | 
			
		||||
					vinfo.CveContents = models.CveContents{}
 | 
			
		||||
				}
 | 
			
		||||
				for _, con := range []models.CveContent{*nvd, *jvn} {
 | 
			
		||||
					if !con.Empty() {
 | 
			
		||||
						r.ScannedCves[i].CveContents.Upsert(con)
 | 
			
		||||
						vinfo.CveContents.Upsert(con)
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				r.ScannedCves[cveID] = vinfo
 | 
			
		||||
				break
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
@@ -528,15 +532,10 @@ func fillCveDetail(r *models.ScanResult) error {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func fillCveInfoFromCveDB(r *models.ScanResult) error {
 | 
			
		||||
	var err error
 | 
			
		||||
	var vs []models.VulnInfo
 | 
			
		||||
 | 
			
		||||
	sInfo := c.Conf.Servers[r.ServerName]
 | 
			
		||||
	vs, err = scanVulnByCpeNames(sInfo.CpeNames, r.ScannedCves)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
	if err := fillVulnByCpeNames(sInfo.CpeNames, r.ScannedCves); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	r.ScannedCves = vs
 | 
			
		||||
	if err := fillCveDetail(r); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -188,9 +188,7 @@ func diff(curResults, preResults models.ScanResults) (diffed models.ScanResults,
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if found {
 | 
			
		||||
			new, updated := getDiffCves(previous, current)
 | 
			
		||||
			current.ScannedCves = append(new, updated...)
 | 
			
		||||
 | 
			
		||||
			current.ScannedCves = getDiffCves(previous, current)
 | 
			
		||||
			packages := models.Packages{}
 | 
			
		||||
			for _, s := range current.ScannedCves {
 | 
			
		||||
				for _, name := range s.PackageNames {
 | 
			
		||||
@@ -206,22 +204,28 @@ func diff(curResults, preResults models.ScanResults) (diffed models.ScanResults,
 | 
			
		||||
	return diffed, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getDiffCves(previous, current models.ScanResult) (new, updated []models.VulnInfo) {
 | 
			
		||||
func getDiffCves(previous, current models.ScanResult) models.VulnInfos {
 | 
			
		||||
	previousCveIDsSet := map[string]bool{}
 | 
			
		||||
	for _, previousVulnInfo := range previous.ScannedCves {
 | 
			
		||||
		previousCveIDsSet[previousVulnInfo.CveID] = true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	new := models.VulnInfos{}
 | 
			
		||||
	updated := models.VulnInfos{}
 | 
			
		||||
	for _, v := range current.ScannedCves {
 | 
			
		||||
		if previousCveIDsSet[v.CveID] {
 | 
			
		||||
			if isCveInfoUpdated(v.CveID, previous, current) {
 | 
			
		||||
				updated = append(updated, v)
 | 
			
		||||
				updated[v.CveID] = v
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			new = append(new, v)
 | 
			
		||||
			new[v.CveID] = v
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
 | 
			
		||||
	for cveID, vuln := range new {
 | 
			
		||||
		updated[cveID] = vuln
 | 
			
		||||
	}
 | 
			
		||||
	return updated
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func isCveInfoUpdated(cveID string, previous, current models.ScanResult) bool {
 | 
			
		||||
@@ -274,42 +278,32 @@ func overwriteJSONFile(dir string, r models.ScanResult) error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func scanVulnByCpeNames(cpeNames []string, scannedVulns []models.VulnInfo) ([]models.VulnInfo, error) {
 | 
			
		||||
	// To remove duplicate
 | 
			
		||||
	set := map[string]models.VulnInfo{}
 | 
			
		||||
	for _, v := range scannedVulns {
 | 
			
		||||
		set[v.CveID] = v
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
func fillVulnByCpeNames(cpeNames []string, scannedVulns models.VulnInfos) error {
 | 
			
		||||
	for _, name := range cpeNames {
 | 
			
		||||
		details, err := cveapi.CveClient.FetchCveDetailsByCpeName(name)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
		for _, detail := range details {
 | 
			
		||||
			if val, ok := set[detail.CveID]; ok {
 | 
			
		||||
			if val, ok := scannedVulns[detail.CveID]; ok {
 | 
			
		||||
				names := val.CpeNames
 | 
			
		||||
				names = util.AppendIfMissing(names, name)
 | 
			
		||||
				val.CpeNames = names
 | 
			
		||||
				val.Confidence = models.CpeNameMatch
 | 
			
		||||
				set[detail.CveID] = val
 | 
			
		||||
				scannedVulns[detail.CveID] = val
 | 
			
		||||
			} else {
 | 
			
		||||
				v := models.VulnInfo{
 | 
			
		||||
					CveID:      detail.CveID,
 | 
			
		||||
					CpeNames:   []string{name},
 | 
			
		||||
					Confidence: models.CpeNameMatch,
 | 
			
		||||
				}
 | 
			
		||||
				v.NilToEmpty()
 | 
			
		||||
				set[detail.CveID] = v
 | 
			
		||||
				//TODO
 | 
			
		||||
				//  v.NilToEmpty()
 | 
			
		||||
				scannedVulns[detail.CveID] = v
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	vinfos := []models.VulnInfo{}
 | 
			
		||||
	for key := range set {
 | 
			
		||||
		vinfos = append(vinfos, set[key])
 | 
			
		||||
	}
 | 
			
		||||
	return vinfos, nil
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func needToRefreshCve(r models.ScanResult) bool {
 | 
			
		||||
 
 | 
			
		||||
@@ -45,8 +45,8 @@ func TestIsCveInfoUpdated(t *testing.T) {
 | 
			
		||||
			in: In{
 | 
			
		||||
				cveID: "CVE-2017-0001",
 | 
			
		||||
				cur: models.ScanResult{
 | 
			
		||||
					ScannedCves: []models.VulnInfo{
 | 
			
		||||
						{
 | 
			
		||||
					ScannedCves: models.VulnInfos{
 | 
			
		||||
						"CVE-2017-0001": {
 | 
			
		||||
							CveID: "CVE-2017-0001",
 | 
			
		||||
							CveContents: models.NewCveContents(
 | 
			
		||||
								models.CveContent{
 | 
			
		||||
@@ -59,8 +59,8 @@ func TestIsCveInfoUpdated(t *testing.T) {
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
				prev: models.ScanResult{
 | 
			
		||||
					ScannedCves: []models.VulnInfo{
 | 
			
		||||
						{
 | 
			
		||||
					ScannedCves: models.VulnInfos{
 | 
			
		||||
						"CVE-2017-0001": {
 | 
			
		||||
							CveID: "CVE-2017-0001",
 | 
			
		||||
							CveContents: models.NewCveContents(
 | 
			
		||||
								models.CveContent{
 | 
			
		||||
@@ -80,8 +80,8 @@ func TestIsCveInfoUpdated(t *testing.T) {
 | 
			
		||||
			in: In{
 | 
			
		||||
				cveID: "CVE-2017-0002",
 | 
			
		||||
				cur: models.ScanResult{
 | 
			
		||||
					ScannedCves: []models.VulnInfo{
 | 
			
		||||
						{
 | 
			
		||||
					ScannedCves: models.VulnInfos{
 | 
			
		||||
						"CVE-2017-0002": {
 | 
			
		||||
							CveID: "CVE-2017-0002",
 | 
			
		||||
							CveContents: models.NewCveContents(
 | 
			
		||||
								models.CveContent{
 | 
			
		||||
@@ -94,8 +94,8 @@ func TestIsCveInfoUpdated(t *testing.T) {
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
				prev: models.ScanResult{
 | 
			
		||||
					ScannedCves: []models.VulnInfo{
 | 
			
		||||
						{
 | 
			
		||||
					ScannedCves: models.VulnInfos{
 | 
			
		||||
						"CVE-2017-0002": {
 | 
			
		||||
							CveID: "CVE-2017-0002",
 | 
			
		||||
							CveContents: models.NewCveContents(
 | 
			
		||||
								models.CveContent{
 | 
			
		||||
@@ -116,8 +116,8 @@ func TestIsCveInfoUpdated(t *testing.T) {
 | 
			
		||||
				cveID: "CVE-2017-0003",
 | 
			
		||||
				cur: models.ScanResult{
 | 
			
		||||
					Family: "ubuntu",
 | 
			
		||||
					ScannedCves: []models.VulnInfo{
 | 
			
		||||
						{
 | 
			
		||||
					ScannedCves: models.VulnInfos{
 | 
			
		||||
						"CVE-2017-0003": {
 | 
			
		||||
							CveID: "CVE-2017-0003",
 | 
			
		||||
							CveContents: models.NewCveContents(
 | 
			
		||||
								models.CveContent{
 | 
			
		||||
@@ -131,8 +131,8 @@ func TestIsCveInfoUpdated(t *testing.T) {
 | 
			
		||||
				},
 | 
			
		||||
				prev: models.ScanResult{
 | 
			
		||||
					Family: "ubuntu",
 | 
			
		||||
					ScannedCves: []models.VulnInfo{
 | 
			
		||||
						{
 | 
			
		||||
					ScannedCves: models.VulnInfos{
 | 
			
		||||
						"CVE-2017-0003": {
 | 
			
		||||
							CveID: "CVE-2017-0003",
 | 
			
		||||
							CveContents: models.NewCveContents(
 | 
			
		||||
								models.CveContent{
 | 
			
		||||
@@ -153,8 +153,8 @@ func TestIsCveInfoUpdated(t *testing.T) {
 | 
			
		||||
				cveID: "CVE-2017-0004",
 | 
			
		||||
				cur: models.ScanResult{
 | 
			
		||||
					Family: "redhat",
 | 
			
		||||
					ScannedCves: []models.VulnInfo{
 | 
			
		||||
						{
 | 
			
		||||
					ScannedCves: models.VulnInfos{
 | 
			
		||||
						"CVE-2017-0004": {
 | 
			
		||||
							CveID: "CVE-2017-0004",
 | 
			
		||||
							CveContents: models.NewCveContents(
 | 
			
		||||
								models.CveContent{
 | 
			
		||||
@@ -168,7 +168,7 @@ func TestIsCveInfoUpdated(t *testing.T) {
 | 
			
		||||
				},
 | 
			
		||||
				prev: models.ScanResult{
 | 
			
		||||
					Family:      "redhat",
 | 
			
		||||
					ScannedCves: []models.VulnInfo{},
 | 
			
		||||
					ScannedCves: models.VulnInfos{},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			expected: true,
 | 
			
		||||
@@ -197,14 +197,14 @@ func TestDiff(t *testing.T) {
 | 
			
		||||
					ServerName: "u16",
 | 
			
		||||
					Family:     "ubuntu",
 | 
			
		||||
					Release:    "16.04",
 | 
			
		||||
					ScannedCves: []models.VulnInfo{
 | 
			
		||||
						{
 | 
			
		||||
					ScannedCves: models.VulnInfos{
 | 
			
		||||
						"CVE-2012-6702": {
 | 
			
		||||
							CveID:            "CVE-2012-6702",
 | 
			
		||||
							PackageNames:     []string{"libexpat1"},
 | 
			
		||||
							DistroAdvisories: []models.DistroAdvisory{},
 | 
			
		||||
							CpeNames:         []string{},
 | 
			
		||||
						},
 | 
			
		||||
						{
 | 
			
		||||
						"CVE-2014-9761": {
 | 
			
		||||
							CveID:            "CVE-2014-9761",
 | 
			
		||||
							PackageNames:     []string{"libc-bin"},
 | 
			
		||||
							DistroAdvisories: []models.DistroAdvisory{},
 | 
			
		||||
@@ -222,14 +222,14 @@ func TestDiff(t *testing.T) {
 | 
			
		||||
					ServerName: "u16",
 | 
			
		||||
					Family:     "ubuntu",
 | 
			
		||||
					Release:    "16.04",
 | 
			
		||||
					ScannedCves: []models.VulnInfo{
 | 
			
		||||
						{
 | 
			
		||||
					ScannedCves: models.VulnInfos{
 | 
			
		||||
						"CVE-2012-6702": {
 | 
			
		||||
							CveID:            "CVE-2012-6702",
 | 
			
		||||
							PackageNames:     []string{"libexpat1"},
 | 
			
		||||
							DistroAdvisories: []models.DistroAdvisory{},
 | 
			
		||||
							CpeNames:         []string{},
 | 
			
		||||
						},
 | 
			
		||||
						{
 | 
			
		||||
						"CVE-2014-9761": {
 | 
			
		||||
							CveID:            "CVE-2014-9761",
 | 
			
		||||
							PackageNames:     []string{"libc-bin"},
 | 
			
		||||
							DistroAdvisories: []models.DistroAdvisory{},
 | 
			
		||||
@@ -242,13 +242,14 @@ func TestDiff(t *testing.T) {
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			out: models.ScanResult{
 | 
			
		||||
				ScannedAt:  atCurrent,
 | 
			
		||||
				ServerName: "u16",
 | 
			
		||||
				Family:     "ubuntu",
 | 
			
		||||
				Release:    "16.04",
 | 
			
		||||
				Packages:   models.Packages{},
 | 
			
		||||
				Errors:     []string{},
 | 
			
		||||
				Optional:   [][]interface{}{},
 | 
			
		||||
				ScannedAt:   atCurrent,
 | 
			
		||||
				ServerName:  "u16",
 | 
			
		||||
				Family:      "ubuntu",
 | 
			
		||||
				Release:     "16.04",
 | 
			
		||||
				Packages:    models.Packages{},
 | 
			
		||||
				ScannedCves: models.VulnInfos{},
 | 
			
		||||
				Errors:      []string{},
 | 
			
		||||
				Optional:    [][]interface{}{},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
@@ -258,8 +259,8 @@ func TestDiff(t *testing.T) {
 | 
			
		||||
					ServerName: "u16",
 | 
			
		||||
					Family:     "ubuntu",
 | 
			
		||||
					Release:    "16.04",
 | 
			
		||||
					ScannedCves: []models.VulnInfo{
 | 
			
		||||
						{
 | 
			
		||||
					ScannedCves: models.VulnInfos{
 | 
			
		||||
						"CVE-2016-6662": {
 | 
			
		||||
							CveID:            "CVE-2016-6662",
 | 
			
		||||
							PackageNames:     []string{"mysql-libs"},
 | 
			
		||||
							DistroAdvisories: []models.DistroAdvisory{},
 | 
			
		||||
@@ -288,7 +289,7 @@ func TestDiff(t *testing.T) {
 | 
			
		||||
					ServerName:  "u16",
 | 
			
		||||
					Family:      "ubuntu",
 | 
			
		||||
					Release:     "16.04",
 | 
			
		||||
					ScannedCves: []models.VulnInfo{},
 | 
			
		||||
					ScannedCves: models.VulnInfos{},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			out: models.ScanResult{
 | 
			
		||||
@@ -296,8 +297,8 @@ func TestDiff(t *testing.T) {
 | 
			
		||||
				ServerName: "u16",
 | 
			
		||||
				Family:     "ubuntu",
 | 
			
		||||
				Release:    "16.04",
 | 
			
		||||
				ScannedCves: []models.VulnInfo{
 | 
			
		||||
					{
 | 
			
		||||
				ScannedCves: models.VulnInfos{
 | 
			
		||||
					"CVE-2016-6662": {
 | 
			
		||||
						CveID:            "CVE-2016-6662",
 | 
			
		||||
						PackageNames:     []string{"mysql-libs"},
 | 
			
		||||
						DistroAdvisories: []models.DistroAdvisory{},
 | 
			
		||||
 
 | 
			
		||||
@@ -164,12 +164,10 @@ func (r ScanResult) FilterByCvssOver() ScanResult {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// TODO: Filter by ignore cves???
 | 
			
		||||
	filtered := VulnInfos{}
 | 
			
		||||
	for _, sc := range r.ScannedCves {
 | 
			
		||||
		if config.Conf.CvssScoreOver <= sc.CveContents.CvssV2Score() {
 | 
			
		||||
			filtered = append(filtered, sc)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	filtered := r.ScannedCves.Find(func(v VulnInfo) bool {
 | 
			
		||||
		return config.Conf.CvssScoreOver <= v.CveContents.CvssV2Score()
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	copiedScanResult := r
 | 
			
		||||
	copiedScanResult.ScannedCves = filtered
 | 
			
		||||
	return copiedScanResult
 | 
			
		||||
@@ -316,61 +314,17 @@ var ChangelogExactMatch = Confidence{95, ChangelogExactMatchStr}
 | 
			
		||||
var ChangelogLenientMatch = Confidence{50, ChangelogLenientMatchStr}
 | 
			
		||||
 | 
			
		||||
// VulnInfos is VulnInfo list, getter/setter, sortable methods.
 | 
			
		||||
type VulnInfos []VulnInfo
 | 
			
		||||
type VulnInfos map[string]VulnInfo
 | 
			
		||||
 | 
			
		||||
// Find elements that matches the function passed in argument
 | 
			
		||||
func (v *VulnInfos) Find(f func(VulnInfo) bool) (filtered VulnInfos) {
 | 
			
		||||
	for _, vv := range *v {
 | 
			
		||||
func (v VulnInfos) Find(f func(VulnInfo) bool) VulnInfos {
 | 
			
		||||
	filtered := VulnInfos{}
 | 
			
		||||
	for _, vv := range v {
 | 
			
		||||
		if f(vv) {
 | 
			
		||||
			filtered = append(filtered, vv)
 | 
			
		||||
			filtered[vv.CveID] = vv
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get VulnInfo by cveID
 | 
			
		||||
func (v *VulnInfos) Get(cveID string) (VulnInfo, bool) {
 | 
			
		||||
	for _, vv := range *v {
 | 
			
		||||
		if vv.CveID == cveID {
 | 
			
		||||
			return vv, true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return VulnInfo{}, false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Delete by cveID
 | 
			
		||||
func (v *VulnInfos) Delete(cveID string) {
 | 
			
		||||
	vInfos := *v
 | 
			
		||||
	for i, vv := range vInfos {
 | 
			
		||||
		if vv.CveID == cveID {
 | 
			
		||||
			*v = append(vInfos[:i], vInfos[i+1:]...)
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Insert VulnInfo
 | 
			
		||||
func (v *VulnInfos) Insert(vinfo VulnInfo) {
 | 
			
		||||
	*v = append(*v, vinfo)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Update VulnInfo
 | 
			
		||||
func (v *VulnInfos) Update(vInfo VulnInfo) (ok bool) {
 | 
			
		||||
	for i, vv := range *v {
 | 
			
		||||
		if vv.CveID == vInfo.CveID {
 | 
			
		||||
			(*v)[i] = vInfo
 | 
			
		||||
			return true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Upsert cveInfo
 | 
			
		||||
func (v *VulnInfos) Upsert(vInfo VulnInfo) {
 | 
			
		||||
	ok := v.Update(vInfo)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		v.Insert(vInfo)
 | 
			
		||||
	}
 | 
			
		||||
	return filtered
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// VulnInfo holds a vulnerability information and unsecure packages
 | 
			
		||||
 
 | 
			
		||||
@@ -58,46 +58,3 @@ func TestMergeNewVersion(t *testing.T) {
 | 
			
		||||
		t.Errorf("expected %s, actual %s", e, a)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
func TestVulnInfosSetGet(t *testing.T) {
 | 
			
		||||
	var test = struct {
 | 
			
		||||
		in  []string
 | 
			
		||||
		out []string
 | 
			
		||||
	}{
 | 
			
		||||
		[]string{
 | 
			
		||||
			"CVE1",
 | 
			
		||||
			"CVE2",
 | 
			
		||||
			"CVE3",
 | 
			
		||||
			"CVE1",
 | 
			
		||||
			"CVE1",
 | 
			
		||||
			"CVE2",
 | 
			
		||||
			"CVE3",
 | 
			
		||||
		},
 | 
			
		||||
		[]string{
 | 
			
		||||
			"CVE1",
 | 
			
		||||
			"CVE2",
 | 
			
		||||
			"CVE3",
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	//  var ps packageCveInfos
 | 
			
		||||
	var ps VulnInfos
 | 
			
		||||
	for _, cid := range test.in {
 | 
			
		||||
		ps.Upsert(VulnInfo{CveID: cid})
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(test.out) != len(ps) {
 | 
			
		||||
		t.Errorf("length: expected %d, actual %d", len(test.out), len(ps))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for i, expectedCid := range test.out {
 | 
			
		||||
		if expectedCid != ps[i].CveID {
 | 
			
		||||
			t.Errorf("expected %s, actual %s", expectedCid, ps[i].CveID)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	for _, cid := range test.in {
 | 
			
		||||
		p, _ := ps.Get(cid)
 | 
			
		||||
		if p.CveID != cid {
 | 
			
		||||
			t.Errorf("expected %s, actual %s", cid, p.CveID)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -62,10 +62,9 @@ func (o Debian) FillCveInfoFromOvalDB(r *models.ScanResult) error {
 | 
			
		||||
func (o Debian) fillOvalInfo(r *models.ScanResult, definition *ovalmodels.Definition) {
 | 
			
		||||
	ovalContent := *o.convertToModel(definition)
 | 
			
		||||
	ovalContent.Type = models.NewCveContentType(r.Family)
 | 
			
		||||
	vinfo, ok := r.ScannedCves.Get(definition.Debian.CveID)
 | 
			
		||||
	vinfo, ok := r.ScannedCves[definition.Debian.CveID]
 | 
			
		||||
	if !ok {
 | 
			
		||||
		util.Log.Infof("%s is newly detected by OVAL",
 | 
			
		||||
			definition.Debian.CveID)
 | 
			
		||||
		util.Log.Infof("%s is newly detected by OVAL", definition.Debian.CveID)
 | 
			
		||||
		vinfo = models.VulnInfo{
 | 
			
		||||
			CveID:        definition.Debian.CveID,
 | 
			
		||||
			Confidence:   models.OvalMatch,
 | 
			
		||||
@@ -73,17 +72,20 @@ func (o Debian) fillOvalInfo(r *models.ScanResult, definition *ovalmodels.Defini
 | 
			
		||||
			CveContents:  models.NewCveContents(ovalContent),
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		if _, ok := vinfo.CveContents.Get(models.NewCveContentType(r.Family)); !ok {
 | 
			
		||||
			util.Log.Infof("%s is also detected by OVAL", definition.Debian.CveID)
 | 
			
		||||
		} else {
 | 
			
		||||
		cveContents := vinfo.CveContents
 | 
			
		||||
		if _, ok := vinfo.CveContents.Get(models.NewCveContentType(r.Family)); ok {
 | 
			
		||||
			util.Log.Infof("%s will be updated by OVAL", definition.Debian.CveID)
 | 
			
		||||
		} else {
 | 
			
		||||
			util.Log.Infof("%s is also detected by OVAL", definition.Debian.CveID)
 | 
			
		||||
			cveContents = models.CveContents{}
 | 
			
		||||
		}
 | 
			
		||||
		if vinfo.Confidence.Score < models.OvalMatch.Score {
 | 
			
		||||
			vinfo.Confidence = models.OvalMatch
 | 
			
		||||
		}
 | 
			
		||||
		vinfo.CveContents.Upsert(ovalContent)
 | 
			
		||||
		cveContents.Upsert(ovalContent)
 | 
			
		||||
		vinfo.CveContents = cveContents
 | 
			
		||||
	}
 | 
			
		||||
	r.ScannedCves.Upsert(vinfo)
 | 
			
		||||
	r.ScannedCves[definition.Debian.CveID] = vinfo
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o Debian) convertToModel(def *ovalmodels.Definition) *models.CveContent {
 | 
			
		||||
 
 | 
			
		||||
@@ -59,7 +59,7 @@ func (o Redhat) FillCveInfoFromOvalDB(r *models.ScanResult) error {
 | 
			
		||||
func (o Redhat) fillOvalInfo(r *models.ScanResult, definition *ovalmodels.Definition) {
 | 
			
		||||
	for _, cve := range definition.Advisory.Cves {
 | 
			
		||||
		ovalContent := *o.convertToModel(cve.CveID, definition)
 | 
			
		||||
		vinfo, ok := r.ScannedCves.Get(cve.CveID)
 | 
			
		||||
		vinfo, ok := r.ScannedCves[cve.CveID]
 | 
			
		||||
		if !ok {
 | 
			
		||||
			util.Log.Infof("%s is newly detected by OVAL", cve.CveID)
 | 
			
		||||
			vinfo = models.VulnInfo{
 | 
			
		||||
@@ -69,17 +69,21 @@ func (o Redhat) fillOvalInfo(r *models.ScanResult, definition *ovalmodels.Defini
 | 
			
		||||
				CveContents:  models.NewCveContents(ovalContent),
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			if _, ok := vinfo.CveContents.Get(models.RedHat); !ok {
 | 
			
		||||
				util.Log.Infof("%s is also detected by OVAL", cve.CveID)
 | 
			
		||||
			} else {
 | 
			
		||||
			cveContents := vinfo.CveContents
 | 
			
		||||
			if _, ok := vinfo.CveContents.Get(models.RedHat); ok {
 | 
			
		||||
				util.Log.Infof("%s will be updated by OVAL", cve.CveID)
 | 
			
		||||
			} else {
 | 
			
		||||
				util.Log.Infof("%s is also detected by OVAL", cve.CveID)
 | 
			
		||||
				cveContents = models.CveContents{}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if vinfo.Confidence.Score < models.OvalMatch.Score {
 | 
			
		||||
				vinfo.Confidence = models.OvalMatch
 | 
			
		||||
			}
 | 
			
		||||
			vinfo.CveContents.Upsert(ovalContent)
 | 
			
		||||
			cveContents.Upsert(ovalContent)
 | 
			
		||||
			vinfo.CveContents = cveContents
 | 
			
		||||
		}
 | 
			
		||||
		r.ScannedCves.Upsert(vinfo)
 | 
			
		||||
		r.ScannedCves[cve.CveID] = vinfo
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -291,10 +291,11 @@ func (l *base) convertToModel() models.ScanResult {
 | 
			
		||||
		errs = append(errs, fmt.Sprintf("%s", e))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	//TODO Remove
 | 
			
		||||
	// Avoid null slice being null in JSON
 | 
			
		||||
	for i := range l.VulnInfos {
 | 
			
		||||
		l.VulnInfos[i].NilToEmpty()
 | 
			
		||||
	}
 | 
			
		||||
	//  for cveID := range l.VulnInfos {
 | 
			
		||||
	//      l.VulnInfos[i].NilToEmpty()
 | 
			
		||||
	//  }
 | 
			
		||||
 | 
			
		||||
	return models.ScanResult{
 | 
			
		||||
		ServerName:  l.ServerInfo.ServerName,
 | 
			
		||||
 
 | 
			
		||||
@@ -264,8 +264,7 @@ func (o *debian) aptGetUpdate() error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *debian) scanUnsecurePackages(upgradable models.Packages) ([]models.VulnInfo, error) {
 | 
			
		||||
 | 
			
		||||
func (o *debian) scanUnsecurePackages(upgradable models.Packages) (models.VulnInfos, error) {
 | 
			
		||||
	o.aptGetUpdate()
 | 
			
		||||
 | 
			
		||||
	// Setup changelog cache
 | 
			
		||||
@@ -491,13 +490,13 @@ func (o *debian) scanVulnInfos(upgradablePacks models.Packages, meta *cache.Meta
 | 
			
		||||
		cveIDs = append(cveIDs, k)
 | 
			
		||||
	}
 | 
			
		||||
	o.log.Debugf("%d Cves are found. cves: %v", len(cveIDs), cveIDs)
 | 
			
		||||
	var vinfos models.VulnInfos
 | 
			
		||||
	vinfos := models.VulnInfos{}
 | 
			
		||||
	for cveID, names := range cvePackages {
 | 
			
		||||
		vinfos = append(vinfos, models.VulnInfo{
 | 
			
		||||
		vinfos[cveID.CveID] = models.VulnInfo{
 | 
			
		||||
			CveID:        cveID.CveID,
 | 
			
		||||
			Confidence:   cveID.Confidence,
 | 
			
		||||
			PackageNames: names,
 | 
			
		||||
		})
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Update meta package information of changelog cache to the latest one.
 | 
			
		||||
 
 | 
			
		||||
@@ -85,7 +85,7 @@ func (o *bsd) scanPackages() error {
 | 
			
		||||
	}
 | 
			
		||||
	o.setPackages(packs)
 | 
			
		||||
 | 
			
		||||
	var vinfos []models.VulnInfo
 | 
			
		||||
	var vinfos models.VulnInfos
 | 
			
		||||
	if vinfos, err = o.scanUnsecurePackages(); err != nil {
 | 
			
		||||
		o.log.Errorf("Failed to scan vulnerable packages")
 | 
			
		||||
		return err
 | 
			
		||||
@@ -103,7 +103,7 @@ func (o *bsd) scanInstalledPackages() (models.Packages, error) {
 | 
			
		||||
	return o.parsePkgVersion(r.Stdout), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *bsd) scanUnsecurePackages() (vulnInfos []models.VulnInfo, err error) {
 | 
			
		||||
func (o *bsd) scanUnsecurePackages() (models.VulnInfos, error) {
 | 
			
		||||
	const vulndbPath = "/tmp/vuln.db"
 | 
			
		||||
	cmd := "rm -f " + vulndbPath
 | 
			
		||||
	r := o.exec(cmd, noSudo)
 | 
			
		||||
@@ -118,7 +118,7 @@ func (o *bsd) scanUnsecurePackages() (vulnInfos []models.VulnInfo, err error) {
 | 
			
		||||
	}
 | 
			
		||||
	if r.ExitStatus == 0 {
 | 
			
		||||
		// no vulnerabilities
 | 
			
		||||
		return []models.VulnInfo{}, nil
 | 
			
		||||
		return nil, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var packAdtRslt []pkgAuditResult
 | 
			
		||||
@@ -149,14 +149,15 @@ func (o *bsd) scanUnsecurePackages() (vulnInfos []models.VulnInfo, err error) {
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for k := range cveIDAdtMap {
 | 
			
		||||
	vinfos := models.VulnInfos{}
 | 
			
		||||
	for cveID := range cveIDAdtMap {
 | 
			
		||||
		packs := models.Packages{}
 | 
			
		||||
		for _, r := range cveIDAdtMap[k] {
 | 
			
		||||
		for _, r := range cveIDAdtMap[cveID] {
 | 
			
		||||
			packs[r.pack.Name] = r.pack
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		disAdvs := []models.DistroAdvisory{}
 | 
			
		||||
		for _, r := range cveIDAdtMap[k] {
 | 
			
		||||
		for _, r := range cveIDAdtMap[cveID] {
 | 
			
		||||
			disAdvs = append(disAdvs, models.DistroAdvisory{
 | 
			
		||||
				AdvisoryID: r.vulnIDCveIDs.vulnID,
 | 
			
		||||
			})
 | 
			
		||||
@@ -166,14 +167,14 @@ func (o *bsd) scanUnsecurePackages() (vulnInfos []models.VulnInfo, err error) {
 | 
			
		||||
		for name := range packs {
 | 
			
		||||
			names = append(names, name)
 | 
			
		||||
		}
 | 
			
		||||
		vulnInfos = append(vulnInfos, models.VulnInfo{
 | 
			
		||||
			CveID:            k,
 | 
			
		||||
		vinfos[cveID] = models.VulnInfo{
 | 
			
		||||
			CveID:            cveID,
 | 
			
		||||
			PackageNames:     names,
 | 
			
		||||
			DistroAdvisories: disAdvs,
 | 
			
		||||
			Confidence:       models.PkgAuditMatch,
 | 
			
		||||
		})
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
	return vinfos, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *bsd) parsePkgVersion(stdout string) models.Packages {
 | 
			
		||||
 
 | 
			
		||||
@@ -240,7 +240,7 @@ func (o *redhat) scanPackages() error {
 | 
			
		||||
	}
 | 
			
		||||
	o.setPackages(models.NewPackages(packs...))
 | 
			
		||||
 | 
			
		||||
	var vinfos []models.VulnInfo
 | 
			
		||||
	var vinfos models.VulnInfos
 | 
			
		||||
	if vinfos, err = o.scanVulnInfos(); err != nil {
 | 
			
		||||
		o.log.Errorf("Failed to scan vulnerable packages")
 | 
			
		||||
		return err
 | 
			
		||||
@@ -292,7 +292,7 @@ func (o *redhat) parseScannedPackagesLine(line string) (models.Package, error) {
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *redhat) scanVulnInfos() ([]models.VulnInfo, error) {
 | 
			
		||||
func (o *redhat) scanVulnInfos() (models.VulnInfos, error) {
 | 
			
		||||
	if o.Distro.Family != "centos" {
 | 
			
		||||
		// Amazon, RHEL, Oracle Linux has yum updateinfo as default
 | 
			
		||||
		// yum updateinfo can collenct vendor advisory information.
 | 
			
		||||
@@ -423,7 +423,7 @@ func (o *redhat) scanUnsecurePackagesUsingYumCheckUpdate() (models.VulnInfos, er
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	vinfos := []models.VulnInfo{}
 | 
			
		||||
	vinfos := models.VulnInfos{}
 | 
			
		||||
	for cveID, packs := range cveIDPackages {
 | 
			
		||||
		names := []string{}
 | 
			
		||||
		for name := range packs {
 | 
			
		||||
@@ -431,11 +431,11 @@ func (o *redhat) scanUnsecurePackagesUsingYumCheckUpdate() (models.VulnInfos, er
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Amazon, RHEL do not use this method, so VendorAdvisory do not set.
 | 
			
		||||
		vinfos = append(vinfos, models.VulnInfo{
 | 
			
		||||
		vinfos[cveID] = models.VulnInfo{
 | 
			
		||||
			CveID:        cveID,
 | 
			
		||||
			PackageNames: names,
 | 
			
		||||
			Confidence:   models.ChangelogExactMatch,
 | 
			
		||||
		})
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return vinfos, nil
 | 
			
		||||
}
 | 
			
		||||
@@ -741,36 +741,29 @@ func (o *redhat) scanUnsecurePackagesUsingYumPluginSecurity() (models.VulnInfos,
 | 
			
		||||
	vinfos := models.VulnInfos{}
 | 
			
		||||
	for _, advIDCveIDs := range advisoryCveIDsList {
 | 
			
		||||
		for _, cveID := range advIDCveIDs.CveIDs {
 | 
			
		||||
			found := false
 | 
			
		||||
			for i, p := range vinfos {
 | 
			
		||||
				if cveID == p.CveID {
 | 
			
		||||
					advAppended := append(p.DistroAdvisories, advIDCveIDs.DistroAdvisory)
 | 
			
		||||
					vinfos[i].DistroAdvisories = advAppended
 | 
			
		||||
			vinfo, found := vinfos[cveID]
 | 
			
		||||
			if found {
 | 
			
		||||
				advAppended := append(vinfo.DistroAdvisories, advIDCveIDs.DistroAdvisory)
 | 
			
		||||
				vinfo.DistroAdvisories = advAppended
 | 
			
		||||
 | 
			
		||||
					packs := dict[advIDCveIDs.DistroAdvisory.AdvisoryID]
 | 
			
		||||
					for _, pack := range packs {
 | 
			
		||||
						vinfos[i].PackageNames = append(vinfos[i].PackageNames, pack.Name)
 | 
			
		||||
					}
 | 
			
		||||
					found = true
 | 
			
		||||
					break
 | 
			
		||||
				packs := dict[advIDCveIDs.DistroAdvisory.AdvisoryID]
 | 
			
		||||
				for _, pack := range packs {
 | 
			
		||||
					vinfo.PackageNames = append(vinfo.PackageNames, pack.Name)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if !found {
 | 
			
		||||
			} else {
 | 
			
		||||
				names := []string{}
 | 
			
		||||
				packs := dict[advIDCveIDs.DistroAdvisory.AdvisoryID]
 | 
			
		||||
				for _, pack := range packs {
 | 
			
		||||
					names = append(names, pack.Name)
 | 
			
		||||
				}
 | 
			
		||||
				cpinfo := models.VulnInfo{
 | 
			
		||||
				vinfo = models.VulnInfo{
 | 
			
		||||
					CveID:            cveID,
 | 
			
		||||
					DistroAdvisories: []models.DistroAdvisory{advIDCveIDs.DistroAdvisory},
 | 
			
		||||
					PackageNames:     names,
 | 
			
		||||
					Confidence:       models.YumUpdateSecurityMatch,
 | 
			
		||||
				}
 | 
			
		||||
				vinfos = append(vinfos, cpinfo)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			vinfos[cveID] = vinfo
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return vinfos, nil
 | 
			
		||||
 
 | 
			
		||||
@@ -69,7 +69,7 @@ func (p *osPackages) setPackages(pi models.Packages) {
 | 
			
		||||
	p.Packages = pi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *osPackages) setVulnInfos(vi []models.VulnInfo) {
 | 
			
		||||
func (p *osPackages) setVulnInfos(vi models.VulnInfos) {
 | 
			
		||||
	p.VulnInfos = vi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user