From 6ecf2ec8847c4e1ae2df219da8b10ec42766ded8 Mon Sep 17 00:00:00 2001 From: Kota Kanbe Date: Mon, 27 Feb 2017 16:45:24 +0900 Subject: [PATCH] Changelog struct --- models/models.go | 43 +++++++++++++++++++++++++------ scan/debian.go | 67 +++++++++++++++++++++++++++++------------------- scan/redhat.go | 5 +++- 3 files changed, 79 insertions(+), 36 deletions(-) diff --git a/models/models.go b/models/models.go index 3f9f4e04f5..aef3bd73d2 100644 --- a/models/models.go +++ b/models/models.go @@ -250,20 +250,43 @@ func (c Confidence) String() string { return fmt.Sprintf("%d / %s", c.Score, c.DetectionMethod) } +const ( + // CpeNameMatchStr is a String representation of CpeNameMatch + CpeNameMatchStr = "CpeNameMatch" + + // YumUpdateSecurityMatchStr is a String representation of YumUpdateSecurityMatch + YumUpdateSecurityMatchStr = "YumUpdateSecurityMatch" + + // PkgAuditMatchStr is a String representation of PkgAuditMatch + PkgAuditMatchStr = "PkgAuditMatch" + + // ChangelogExactMatchStr is a String representation of ChangelogExactMatch + ChangelogExactMatchStr = "ChangelogExactMatch" + + // ChangelogLenientMatchStr is a String representation of ChangelogLenientMatch + ChangelogLenientMatchStr = "ChangelogLenientMatch" + + // FailedToGetChangelog is a String representation of ChangelogLenientMatch + FailedToGetChangelog = "FailedToGetChangelog" + + // FailedToFindVersionInChangelog is a String representation of ChangelogLenientMatch + FailedToFindVersionInChangelog = "FailedToFindVersionInChangelog" +) + // CpeNameMatch is a ranking how confident the CVE-ID was deteted correctly -var CpeNameMatch = Confidence{100, "CpeNameMatch"} +var CpeNameMatch = Confidence{100, CpeNameMatchStr} // YumUpdateSecurityMatch is a ranking how confident the CVE-ID was deteted correctly -var YumUpdateSecurityMatch = Confidence{100, "YumUpdateSecurityMatch"} +var YumUpdateSecurityMatch = Confidence{100, YumUpdateSecurityMatchStr} // PkgAuditMatch is a ranking how confident the CVE-ID was deteted correctly -var PkgAuditMatch = Confidence{100, "PkgAuditMatch"} +var PkgAuditMatch = Confidence{100, PkgAuditMatchStr} // ChangelogExactMatch is a ranking how confident the CVE-ID was deteted correctly -var ChangelogExactMatch = Confidence{95, "ChangelogExactMatch"} +var ChangelogExactMatch = Confidence{95, ChangelogExactMatchStr} // ChangelogLenientMatch is a ranking how confident the CVE-ID was deteted correctly -var ChangelogLenientMatch = Confidence{50, "ChangelogLenientMatch"} +var ChangelogLenientMatch = Confidence{50, ChangelogLenientMatchStr} // VulnInfos is VulnInfo list, getter/setter, sortable methods. type VulnInfos []VulnInfo @@ -466,10 +489,14 @@ type PackageInfo struct { NewVersion string NewRelease string Repository string - Changelog string + Changelog Changelog +} - //TODO Rename - VerFoundInChangelog bool +// Changelog has contents of changelog and how to get it. +// Method: modesl.detectionMethodStr +type Changelog struct { + Contents string + Method string } // ToStringCurrentVersion returns package name-version-release diff --git a/scan/debian.go b/scan/debian.go index 5dd849bdda..27669d5a48 100644 --- a/scan/debian.go +++ b/scan/debian.go @@ -447,7 +447,7 @@ func (o *debian) scanVulnInfos(upgradablePacks []models.PackageInfo, meta *cache func(p models.PackageInfo) { changelog := o.getChangelogCache(meta, p) if 0 < len(changelog) { - _, cveIDs, _ := o.getCveIDsFromChangelog(changelog, p.Name, p.Version) + cveIDs, _ := o.getCveIDsFromChangelog(changelog, p.Name, p.Version) resChan <- struct { models.PackageInfo DetectedCveIDs @@ -563,21 +563,14 @@ func (o *debian) scanPackageCveIDs(pack models.PackageInfo) ([]DetectedCveID, er } stdout := strings.Replace(r.Stdout, "\r", "", -1) - verFound, cveIDs, changelog := o.getCveIDsFromChangelog( + cveIDs, clog := o.getCveIDsFromChangelog( stdout, pack.Name, pack.Version) - if 0 < len(strings.TrimSpace(changelog)) { - err := cache.DB.PutChangelog(o.getServerInfo().GetServerName(), pack.Name, changelog) + if clog.Method != models.FailedToGetChangelog { + err := cache.DB.PutChangelog(o.getServerInfo().GetServerName(), pack.Name, clog.Contents) if err != nil { return nil, fmt.Errorf("Failed to put changelog into cache") } - - for i, p := range o.Packages { - if p.Name == pack.Name { - o.Packages[i].Changelog = changelog - o.Packages[i].VerFoundInChangelog = verFound - } - } } // No error will be returned. Only logging. @@ -585,15 +578,15 @@ func (o *debian) scanPackageCveIDs(pack models.PackageInfo) ([]DetectedCveID, er } func (o *debian) getCveIDsFromChangelog(changelog string, - packName string, versionOrLater string) (bool, []DetectedCveID, string) { + packName string, versionOrLater string) ([]DetectedCveID, models.Changelog) { if cveIDs, relevantChangelog, err := o.parseChangelog(changelog, packName, versionOrLater); err == nil { - return true, cveIDs, relevantChangelog + return cveIDs, relevantChangelog } ver := strings.Split(versionOrLater, "ubuntu")[0] if cveIDs, relevantChangelog, err := o.parseChangelog(changelog, packName, ver); err == nil { - return true, cveIDs, relevantChangelog + return cveIDs, relevantChangelog } splittedByColon := strings.Split(versionOrLater, ":") @@ -602,14 +595,17 @@ func (o *debian) getCveIDsFromChangelog(changelog string, } cveIDs, relevantChangelog, err := o.parseChangelog(changelog, packName, ver) if err == nil { - return true, cveIDs, relevantChangelog + return cveIDs, relevantChangelog } // Only logging the error. o.log.Error(err) // If the version is not in changelog, return entire changelog to put into cache - return false, []DetectedCveID{}, changelog + return []DetectedCveID{}, models.Changelog{ + Contents: changelog, + Method: models.FailedToFindVersionInChangelog, + } } // DetectedCveID has CveID, Confidence and DetectionMethod fields @@ -627,7 +623,7 @@ var cveRe = regexp.MustCompile(`(CVE-\d{4}-\d{4,})`) // Collect CVE-IDs included in the changelog. // The version which specified in argument(versionOrLater) is excluded. -func (o *debian) parseChangelog(changelog string, packName string, versionOrLater string) ([]DetectedCveID, string, error) { +func (o *debian) parseChangelog(changelog string, packName string, versionOrLater string) ([]DetectedCveID, models.Changelog, error) { buf, cveIDs := []string{}, []string{} stopRe := regexp.MustCompile(fmt.Sprintf(`\(%s\)`, regexp.QuoteMeta(versionOrLater))) @@ -655,22 +651,39 @@ func (o *debian) parseChangelog(changelog string, packName string, versionOrLate } } if !stopLineFound && !lenientStopLineFound { - return nil, "", fmt.Errorf( - "Failed to scan CVE IDs. The version is not in changelog. name: %s, version: %s", - packName, - versionOrLater, - ) + return nil, models.Changelog{ + Contents: "", + Method: models.FailedToFindVersionInChangelog, + }, + fmt.Errorf( + "Failed to scan CVE IDs. The version is not in changelog. name: %s, version: %s", + packName, + versionOrLater, + ) + } + + confidence := models.ChangelogExactMatch + if lenientStopLineFound { + confidence = models.ChangelogLenientMatch + } + + clog := models.Changelog{ + Contents: strings.Join(buf, "\n"), + Method: string(confidence.DetectionMethod), + } + + for i, p := range o.Packages { + if p.Name == packName { + o.Packages[i].Changelog = clog + } } cves := []DetectedCveID{} for _, id := range cveIDs { - confidence := models.ChangelogExactMatch - if lenientStopLineFound { - confidence = models.ChangelogLenientMatch - } cves = append(cves, DetectedCveID{id, confidence}) } - return cves, strings.Join(buf, "\n"), nil + + return cves, clog, nil } func (o *debian) splitAptCachePolicy(stdout string) map[string]string { diff --git a/scan/redhat.go b/scan/redhat.go index 708546eafa..452c306ee1 100644 --- a/scan/redhat.go +++ b/scan/redhat.go @@ -297,7 +297,10 @@ func (o *redhat) scanUnsecurePackagesUsingYumCheckUpdate() (models.VulnInfos, er n := fmt.Sprintf("%s-%s-%s", p.Name, p.NewVersion, p.NewRelease) if name == n { - o.Packages[i].Changelog = *clog + o.Packages[i].Changelog = models.Changelog{ + Contents: *clog, + Method: models.ChangelogExactMatchStr, + } break } }