nosudo on CentOS and Fetch Changelogs on Amazon, RHEL (#448)
* Use repoquery for no sudo and avoid unintended line feed of yum or rpm. #444 * Change data type of enablerepo in config.toml. string to array * Fetch yum changelogs at once then grep CVE-IDs * Fix changelog parse logic and Update Gopkg
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
language: go
|
||||
|
||||
go:
|
||||
- 1.7
|
||||
- 1.8
|
||||
|
||||
|
||||
61
Gopkg.lock
generated
61
Gopkg.lock
generated
@@ -2,10 +2,10 @@
|
||||
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/Azure/azure-storage-go"
|
||||
packages = ["."]
|
||||
revision = "32cfbe17a139c17f84be16bdf8f9c45c840a046b"
|
||||
name = "github.com/Azure/azure-sdk-for-go"
|
||||
packages = ["storage"]
|
||||
revision = "59c277f1b488b81b1a5f944212f25b69bea8ece3"
|
||||
version = "v10.1.0-beta"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/Azure/go-autorest"
|
||||
@@ -14,10 +14,10 @@
|
||||
version = "v8.1.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/BurntSushi/toml"
|
||||
packages = ["."]
|
||||
revision = "a368813c5e648fee92e5f6c30e3944ff9d5e8895"
|
||||
revision = "b26d9c308763d68093482582cea63d69be07a0f0"
|
||||
version = "v0.3.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/asaskevich/govalidator"
|
||||
@@ -27,14 +27,15 @@
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/aws/aws-sdk-go"
|
||||
packages = ["aws","aws/awserr","aws/awsutil","aws/client","aws/client/metadata","aws/corehandlers","aws/credentials","aws/credentials/ec2rolecreds","aws/credentials/endpointcreds","aws/credentials/stscreds","aws/defaults","aws/ec2metadata","aws/request","aws/session","aws/signer/v4","private/endpoints","private/protocol","private/protocol/query","private/protocol/query/queryutil","private/protocol/rest","private/protocol/restxml","private/protocol/xml/xmlutil","private/waiter","service/s3","service/sts"]
|
||||
revision = "5b341290c488aa6bd76b335d819b4a68516ec3ab"
|
||||
packages = ["aws","aws/awserr","aws/awsutil","aws/client","aws/client/metadata","aws/corehandlers","aws/credentials","aws/credentials/ec2rolecreds","aws/credentials/endpointcreds","aws/credentials/stscreds","aws/defaults","aws/ec2metadata","aws/endpoints","aws/request","aws/session","aws/signer/v4","internal/shareddefaults","private/protocol","private/protocol/query","private/protocol/query/queryutil","private/protocol/rest","private/protocol/restxml","private/protocol/xml/xmlutil","service/s3","service/sts"]
|
||||
revision = "6d7fc1a00fcae6bbb53550f4a0b98324fd7aa250"
|
||||
version = "v1.10.12"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/boltdb/bolt"
|
||||
packages = ["."]
|
||||
revision = "583e8937c61f1af6513608ccc75c97b6abdf4ff9"
|
||||
version = "v1.3.0"
|
||||
revision = "2f1ce7a837dcb8da3ec595b1dac9d0632f0f99e8"
|
||||
version = "v1.3.1"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/cenkalti/backoff"
|
||||
@@ -63,8 +64,8 @@
|
||||
[[projects]]
|
||||
name = "github.com/go-redis/redis"
|
||||
packages = [".","internal","internal/consistenthash","internal/hashtag","internal/pool","internal/proto"]
|
||||
revision = "e14976b254c5bc5f399dd0ae9314b1d02a176897"
|
||||
version = "v6.5.0"
|
||||
revision = "da63fe7def48e378caf9539abf64b9b1e37bc01e"
|
||||
version = "v6.5.3"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/go-sql-driver/mysql"
|
||||
@@ -109,10 +110,10 @@
|
||||
version = "0.2.2"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/jroimartin/gocui"
|
||||
packages = ["."]
|
||||
revision = "612b0b2987ec1a6af46d7008cef1efd4b3898346"
|
||||
revision = "4e9ce9a8e26f2ef33dfe297dbdfca148733b6b9b"
|
||||
version = "v0.3.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
@@ -128,9 +129,15 @@
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/knqyf263/go-rpm-version"
|
||||
packages = ["."]
|
||||
revision = "74609b86c936dff800c69ec89fcf4bc52d5f13a4"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/kotakanbe/go-cve-dictionary"
|
||||
packages = ["config","db","jvn","log","models","nvd","util"]
|
||||
revision = "89e381b4e7e5a31097bbd5779cbb555f5bd3fe87"
|
||||
version = "v0.1.1"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/kotakanbe/go-pingscanner"
|
||||
@@ -153,14 +160,14 @@
|
||||
[[projects]]
|
||||
name = "github.com/labstack/gommon"
|
||||
packages = ["color","log"]
|
||||
revision = "1121fd3e243c202482226a7afe4dcd07ffc4139a"
|
||||
version = "v0.2.1"
|
||||
revision = "779b8a8b9850a97acba6a3fe20feb628c39e17c1"
|
||||
version = "0.2.2"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/lib/pq"
|
||||
packages = [".","hstore","oid"]
|
||||
revision = "8837942c3e09574accbc5f150e2c5e057189cace"
|
||||
revision = "dd1fe2071026ce53f36a39112e645b4d4f5793a4"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/mattn/go-colorable"
|
||||
@@ -202,7 +209,7 @@
|
||||
branch = "master"
|
||||
name = "github.com/nsf/termbox-go"
|
||||
packages = ["."]
|
||||
revision = "72800b73ab9a3c78df350738298b0361354772ff"
|
||||
revision = "4ed959e0540971545eddb8c75514973d670cf739"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/parnurzeal/gorequest"
|
||||
@@ -232,7 +239,7 @@
|
||||
branch = "master"
|
||||
name = "github.com/sirupsen/logrus"
|
||||
packages = ["."]
|
||||
revision = "3d4380f53a34dcdc95f0c1db702615992b38d9a4"
|
||||
revision = "5ff5dd844dfeb4e23e27528f79f1f845bc8bb78f"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
@@ -252,39 +259,33 @@
|
||||
packages = ["oval"]
|
||||
revision = "003ac9af5fffac6c97ab1def025d2cb73e88469a"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "go4.org"
|
||||
packages = ["syncutil"]
|
||||
revision = "034d17a462f7b2dcd1a4a73553ec5357ff6e6c6e"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/crypto"
|
||||
packages = ["curve25519","ed25519","ed25519/internal/edwards25519","ssh","ssh/agent","ssh/terminal"]
|
||||
revision = "adbae1b6b6fb4b02448a0fc0dbbc9ba2b95b294d"
|
||||
revision = "7f7c0c2d75ebb4e32a21396ce36e87b6dadc91c9"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/net"
|
||||
packages = ["context","idna","publicsuffix"]
|
||||
revision = "455220fa52c866a8aa14ff5e8cc68cde16b8395e"
|
||||
revision = "b3756b4b77d7b13260a0a2ec658753cf48922eac"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/sys"
|
||||
packages = ["unix"]
|
||||
revision = "90796e5a05ce440b41c768bd9af257005e470461"
|
||||
revision = "4cd6d1a821c7175768725b55ca82f14683a29ea4"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/text"
|
||||
packages = ["internal/gen","internal/triegen","internal/ucd","secure/bidirule","transform","unicode/bidi","unicode/cldr","unicode/norm","unicode/rangetable"]
|
||||
revision = "6353ef0f924300eea566d3438817aa4d3374817e"
|
||||
revision = "836efe42bb4aa16aaa17b9c155d8813d336ed720"
|
||||
|
||||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
inputs-digest = "a6b387c74e75e1f971ee643c8904f6fd4e3dfdb7fa36119ab7bc28d9cfd66427"
|
||||
inputs-digest = "269ff02f8e4540ba049a340068dac0ff4f0495df9f8eeb21d4a545ea5dedf2dd"
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
||||
|
||||
74
Gopkg.toml
74
Gopkg.toml
@@ -1,23 +1,57 @@
|
||||
|
||||
# Gopkg.toml example
|
||||
#
|
||||
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
|
||||
# for detailed Gopkg.toml documentation.
|
||||
#
|
||||
# required = ["github.com/user/thing/cmd/thing"]
|
||||
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
|
||||
#
|
||||
# [[constraint]]
|
||||
# name = "github.com/user/project"
|
||||
# version = "1.0.0"
|
||||
#
|
||||
# [[constraint]]
|
||||
# name = "github.com/user/project2"
|
||||
# branch = "dev"
|
||||
# source = "github.com/myfork/project2"
|
||||
#
|
||||
# [[override]]
|
||||
# name = "github.com/x/y"
|
||||
# version = "2.4.0"
|
||||
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/Azure/azure-storage-go"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/BurntSushi/toml"
|
||||
version = "0.3.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/asaskevich/govalidator"
|
||||
version = "6.0.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/boltdb/bolt"
|
||||
version = "1.3.1"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/cenkalti/backoff"
|
||||
version = "1.0.0"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/sirupsen/logrus"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/aws/aws-sdk-go"
|
||||
revision = "5b341290c488aa6bd76b335d819b4a68516ec3ab"
|
||||
name = "github.com/google/subcommands"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/gosuri/uitable"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/howeyc/gopass"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/jroimartin/gocui"
|
||||
version = "0.3.0"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
@@ -25,12 +59,28 @@
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/kotakanbe/go-cve-dictionary"
|
||||
name = "github.com/knqyf263/go-deb-version"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/kotakanbe/goval-dictionary"
|
||||
name = "github.com/knqyf263/go-rpm-version"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/kotakanbe/go-pingscanner"
|
||||
version = "0.1.0"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/kotakanbe/logrus-prefixed-formatter"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/parnurzeal/gorequest"
|
||||
version = "0.2.15"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/rifflock/lfshook"
|
||||
version = "1.7.0"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/sirupsen/logrus"
|
||||
|
||||
12
README.md
12
README.md
@@ -803,12 +803,12 @@ In order to scan, the following dependencies are required, so you need to instal
|
||||
|:-------------|-------------------:|:-------------|
|
||||
| Ubuntu | 12, 14, 16| - |
|
||||
| Debian | 7, 8| aptitude |
|
||||
| CentOS | 6, 7| yum-plugin-changelog |
|
||||
| Amazon | All | - |
|
||||
| RHEL | 5 | yum-security |
|
||||
| RHEL | 6, 7 | - |
|
||||
| Oracle Linux | 5 | yum-security |
|
||||
| Oracle Linux | 6, 7 | - |
|
||||
| CentOS | 6, 7| yum-plugin-changelog, yum-utils |
|
||||
| Amazon | All | - | TODO yum-utils?, yum-plugin-changelog
|
||||
| RHEL | 5 | yum-security | TODO yum-utils?
|
||||
| RHEL | 6, 7 | - | TODO yum-utils?
|
||||
| Oracle Linux | 5 | yum-security | TODO yum-utils?
|
||||
| Oracle Linux | 6, 7 | - |TODO yum-utils?
|
||||
| FreeBSD | 10 | - |
|
||||
| Raspbian | Wheezy, Jessie | - |
|
||||
|
||||
|
||||
@@ -67,6 +67,7 @@ func (*ScanCmd) Usage() string {
|
||||
[-cachedb-path=/path/to/cache.db]
|
||||
[-ssh-native-insecure]
|
||||
[-containers-only]
|
||||
[-package-list-only]
|
||||
[-skip-broken]
|
||||
[-http-proxy=http://192.168.0.1:8080]
|
||||
[-ask-key-password]
|
||||
|
||||
@@ -418,7 +418,7 @@ type ServerInfo struct {
|
||||
Optional [][]interface{}
|
||||
|
||||
// For CentOS, RHEL, Amazon
|
||||
Enablerepo string
|
||||
Enablerepo []string
|
||||
|
||||
// used internal
|
||||
LogMsgAnsiColor string // DebugLog Color
|
||||
|
||||
@@ -20,7 +20,6 @@ package config
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
"github.com/future-architect/vuls/contrib/owasp-dependency-check/parser"
|
||||
@@ -164,7 +163,7 @@ func (c TOMLLoader) Load(pathToToml, keyPass string) error {
|
||||
s.Enablerepo = d.Enablerepo
|
||||
}
|
||||
if len(s.Enablerepo) != 0 {
|
||||
for _, repo := range strings.Split(s.Enablerepo, ",") {
|
||||
for _, repo := range s.Enablerepo {
|
||||
switch repo {
|
||||
case "base", "updates":
|
||||
// nop
|
||||
|
||||
@@ -18,4 +18,4 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
package models
|
||||
|
||||
// JSONVersion is JSON Version
|
||||
const JSONVersion = "0.3.0"
|
||||
const JSONVersion = 2
|
||||
|
||||
@@ -42,6 +42,7 @@ func (ps Packages) MergeNewVersion(as Packages) {
|
||||
if pack, ok := ps[a.Name]; ok {
|
||||
pack.NewVersion = a.NewVersion
|
||||
pack.NewRelease = a.NewRelease
|
||||
pack.Repository = a.Repository
|
||||
ps[a.Name] = pack
|
||||
}
|
||||
}
|
||||
@@ -79,6 +80,16 @@ func (ps Packages) FormatUpdatablePacksSummary() string {
|
||||
return fmt.Sprintf("%d updatable packages", nUpdatable)
|
||||
}
|
||||
|
||||
// FindOne search a element by name-newver-newrel-arch
|
||||
func (ps Packages) FindOne(f func(Package) bool) (string, Package, bool) {
|
||||
for key, p := range ps {
|
||||
if f(p) {
|
||||
return key, p, true
|
||||
}
|
||||
}
|
||||
return "", Package{}, false
|
||||
}
|
||||
|
||||
// Package has installed packages.
|
||||
type Package struct {
|
||||
Name string
|
||||
@@ -86,6 +97,7 @@ type Package struct {
|
||||
Release string
|
||||
NewVersion string
|
||||
NewRelease string
|
||||
Arch string
|
||||
Repository string
|
||||
Changelog Changelog
|
||||
NotFixedYet bool // Ubuntu OVAL Only
|
||||
@@ -145,8 +157,8 @@ func (p Package) FormatChangelog() string {
|
||||
}
|
||||
|
||||
// Changelog has contents of changelog and how to get it.
|
||||
// Method: modesl.detectionMethodStr
|
||||
// Method: models.detectionMethodStr
|
||||
type Changelog struct {
|
||||
Contents string
|
||||
Method string
|
||||
Method DetectionMethod
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ type ScanResults []ScanResult
|
||||
// ScanResult has the result of scanned CVE information.
|
||||
type ScanResult struct {
|
||||
ScannedAt time.Time
|
||||
JSONVersion string
|
||||
JSONVersion int
|
||||
Lang string
|
||||
ServerName string // TOML Section key
|
||||
Family string
|
||||
|
||||
@@ -26,7 +26,8 @@ import (
|
||||
"github.com/future-architect/vuls/config"
|
||||
)
|
||||
|
||||
// VulnInfos is VulnInfo list, getter/setter, sortable methods.
|
||||
// VulnInfos has a map of VulnInfo
|
||||
// Key: CveID
|
||||
type VulnInfos map[string]VulnInfo
|
||||
|
||||
// Find elements that matches the function passed in argument
|
||||
@@ -198,13 +199,18 @@ type DistroAdvisory struct {
|
||||
// Score: 0 - 100
|
||||
type Confidence struct {
|
||||
Score int
|
||||
DetectionMethod string
|
||||
DetectionMethod DetectionMethod
|
||||
}
|
||||
|
||||
func (c Confidence) String() string {
|
||||
return fmt.Sprintf("%d / %s", c.Score, c.DetectionMethod)
|
||||
}
|
||||
|
||||
// DetectionMethod indicates
|
||||
// - How to detect the CveID
|
||||
// - How to get the changelog difference between installed and candidate version
|
||||
type DetectionMethod string
|
||||
|
||||
const (
|
||||
// CpeNameMatchStr is a String representation of CpeNameMatch
|
||||
CpeNameMatchStr = "CpeNameMatch"
|
||||
|
||||
@@ -24,7 +24,7 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/Azure/azure-storage-go"
|
||||
storage "github.com/Azure/azure-sdk-for-go/storage"
|
||||
|
||||
c "github.com/future-architect/vuls/config"
|
||||
"github.com/future-architect/vuls/models"
|
||||
|
||||
@@ -45,14 +45,12 @@ var currentDetailLimitY int
|
||||
func RunTui(results models.ScanResults) subcommands.ExitStatus {
|
||||
scanResults = results
|
||||
|
||||
g, err := gocui.NewGui(gocui.OutputNormal)
|
||||
if err != nil {
|
||||
log.Errorf("%s", err)
|
||||
return subcommands.ExitFailure
|
||||
}
|
||||
// g, err := gocui.NewGui(gocui.OutputNormal)
|
||||
g := gocui.NewGui()
|
||||
defer g.Close()
|
||||
|
||||
g.SetManagerFunc(layout)
|
||||
g.SetLayout(layout)
|
||||
// g.SetManagerFunc(layout)
|
||||
if err := keybindings(g); err != nil {
|
||||
log.Errorf("%s", err)
|
||||
return subcommands.ExitFailure
|
||||
@@ -177,19 +175,19 @@ func nextView(g *gocui.Gui, v *gocui.View) error {
|
||||
var err error
|
||||
|
||||
if v == nil {
|
||||
_, err = g.SetCurrentView("side")
|
||||
err = g.SetCurrentView("side")
|
||||
}
|
||||
switch v.Name() {
|
||||
case "side":
|
||||
_, err = g.SetCurrentView("summary")
|
||||
err = g.SetCurrentView("summary")
|
||||
case "summary":
|
||||
_, err = g.SetCurrentView("detail")
|
||||
err = g.SetCurrentView("detail")
|
||||
case "detail":
|
||||
_, err = g.SetCurrentView("changelog")
|
||||
err = g.SetCurrentView("changelog")
|
||||
case "changelog":
|
||||
_, err = g.SetCurrentView("side")
|
||||
err = g.SetCurrentView("side")
|
||||
default:
|
||||
_, err = g.SetCurrentView("summary")
|
||||
err = g.SetCurrentView("summary")
|
||||
}
|
||||
return err
|
||||
}
|
||||
@@ -198,19 +196,19 @@ func previousView(g *gocui.Gui, v *gocui.View) error {
|
||||
var err error
|
||||
|
||||
if v == nil {
|
||||
_, err = g.SetCurrentView("side")
|
||||
err = g.SetCurrentView("side")
|
||||
}
|
||||
switch v.Name() {
|
||||
case "side":
|
||||
_, err = g.SetCurrentView("side")
|
||||
err = g.SetCurrentView("side")
|
||||
case "summary":
|
||||
_, err = g.SetCurrentView("side")
|
||||
err = g.SetCurrentView("side")
|
||||
case "detail":
|
||||
_, err = g.SetCurrentView("summary")
|
||||
err = g.SetCurrentView("summary")
|
||||
case "changelog":
|
||||
_, err = g.SetCurrentView("detail")
|
||||
err = g.SetCurrentView("detail")
|
||||
default:
|
||||
_, err = g.SetCurrentView("side")
|
||||
err = g.SetCurrentView("side")
|
||||
}
|
||||
return err
|
||||
}
|
||||
@@ -393,7 +391,7 @@ func cursorPageUp(g *gocui.Gui, v *gocui.View) error {
|
||||
func previousSummary(g *gocui.Gui, v *gocui.View) error {
|
||||
if v != nil {
|
||||
// cursor to summary
|
||||
if _, err := g.SetCurrentView("summary"); err != nil {
|
||||
if err := g.SetCurrentView("summary"); err != nil {
|
||||
return err
|
||||
}
|
||||
// move next line
|
||||
@@ -401,7 +399,7 @@ func previousSummary(g *gocui.Gui, v *gocui.View) error {
|
||||
return err
|
||||
}
|
||||
// cursor to detail
|
||||
if _, err := g.SetCurrentView("detail"); err != nil {
|
||||
if err := g.SetCurrentView("detail"); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -411,7 +409,7 @@ func previousSummary(g *gocui.Gui, v *gocui.View) error {
|
||||
func nextSummary(g *gocui.Gui, v *gocui.View) error {
|
||||
if v != nil {
|
||||
// cursor to summary
|
||||
if _, err := g.SetCurrentView("summary"); err != nil {
|
||||
if err := g.SetCurrentView("summary"); err != nil {
|
||||
return err
|
||||
}
|
||||
// move next line
|
||||
@@ -419,7 +417,7 @@ func nextSummary(g *gocui.Gui, v *gocui.View) error {
|
||||
return err
|
||||
}
|
||||
// cursor to detail
|
||||
if _, err := g.SetCurrentView("detail"); err != nil {
|
||||
if err := g.SetCurrentView("detail"); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -502,7 +500,7 @@ func getLine(g *gocui.Gui, v *gocui.View) error {
|
||||
return err
|
||||
}
|
||||
fmt.Fprintln(v, l)
|
||||
if _, err := g.SetCurrentView("msg"); err != nil {
|
||||
if err := g.SetCurrentView("msg"); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -525,7 +523,7 @@ func showMsg(g *gocui.Gui, v *gocui.View) error {
|
||||
return err
|
||||
}
|
||||
fmt.Fprintln(v, l)
|
||||
if _, err := g.SetCurrentView("msg"); err != nil {
|
||||
if err := g.SetCurrentView("msg"); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -536,7 +534,7 @@ func delMsg(g *gocui.Gui, v *gocui.View) error {
|
||||
if err := g.DeleteView("msg"); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := g.SetCurrentView("summary"); err != nil {
|
||||
if err := g.SetCurrentView("summary"); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
@@ -592,7 +590,7 @@ func setSideLayout(g *gocui.Gui) error {
|
||||
}
|
||||
currentScanResult = scanResults[0]
|
||||
vinfos = scanResults[0].ScannedCves.ToSortedSlice()
|
||||
if _, err := g.SetCurrentView("side"); err != nil {
|
||||
if err := g.SetCurrentView("side"); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,7 +167,7 @@ func (o *debian) checkDependencies() error {
|
||||
}
|
||||
|
||||
func (o *debian) scanPackages() error {
|
||||
installed, upgradable, err := o.scanInstalledPackages()
|
||||
installed, updatable, err := o.scanInstalledPackages()
|
||||
if err != nil {
|
||||
o.log.Errorf("Failed to scan installed packages")
|
||||
return err
|
||||
@@ -178,7 +178,7 @@ func (o *debian) scanPackages() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
unsecure, err := o.scanUnsecurePackages(upgradable)
|
||||
unsecure, err := o.scanUnsecurePackages(updatable)
|
||||
if err != nil {
|
||||
o.log.Errorf("Failed to scan vulnerable packages")
|
||||
return err
|
||||
@@ -189,7 +189,7 @@ func (o *debian) scanPackages() error {
|
||||
|
||||
func (o *debian) scanInstalledPackages() (models.Packages, models.Packages, error) {
|
||||
installed := models.Packages{}
|
||||
upgradable := models.Packages{}
|
||||
updatable := models.Packages{}
|
||||
|
||||
r := o.exec("dpkg-query -W", noSudo)
|
||||
if !r.isSuccess() {
|
||||
@@ -214,27 +214,27 @@ func (o *debian) scanInstalledPackages() (models.Packages, models.Packages, erro
|
||||
}
|
||||
}
|
||||
|
||||
upgradableNames, err := o.GetUpgradablePackNames()
|
||||
updatableNames, err := o.getUpdatablePackNames()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
for _, name := range upgradableNames {
|
||||
for _, name := range updatableNames {
|
||||
for _, pack := range installed {
|
||||
if pack.Name == name {
|
||||
upgradable[name] = pack
|
||||
updatable[name] = pack
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fill the candidate versions of upgradable packages
|
||||
err = o.fillCandidateVersion(upgradable)
|
||||
err = o.fillCandidateVersion(updatable)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("Failed to fill candidate versions. err: %s", err)
|
||||
}
|
||||
installed.MergeNewVersion(upgradable)
|
||||
installed.MergeNewVersion(updatable)
|
||||
|
||||
return installed, upgradable, nil
|
||||
return installed, updatable, nil
|
||||
}
|
||||
|
||||
var packageLinePattern = regexp.MustCompile(`^([^\t']+)\t(.+)$`)
|
||||
@@ -263,14 +263,14 @@ func (o *debian) aptGetUpdate() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *debian) scanUnsecurePackages(upgradable models.Packages) (models.VulnInfos, error) {
|
||||
func (o *debian) scanUnsecurePackages(updatable models.Packages) (models.VulnInfos, error) {
|
||||
o.aptGetUpdate()
|
||||
|
||||
// Setup changelog cache
|
||||
current := cache.Meta{
|
||||
Name: o.getServerInfo().GetServerName(),
|
||||
Distro: o.getServerInfo().Distro,
|
||||
Packs: upgradable,
|
||||
Packs: updatable,
|
||||
}
|
||||
|
||||
o.log.Debugf("Ensure changelog cache: %s", current.Name)
|
||||
@@ -280,7 +280,7 @@ func (o *debian) scanUnsecurePackages(upgradable models.Packages) (models.VulnIn
|
||||
}
|
||||
|
||||
// Collect CVE information of upgradable packages
|
||||
vulnInfos, err := o.scanVulnInfos(upgradable, meta)
|
||||
vulnInfos, err := o.scanVulnInfos(updatable, meta)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to scan unsecure packages. err: %s", err)
|
||||
}
|
||||
@@ -349,7 +349,7 @@ func (o *debian) fillCandidateVersion(packages models.Packages) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (o *debian) GetUpgradablePackNames() (packNames []string, err error) {
|
||||
func (o *debian) getUpdatablePackNames() (packNames []string, err error) {
|
||||
cmd := util.PrependProxyEnv("LANGUAGE=en_US.UTF-8 apt-get upgrade --dry-run")
|
||||
r := o.exec(cmd, noSudo)
|
||||
if r.isSuccess(0, 1) {
|
||||
@@ -360,7 +360,7 @@ func (o *debian) GetUpgradablePackNames() (packNames []string, err error) {
|
||||
cmd, r.ExitStatus, r.Stdout, r.Stderr)
|
||||
}
|
||||
|
||||
func (o *debian) parseAptGetUpgrade(stdout string) (upgradableNames []string, err error) {
|
||||
func (o *debian) parseAptGetUpgrade(stdout string) (updatableNames []string, err error) {
|
||||
startRe := regexp.MustCompile(`The following packages will be upgraded:`)
|
||||
stopRe := regexp.MustCompile(`^(\d+) upgraded.*`)
|
||||
startLineFound, stopLineFound := false, false
|
||||
@@ -375,21 +375,21 @@ func (o *debian) parseAptGetUpgrade(stdout string) (upgradableNames []string, er
|
||||
}
|
||||
result := stopRe.FindStringSubmatch(line)
|
||||
if len(result) == 2 {
|
||||
numUpgradablePacks, err := strconv.Atoi(result[1])
|
||||
nUpdatable, err := strconv.Atoi(result[1])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf(
|
||||
"Failed to scan upgradable packages number. line: %s", line)
|
||||
}
|
||||
if numUpgradablePacks != len(upgradableNames) {
|
||||
if nUpdatable != len(updatableNames) {
|
||||
return nil, fmt.Errorf(
|
||||
"Failed to scan upgradable packages, expected: %s, detected: %d",
|
||||
result[1], len(upgradableNames))
|
||||
result[1], len(updatableNames))
|
||||
}
|
||||
stopLineFound = true
|
||||
o.log.Debugf("Found the stop line. line: %s", line)
|
||||
break
|
||||
}
|
||||
upgradableNames = append(upgradableNames, strings.Fields(line)...)
|
||||
updatableNames = append(updatableNames, strings.Fields(line)...)
|
||||
}
|
||||
if !startLineFound {
|
||||
// no upgrades
|
||||
@@ -410,20 +410,20 @@ type DetectedCveID struct {
|
||||
Confidence models.Confidence
|
||||
}
|
||||
|
||||
func (o *debian) scanVulnInfos(upgradablePacks models.Packages, meta *cache.Meta) (models.VulnInfos, error) {
|
||||
func (o *debian) scanVulnInfos(updatablePacks models.Packages, meta *cache.Meta) (models.VulnInfos, error) {
|
||||
type response struct {
|
||||
pack *models.Package
|
||||
DetectedCveIDs []DetectedCveID
|
||||
}
|
||||
resChan := make(chan response, len(upgradablePacks))
|
||||
errChan := make(chan error, len(upgradablePacks))
|
||||
reqChan := make(chan models.Package, len(upgradablePacks))
|
||||
resChan := make(chan response, len(updatablePacks))
|
||||
errChan := make(chan error, len(updatablePacks))
|
||||
reqChan := make(chan models.Package, len(updatablePacks))
|
||||
defer close(resChan)
|
||||
defer close(errChan)
|
||||
defer close(reqChan)
|
||||
|
||||
go func() {
|
||||
for _, pack := range upgradablePacks {
|
||||
for _, pack := range updatablePacks {
|
||||
reqChan <- pack
|
||||
}
|
||||
}()
|
||||
@@ -431,7 +431,7 @@ func (o *debian) scanVulnInfos(upgradablePacks models.Packages, meta *cache.Meta
|
||||
timeout := time.After(30 * 60 * time.Second)
|
||||
concurrency := 10
|
||||
tasks := util.GenWorkers(concurrency)
|
||||
for range upgradablePacks {
|
||||
for range updatablePacks {
|
||||
tasks <- func() {
|
||||
select {
|
||||
case pack := <-reqChan:
|
||||
@@ -459,7 +459,7 @@ func (o *debian) scanVulnInfos(upgradablePacks models.Packages, meta *cache.Meta
|
||||
// { DetectedCveID{} : [package] }
|
||||
cvePackages := make(map[DetectedCveID][]string)
|
||||
errs := []error{}
|
||||
for i := 0; i < len(upgradablePacks); i++ {
|
||||
for i := 0; i < len(updatablePacks); i++ {
|
||||
select {
|
||||
case response := <-resChan:
|
||||
o.Packages[response.pack.Name] = *response.pack
|
||||
@@ -474,7 +474,7 @@ func (o *debian) scanVulnInfos(upgradablePacks models.Packages, meta *cache.Meta
|
||||
cvePackages[cve] = packNames
|
||||
}
|
||||
o.log.Infof("(%d/%d) Scanned %s: %s",
|
||||
i+1, len(upgradablePacks), response.pack.Name, cves)
|
||||
i+1, len(updatablePacks), response.pack.Name, cves)
|
||||
case err := <-errChan:
|
||||
errs = append(errs, err)
|
||||
case <-timeout:
|
||||
@@ -500,7 +500,7 @@ func (o *debian) scanVulnInfos(upgradablePacks models.Packages, meta *cache.Meta
|
||||
}
|
||||
|
||||
// Update meta package information of changelog cache to the latest one.
|
||||
meta.Packs = upgradablePacks
|
||||
meta.Packs = updatablePacks
|
||||
if err := cache.DB.RefreshMeta(*meta); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -664,7 +664,7 @@ func (o *debian) parseChangelog(changelog, name, ver string, confidence models.C
|
||||
|
||||
clog := models.Changelog{
|
||||
Contents: strings.Join(buf, "\n"),
|
||||
Method: string(confidence.DetectionMethod),
|
||||
Method: confidence.DetectionMethod,
|
||||
}
|
||||
pack := o.Packages[name]
|
||||
pack.Changelog = clog
|
||||
|
||||
713
scan/redhat.go
713
scan/redhat.go
@@ -18,6 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
package scan
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
@@ -27,7 +28,7 @@ import (
|
||||
"github.com/future-architect/vuls/models"
|
||||
"github.com/future-architect/vuls/util"
|
||||
|
||||
"github.com/k0kubun/pp"
|
||||
ver "github.com/knqyf263/go-rpm-version"
|
||||
)
|
||||
|
||||
// inherit OsTypeInterface
|
||||
@@ -147,14 +148,14 @@ func (o *redhat) checkIfSudoNoPasswd() error {
|
||||
if majorVersion < 6 {
|
||||
cmds = []cmd{
|
||||
{"yum --color=never repolist", zero},
|
||||
{"yum --color=never check-update", []int{0, 100}},
|
||||
// {"yum --color=never check-update", []int{0, 100}},
|
||||
{"yum --color=never list-security --security", zero},
|
||||
{"yum --color=never info-security", zero},
|
||||
}
|
||||
} else {
|
||||
cmds = []cmd{
|
||||
{"yum --color=never repolist", zero},
|
||||
{"yum --color=never check-update", []int{0, 100}},
|
||||
// {"yum --color=never check-update", []int{0, 100}},
|
||||
{"yum --color=never --security updateinfo list updates", zero},
|
||||
{"yum --color=never --security updateinfo updates", zero},
|
||||
}
|
||||
@@ -174,12 +175,11 @@ func (o *redhat) checkIfSudoNoPasswd() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// CentOS 6, 7 ... yum-plugin-changelog
|
||||
// CentOS 6, 7 ... yum-plugin-changelog, yum-utils
|
||||
// RHEL 5 ... yum-security
|
||||
// RHEL 6, 7 ... -
|
||||
// Amazon ... -
|
||||
func (o *redhat) checkDependencies() error {
|
||||
var packName string
|
||||
if o.Distro.Family == config.Amazon {
|
||||
return nil
|
||||
}
|
||||
@@ -207,12 +207,14 @@ func (o *redhat) checkDependencies() error {
|
||||
}
|
||||
}
|
||||
|
||||
//TODO Check if yum-plugin-changelog is installed when scan with --changelog option on Amazon,RHEL, Oracle
|
||||
var packNames []string
|
||||
switch o.Distro.Family {
|
||||
case config.CentOS:
|
||||
packName = "yum-plugin-changelog"
|
||||
packNames = []string{"yum-plugin-changelog", "yum-utils"}
|
||||
case config.RedHat, config.Oracle:
|
||||
if majorVersion < 6 {
|
||||
packName = "yum-security"
|
||||
packNames = []string{"yum-security"}
|
||||
} else {
|
||||
// yum-plugin-security is installed by default on RHEL6, 7
|
||||
return nil
|
||||
@@ -221,27 +223,45 @@ func (o *redhat) checkDependencies() error {
|
||||
return fmt.Errorf("Not implemented yet: %s", o.Distro)
|
||||
}
|
||||
|
||||
cmd := "rpm -q " + packName
|
||||
if r := o.exec(cmd, noSudo); !r.isSuccess() {
|
||||
msg := fmt.Sprintf("%s is not installed", packName)
|
||||
o.log.Errorf(msg)
|
||||
return fmt.Errorf(msg)
|
||||
for _, name := range packNames {
|
||||
cmd := "rpm -q " + name
|
||||
if r := o.exec(cmd, noSudo); !r.isSuccess() {
|
||||
msg := fmt.Sprintf("%s is not installed", name)
|
||||
o.log.Errorf(msg)
|
||||
return fmt.Errorf(msg)
|
||||
}
|
||||
}
|
||||
o.log.Infof("Dependencies... Pass")
|
||||
o.log.Infof("Dependencies ... Pass")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *redhat) scanPackages() error {
|
||||
var err error
|
||||
var packs []models.Package
|
||||
if packs, err = o.scanInstalledPackages(); err != nil {
|
||||
installed, err := o.scanInstalledPackages()
|
||||
if err != nil {
|
||||
o.log.Errorf("Failed to scan installed packages")
|
||||
return err
|
||||
}
|
||||
o.setPackages(models.NewPackages(packs...))
|
||||
|
||||
updatable, err := o.scanUpdatablePackages()
|
||||
if err != nil {
|
||||
o.log.Errorf("Failed to scan installed packages")
|
||||
return err
|
||||
}
|
||||
installed.MergeNewVersion(updatable)
|
||||
o.setPackages(installed)
|
||||
|
||||
if config.Conf.PackageListOnly {
|
||||
return nil
|
||||
}
|
||||
|
||||
//TODO Cache changelogs to bolt
|
||||
//TODO --with-changelog
|
||||
if err := o.fillChangelogs(updatable); err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
var vinfos models.VulnInfos
|
||||
if vinfos, err = o.scanVulnInfos(); err != nil {
|
||||
if vinfos, err = o.scanUnsecurePackages(updatable); err != nil {
|
||||
o.log.Errorf("Failed to scan vulnerable packages")
|
||||
return err
|
||||
}
|
||||
@@ -249,406 +269,360 @@ func (o *redhat) scanPackages() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *redhat) scanInstalledPackages() (installed []models.Package, err error) {
|
||||
cmd := "rpm -qa --queryformat '%{NAME}\t%{EPOCHNUM}\t%{VERSION}\t%{RELEASE}\n'"
|
||||
func (o *redhat) scanInstalledPackages() (models.Packages, error) {
|
||||
installed := models.Packages{}
|
||||
cmd := "rpm -qa --queryformat '%{NAME} %{EPOCHNUM} %{VERSION} %{RELEASE} %{ARCH}\n'"
|
||||
r := o.exec(cmd, noSudo)
|
||||
if r.isSuccess() {
|
||||
// e.g.
|
||||
// openssl 1.0.1e 30.el6.11
|
||||
// openssl 0 1.0.1e 30.el6.11 x86_64
|
||||
lines := strings.Split(r.Stdout, "\n")
|
||||
for _, line := range lines {
|
||||
if trimed := strings.TrimSpace(line); len(trimed) != 0 {
|
||||
var pack models.Package
|
||||
if pack, err = o.parseScannedPackagesLine(line); err != nil {
|
||||
return
|
||||
pack, err := o.parseInstalledPackagesLine(line)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
installed = append(installed, pack)
|
||||
installed[pack.Name] = pack
|
||||
}
|
||||
}
|
||||
return
|
||||
return installed, nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf(
|
||||
"Scan packages failed. status: %d, stdout: %s, stderr: %s",
|
||||
return nil, fmt.Errorf("Scan packages failed. status: %d, stdout: %s, stderr: %s",
|
||||
r.ExitStatus, r.Stdout, r.Stderr)
|
||||
|
||||
}
|
||||
|
||||
func (o *redhat) parseScannedPackagesLine(line string) (models.Package, error) {
|
||||
func (o *redhat) parseInstalledPackagesLine(line string) (models.Package, error) {
|
||||
fields := strings.Fields(line)
|
||||
if len(fields) != 4 {
|
||||
if len(fields) != 5 {
|
||||
return models.Package{},
|
||||
fmt.Errorf("Failed to parse package line: %s", line)
|
||||
}
|
||||
ver := ""
|
||||
if fields[1] == "0" {
|
||||
epoch := fields[1]
|
||||
if epoch == "0" {
|
||||
ver = fields[2]
|
||||
} else {
|
||||
ver = fmt.Sprintf("%s:%s", fields[1], fields[2])
|
||||
ver = fmt.Sprintf("%s:%s", epoch, fields[2])
|
||||
}
|
||||
|
||||
return models.Package{
|
||||
Name: fields[0],
|
||||
Version: ver,
|
||||
Release: fields[3],
|
||||
Arch: fields[4],
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (o *redhat) scanVulnInfos() (models.VulnInfos, error) {
|
||||
if o.Distro.Family != config.CentOS {
|
||||
// Amazon, RHEL, Oracle Linux has yum updateinfo as default
|
||||
// yum updateinfo can collenct vendor advisory information.
|
||||
return o.scanUnsecurePackagesUsingYumPluginSecurity()
|
||||
}
|
||||
// CentOS does not have security channel...
|
||||
// So, yum check-update then parse chnagelog.
|
||||
return o.scanUnsecurePackagesUsingYumCheckUpdate()
|
||||
}
|
||||
|
||||
// For CentOS
|
||||
func (o *redhat) scanUnsecurePackagesUsingYumCheckUpdate() (models.VulnInfos, error) {
|
||||
cmd := "LANGUAGE=en_US.UTF-8 yum --color=never %s check-update"
|
||||
if o.getServerInfo().Enablerepo != "" {
|
||||
cmd = fmt.Sprintf(cmd, "--enablerepo="+o.getServerInfo().Enablerepo)
|
||||
} else {
|
||||
cmd = fmt.Sprintf(cmd, "")
|
||||
func (o *redhat) scanUpdatablePackages() (models.Packages, error) {
|
||||
cmd := "repoquery --all --pkgnarrow=updates --qf='%{NAME} %{EPOCH} %{VERSION} %{RELEASE} %{REPO}'"
|
||||
for _, repo := range o.getServerInfo().Enablerepo {
|
||||
cmd += " --enablerepo=" + repo
|
||||
}
|
||||
|
||||
r := o.exec(util.PrependProxyEnv(cmd), noSudo)
|
||||
if !r.isSuccess(0, 100) {
|
||||
//returns an exit code of 100 if there are available updates.
|
||||
r := o.exec(util.PrependProxyEnv(cmd), o.sudo())
|
||||
if !r.isSuccess() {
|
||||
return nil, fmt.Errorf("Failed to SSH: %s", r)
|
||||
}
|
||||
|
||||
// get Updateble package name, installed, candidate version.
|
||||
packages, err := o.parseYumCheckUpdateLines(r.Stdout)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to parse %s. err: %s", cmd, err)
|
||||
}
|
||||
o.log.Debugf("%s", pp.Sprintf("%v", packages))
|
||||
|
||||
// set candidate version info
|
||||
o.Packages.MergeNewVersion(packages)
|
||||
|
||||
// Collect CVE-IDs in changelog
|
||||
type PackageCveIDs struct {
|
||||
Package models.Package
|
||||
CveIDs []string
|
||||
}
|
||||
|
||||
allChangelog, err := o.getAllChangelog(packages)
|
||||
if err != nil {
|
||||
o.log.Errorf("Failed to getAllchangelog. err: %s", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// { packageName: changelog-lines }
|
||||
var rpm2changelog map[string]*string
|
||||
rpm2changelog, err = o.divideChangelogByPackage(allChangelog)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to parseAllChangelog. err: %s", err)
|
||||
}
|
||||
|
||||
for name, clog := range rpm2changelog {
|
||||
for _, p := range o.Packages {
|
||||
n := fmt.Sprintf("%s-%s-%s", p.Name, p.NewVersion, p.NewRelease)
|
||||
if name == n {
|
||||
p.Changelog = models.Changelog{
|
||||
Contents: *clog,
|
||||
Method: models.ChangelogExactMatchStr,
|
||||
}
|
||||
o.Packages[p.Name] = p
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var results []PackageCveIDs
|
||||
i := 0
|
||||
for name := range packages {
|
||||
changelog := o.getChangelogCVELines(rpm2changelog, packages[name])
|
||||
|
||||
// Collect unique set of CVE-ID in each changelog
|
||||
uniqueCveIDMap := make(map[string]bool)
|
||||
lines := strings.Split(changelog, "\n")
|
||||
for _, line := range lines {
|
||||
cveIDs := o.parseYumUpdateinfoLineToGetCveIDs(line)
|
||||
for _, c := range cveIDs {
|
||||
uniqueCveIDMap[c] = true
|
||||
}
|
||||
}
|
||||
|
||||
// keys
|
||||
var cveIDs []string
|
||||
for k := range uniqueCveIDMap {
|
||||
cveIDs = append(cveIDs, k)
|
||||
}
|
||||
p := PackageCveIDs{
|
||||
Package: packages[name],
|
||||
CveIDs: cveIDs,
|
||||
}
|
||||
results = append(results, p)
|
||||
|
||||
o.log.Infof("(%d/%d) Scanned %s-%s-%s -> %s-%s : %s",
|
||||
i+1,
|
||||
len(packages),
|
||||
p.Package.Name,
|
||||
p.Package.Version,
|
||||
p.Package.Release,
|
||||
p.Package.NewVersion,
|
||||
p.Package.NewRelease,
|
||||
p.CveIDs)
|
||||
i++
|
||||
}
|
||||
|
||||
// transform datastructure
|
||||
// - From
|
||||
// [
|
||||
// {
|
||||
// Pack: models.Packages,
|
||||
// CveIDs: []string,
|
||||
// },
|
||||
// ]
|
||||
// - To
|
||||
// map {
|
||||
// CveID: models.Packages{}
|
||||
// }
|
||||
cveIDPackages := make(map[string]models.Packages)
|
||||
for _, res := range results {
|
||||
for _, cveID := range res.CveIDs {
|
||||
if packages, ok := cveIDPackages[cveID]; ok {
|
||||
packages[res.Package.Name] = res.Package
|
||||
cveIDPackages[cveID] = packages
|
||||
} else {
|
||||
cveIDPackages[cveID] = models.NewPackages(res.Package)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vinfos := models.VulnInfos{}
|
||||
for cveID, packs := range cveIDPackages {
|
||||
names := []string{}
|
||||
for name := range packs {
|
||||
names = append(names, name)
|
||||
}
|
||||
|
||||
// Amazon, RHEL do not use this method, so VendorAdvisory do not set.
|
||||
vinfos[cveID] = models.VulnInfo{
|
||||
CveID: cveID,
|
||||
PackageNames: names,
|
||||
Confidence: models.ChangelogExactMatch,
|
||||
}
|
||||
}
|
||||
return vinfos, nil
|
||||
// Collect Updateble packages, installed, candidate version and repository.
|
||||
return o.parseUpdatablePacksLines(r.Stdout)
|
||||
}
|
||||
|
||||
// parseYumCheckUpdateLines parse yum check-update to get package name, candidate version
|
||||
func (o *redhat) parseYumCheckUpdateLines(stdout string) (models.Packages, error) {
|
||||
results := models.Packages{}
|
||||
needToParse := false
|
||||
// parseUpdatablePacksLines parse the stdout of repoquery to get package name, candidate version
|
||||
func (o *redhat) parseUpdatablePacksLines(stdout string) (models.Packages, error) {
|
||||
updatable := models.Packages{}
|
||||
lines := strings.Split(stdout, "\n")
|
||||
for _, line := range lines {
|
||||
// update information of packages begin after blank line.
|
||||
if trimed := strings.TrimSpace(line); len(trimed) == 0 {
|
||||
needToParse = true
|
||||
// TODO remove
|
||||
// if strings.HasPrefix(line, "Obsoleting") ||
|
||||
// strings.HasPrefix(line, "Security:") {
|
||||
// // see https://github.com/future-architect/vuls/issues/165
|
||||
// continue
|
||||
// }
|
||||
if len(strings.TrimSpace(line)) == 0 {
|
||||
continue
|
||||
}
|
||||
if needToParse {
|
||||
if strings.HasPrefix(line, "Obsoleting") ||
|
||||
strings.HasPrefix(line, "Security:") {
|
||||
// see https://github.com/future-architect/vuls/issues/165
|
||||
continue
|
||||
}
|
||||
candidate, err := o.parseYumCheckUpdateLine(line)
|
||||
if err != nil {
|
||||
return results, err
|
||||
}
|
||||
|
||||
installed, found := o.Packages[candidate.Name]
|
||||
if !found {
|
||||
o.log.Warnf("Not found the package in rpm -qa. candidate: %s-%s-%s",
|
||||
candidate.Name, candidate.Version, candidate.Release)
|
||||
results[candidate.Name] = candidate
|
||||
continue
|
||||
}
|
||||
installed.NewVersion = candidate.NewVersion
|
||||
installed.NewRelease = candidate.NewRelease
|
||||
installed.Repository = candidate.Repository
|
||||
results[installed.Name] = installed
|
||||
pack, err := o.parseUpdatablePacksLine(line)
|
||||
if err != nil {
|
||||
return updatable, err
|
||||
}
|
||||
updatable[pack.Name] = pack
|
||||
}
|
||||
return results, nil
|
||||
return updatable, nil
|
||||
}
|
||||
|
||||
func (o *redhat) parseYumCheckUpdateLine(line string) (models.Package, error) {
|
||||
func (o *redhat) parseUpdatablePacksLine(line string) (models.Package, error) {
|
||||
fields := strings.Fields(line)
|
||||
if len(fields) < 3 {
|
||||
return models.Package{}, fmt.Errorf("Unknown format: %s", line)
|
||||
if len(fields) < 5 {
|
||||
return models.Package{}, fmt.Errorf("Unknown format: %s, fields: %s", line, fields)
|
||||
}
|
||||
splitted := strings.Split(fields[0], ".")
|
||||
packName := ""
|
||||
if len(splitted) == 1 {
|
||||
packName = fields[0]
|
||||
|
||||
ver := ""
|
||||
epoch := fields[1]
|
||||
if epoch == "0" {
|
||||
ver = fields[2]
|
||||
} else {
|
||||
packName = strings.Join(strings.Split(fields[0], ".")[0:(len(splitted)-1)], ".")
|
||||
ver = fmt.Sprintf("%s:%s", epoch, fields[2])
|
||||
}
|
||||
|
||||
verfields := strings.Split(fields[1], "-")
|
||||
if len(verfields) != 2 {
|
||||
return models.Package{}, fmt.Errorf("Unknown format: %s", line)
|
||||
}
|
||||
release := verfields[1]
|
||||
repos := strings.Join(fields[2:len(fields)], " ")
|
||||
repos := strings.Join(fields[4:len(fields)], " ")
|
||||
|
||||
return models.Package{
|
||||
Name: packName,
|
||||
NewVersion: verfields[0],
|
||||
NewRelease: release,
|
||||
p := models.Package{
|
||||
Name: fields[0],
|
||||
NewVersion: ver,
|
||||
NewRelease: fields[3],
|
||||
Repository: repos,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (o *redhat) mkPstring() *string {
|
||||
str := ""
|
||||
return &str
|
||||
}
|
||||
|
||||
func (o *redhat) regexpReplace(src string, pat string, rep string) string {
|
||||
re := regexp.MustCompile(pat)
|
||||
return re.ReplaceAllString(src, rep)
|
||||
}
|
||||
|
||||
var changeLogCVEPattern = regexp.MustCompile(`CVE-[0-9]+-[0-9]+`)
|
||||
|
||||
func (o *redhat) getChangelogCVELines(rpm2changelog map[string]*string, pack models.Package) string {
|
||||
rpm := fmt.Sprintf("%s-%s-%s", pack.Name, pack.NewVersion, pack.NewRelease)
|
||||
retLine := ""
|
||||
if rpm2changelog[rpm] != nil {
|
||||
lines := strings.Split(*rpm2changelog[rpm], "\n")
|
||||
for _, line := range lines {
|
||||
if changeLogCVEPattern.MatchString(line) {
|
||||
retLine += fmt.Sprintf("%s\n", line)
|
||||
}
|
||||
}
|
||||
}
|
||||
return retLine
|
||||
return p, nil
|
||||
}
|
||||
|
||||
func (o *redhat) divideChangelogByPackage(allChangelog string) (map[string]*string, error) {
|
||||
var majorVersion int
|
||||
var err error
|
||||
if o.Distro.Family == config.CentOS {
|
||||
majorVersion, err = o.Distro.MajorVersion()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Not implemented yet: %s, err: %s", o.Distro, err)
|
||||
func (o *redhat) scanUnsecurePackages(updatable models.Packages) (models.VulnInfos, error) {
|
||||
if o.Distro.Family != config.CentOS {
|
||||
// Amazon, RHEL, Oracle Linux has yum updateinfo as default
|
||||
// yum updateinfo can collenct vendor advisory information.
|
||||
return o.scanCveIDsByCommands(updatable)
|
||||
}
|
||||
|
||||
// Parse chnagelog because CentOS does not have security channel...
|
||||
return o.scanCveIDsInChangelog(updatable)
|
||||
}
|
||||
|
||||
func (o *redhat) fillChangelogs(updatables models.Packages) error {
|
||||
names := []string{}
|
||||
for name := range updatables {
|
||||
names = append(names, name)
|
||||
}
|
||||
|
||||
if err := o.fillDiffChangelogs(names); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
emptyChangelogPackNames := []string{}
|
||||
for _, pack := range o.Packages {
|
||||
if pack.NewVersion != "" && pack.Changelog.Contents == "" {
|
||||
emptyChangelogPackNames = append(emptyChangelogPackNames, pack.Name)
|
||||
}
|
||||
}
|
||||
|
||||
orglines := strings.Split(allChangelog, "\n")
|
||||
tmpline := ""
|
||||
var lines []string
|
||||
var prev, now bool
|
||||
for i := range orglines {
|
||||
if majorVersion == 5 {
|
||||
/* for CentOS5 (yum-util < 1.1.20) */
|
||||
prev = false
|
||||
now = false
|
||||
if 0 < i {
|
||||
prev, err = o.isRpmPackageNameLine(orglines[i-1])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
now, err = o.isRpmPackageNameLine(orglines[i])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if prev && now {
|
||||
tmpline = fmt.Sprintf("%s, %s", tmpline, orglines[i])
|
||||
continue
|
||||
}
|
||||
if !prev && now {
|
||||
tmpline = fmt.Sprintf("%s%s", tmpline, orglines[i])
|
||||
continue
|
||||
}
|
||||
if tmpline != "" {
|
||||
lines = append(lines, fmt.Sprintf("%s", tmpline))
|
||||
tmpline = ""
|
||||
}
|
||||
lines = append(lines, fmt.Sprintf("%s", orglines[i]))
|
||||
} else {
|
||||
/* for CentOS6,7 (yum-util >= 1.1.20) */
|
||||
line := orglines[i]
|
||||
line = o.regexpReplace(line, `^ChangeLog for: `, "")
|
||||
line = o.regexpReplace(line, `^\*\*\sNo\sChangeLog\sfor:.*`, "")
|
||||
lines = append(lines, line)
|
||||
i := 0
|
||||
for _, name := range emptyChangelogPackNames {
|
||||
i++
|
||||
o.log.Infof("(%d/%d) Fetched Changelogs %s", i, len(emptyChangelogPackNames), name)
|
||||
if err := o.fillDiffChangelogs([]string{name}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
rpm2changelog := make(map[string]*string)
|
||||
writePointer := o.mkPstring()
|
||||
for _, line := range lines {
|
||||
match, err := o.isRpmPackageNameLine(line)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if match {
|
||||
rpms := strings.Split(line, ",")
|
||||
pNewString := o.mkPstring()
|
||||
writePointer = pNewString
|
||||
for _, rpm := range rpms {
|
||||
rpm = strings.TrimSpace(rpm)
|
||||
rpm = o.regexpReplace(rpm, `\.(i386|i486|i586|i686|k6|athlon|x86_64|noarch|ppc|alpha|sparc)$`, "")
|
||||
if ss := strings.Split(rpm, ":"); 1 < len(ss) {
|
||||
epoch := ss[0]
|
||||
packVersion := strings.Join(ss[1:len(ss)], ":")
|
||||
if sss := strings.Split(packVersion, "-"); 2 < len(sss) {
|
||||
version := strings.Join(sss[len(sss)-2:len(sss)], "-")
|
||||
name := strings.Join(sss[0:len(sss)-2], "-")
|
||||
rpm = fmt.Sprintf("%s-%s:%s", name, epoch, version)
|
||||
}
|
||||
}
|
||||
|
||||
rpm2changelog[rpm] = pNewString
|
||||
}
|
||||
} else {
|
||||
if strings.HasPrefix(line, "Dependencies Resolved") {
|
||||
return rpm2changelog, nil
|
||||
}
|
||||
*writePointer += fmt.Sprintf("%s\n", line)
|
||||
}
|
||||
}
|
||||
return rpm2changelog, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
// CentOS
|
||||
func (o *redhat) getAllChangelog(packages models.Packages) (stdout string, err error) {
|
||||
packageNames := ""
|
||||
for _, pack := range packages {
|
||||
packageNames += fmt.Sprintf("%s ", pack.Name)
|
||||
}
|
||||
|
||||
command := ""
|
||||
if 0 < len(config.Conf.HTTPProxy) {
|
||||
command += util.ProxyEnv()
|
||||
}
|
||||
|
||||
func (o *redhat) getAvailableChangelogs(packNames []string) (map[string]string, error) {
|
||||
yumopts := ""
|
||||
if o.getServerInfo().Enablerepo != "" {
|
||||
yumopts = " --enablerepo=" + o.getServerInfo().Enablerepo
|
||||
if 0 < len(o.getServerInfo().Enablerepo) {
|
||||
yumopts = " --enablerepo=" + strings.Join(o.getServerInfo().Enablerepo, ",")
|
||||
}
|
||||
if config.Conf.SkipBroken {
|
||||
yumopts += " --skip-broken"
|
||||
}
|
||||
cmd := `yum --color=never %s changelog all %s | grep -A 10000 '==================== Available Packages ===================='`
|
||||
cmd = fmt.Sprintf(cmd, yumopts, strings.Join(packNames, " "))
|
||||
|
||||
// yum update --changelog doesn't have --color option.
|
||||
command += fmt.Sprintf(" LANGUAGE=en_US.UTF-8 yum --changelog --assumeno update %s ", yumopts) + packageNames
|
||||
|
||||
r := o.exec(command, sudo)
|
||||
r := o.exec(util.PrependProxyEnv(cmd), noSudo)
|
||||
if !r.isSuccess(0, 1) {
|
||||
return "", fmt.Errorf(
|
||||
"Failed to get changelog. status: %d, stdout: %s, stderr: %s",
|
||||
r.ExitStatus, r.Stdout, r.Stderr)
|
||||
return nil, fmt.Errorf("Failed to SSH: %s", r)
|
||||
}
|
||||
return strings.Replace(r.Stdout, "\r", "", -1), nil
|
||||
|
||||
return o.divideChangelogsIntoEachPackages(r.Stdout), nil
|
||||
}
|
||||
|
||||
// Divide available change logs of all updatable packages into each package's changelog
|
||||
func (o *redhat) divideChangelogsIntoEachPackages(stdout string) map[string]string {
|
||||
changelogs := make(map[string]string)
|
||||
scanner := bufio.NewScanner(strings.NewReader(stdout))
|
||||
|
||||
crlf, newBlock := false, true
|
||||
packNameVer, contents := "", []string{}
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
if strings.HasPrefix(line, "==================== Available Packages ====================") {
|
||||
continue
|
||||
}
|
||||
if newBlock {
|
||||
left := strings.Fields(line)[0]
|
||||
// ss := strings.Split(left, ".")
|
||||
// packNameVer = strings.Join(ss[0:len(ss)-1], ".")
|
||||
packNameVer = left
|
||||
newBlock = false
|
||||
continue
|
||||
}
|
||||
if len(strings.TrimSpace(line)) == 0 {
|
||||
if crlf {
|
||||
changelogs[packNameVer] = strings.Join(contents, "\n")
|
||||
packNameVer = ""
|
||||
contents = []string{}
|
||||
newBlock = true
|
||||
crlf = false
|
||||
} else {
|
||||
contents = append(contents, line)
|
||||
crlf = true
|
||||
}
|
||||
} else {
|
||||
contents = append(contents, line)
|
||||
crlf = false
|
||||
}
|
||||
}
|
||||
if 0 < len(contents) {
|
||||
changelogs[packNameVer] = strings.Join(contents, "\n")
|
||||
}
|
||||
return changelogs
|
||||
}
|
||||
|
||||
func (o *redhat) fillDiffChangelogs(packNames []string) error {
|
||||
changelogs, err := o.getAvailableChangelogs(packNames)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for s := range changelogs {
|
||||
// name, pack, found := o.Packages.FindOne(func(p models.Package) bool {
|
||||
name, pack, found := o.Packages.FindOne(func(p models.Package) bool {
|
||||
var epochNameVerRel string
|
||||
if index := strings.Index(p.NewVersion, ":"); 0 < index {
|
||||
epoch := p.NewVersion[0:index]
|
||||
ver := p.NewVersion[index+1 : len(p.NewVersion)]
|
||||
epochNameVerRel = fmt.Sprintf("%s:%s-%s",
|
||||
epoch, p.Name, ver)
|
||||
} else {
|
||||
epochNameVerRel = fmt.Sprintf("%s-%s",
|
||||
p.Name, p.NewVersion)
|
||||
}
|
||||
return strings.HasPrefix(s, epochNameVerRel)
|
||||
})
|
||||
|
||||
if found {
|
||||
diff, err := o.getDiffChangelog(pack, changelogs[s])
|
||||
detectionMethod := models.ChangelogExactMatchStr
|
||||
|
||||
if err != nil {
|
||||
o.log.Debug(err)
|
||||
// Try without epoch
|
||||
if index := strings.Index(pack.Version, ":"); 0 < index {
|
||||
pack.Version = pack.Version[index+1 : len(pack.Version)]
|
||||
o.log.Debug("Try without epoch", pack)
|
||||
diff, err = o.getDiffChangelog(pack, changelogs[s])
|
||||
if err != nil {
|
||||
o.log.Debugf("Failed to find the version in changelog: %s-%s-%s",
|
||||
pack.Name, pack.Version, pack.Release)
|
||||
detectionMethod = models.FailedToFindVersionInChangelog
|
||||
} else {
|
||||
o.log.Debugf("Found the version in changelog without epoch: %s-%s-%s",
|
||||
pack.Name, pack.Version, pack.Release)
|
||||
detectionMethod = models.ChangelogLenientMatchStr
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pack = o.Packages[name]
|
||||
pack.Changelog = models.Changelog{
|
||||
Contents: diff,
|
||||
Method: models.DetectionMethod(detectionMethod),
|
||||
}
|
||||
o.Packages[name] = pack
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *redhat) getDiffChangelog(pack models.Package, availableChangelog string) (string, error) {
|
||||
installedVer := ver.NewVersion(fmt.Sprintf("%s-%s", pack.Version, pack.Release))
|
||||
scanner := bufio.NewScanner(strings.NewReader(availableChangelog))
|
||||
diff := []string{}
|
||||
found := false
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
if !strings.HasPrefix(line, "* ") {
|
||||
diff = append(diff, line)
|
||||
continue
|
||||
}
|
||||
|
||||
// openssh on RHEL
|
||||
// openssh-server-6.6.1p1-35.el7_3.x86_64 rhui-rhel-7-server-rhui-rpms
|
||||
// Wed Mar 1 21:00:00 2017 Jakub Jelen <jjelen@redhat.com> - 6.6.1p1-35 + 0.9.3-9
|
||||
ss := strings.Split(line, " + ")
|
||||
if 1 < len(ss) {
|
||||
line = ss[0]
|
||||
}
|
||||
|
||||
ss = strings.Split(line, " ")
|
||||
if len(ss) < 2 {
|
||||
diff = append(diff, line)
|
||||
continue
|
||||
}
|
||||
v := ss[len(ss)-1]
|
||||
v = strings.TrimPrefix(v, "-")
|
||||
v = strings.TrimPrefix(v, "[")
|
||||
v = strings.TrimSuffix(v, "]")
|
||||
version := ver.NewVersion(v)
|
||||
if installedVer.Equal(version) || installedVer.GreaterThan(version) {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
diff = append(diff, line)
|
||||
}
|
||||
|
||||
if len(diff) == 0 || !found {
|
||||
return availableChangelog,
|
||||
fmt.Errorf("Failed to find the version in changelog: %s-%s-%s",
|
||||
pack.Name, pack.Version, pack.Release)
|
||||
}
|
||||
return strings.TrimSpace(strings.Join(diff, "\n")), nil
|
||||
}
|
||||
|
||||
func (o *redhat) scanCveIDsInChangelog(updatable models.Packages) (models.VulnInfos, error) {
|
||||
packCveIDs := make(map[string][]string)
|
||||
for name := range updatable {
|
||||
cveIDs := []string{}
|
||||
pack := o.Packages[name]
|
||||
if pack.Changelog.Method == models.FailedToFindVersionInChangelog {
|
||||
continue
|
||||
}
|
||||
scanner := bufio.NewScanner(strings.NewReader(pack.Changelog.Contents))
|
||||
for scanner.Scan() {
|
||||
if matches := cveRe.FindAllString(scanner.Text(), -1); 0 < len(matches) {
|
||||
for _, m := range matches {
|
||||
cveIDs = util.AppendIfMissing(cveIDs, m)
|
||||
}
|
||||
}
|
||||
}
|
||||
packCveIDs[name] = cveIDs
|
||||
}
|
||||
|
||||
// transform datastructure
|
||||
// - From
|
||||
// "packname": []{"CVE-2017-1111", ".../
|
||||
//
|
||||
// - To
|
||||
// map {
|
||||
// "CVE-2017-1111": "packname",
|
||||
// }
|
||||
vinfos := models.VulnInfos{}
|
||||
for name, cveIDs := range packCveIDs {
|
||||
for _, cid := range cveIDs {
|
||||
if v, ok := vinfos[cid]; ok {
|
||||
v.PackageNames = append(v.PackageNames, name)
|
||||
vinfos[cid] = v
|
||||
} else {
|
||||
vinfos[cid] = models.VulnInfo{
|
||||
CveID: cid,
|
||||
PackageNames: []string{name},
|
||||
Confidence: models.ChangelogExactMatch,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return vinfos, nil
|
||||
}
|
||||
|
||||
type distroAdvisoryCveIDs struct {
|
||||
@@ -658,7 +632,7 @@ type distroAdvisoryCveIDs struct {
|
||||
|
||||
// Scaning unsecure packages using yum-plugin-security.
|
||||
// Amazon, RHEL, Oracle Linux
|
||||
func (o *redhat) scanUnsecurePackagesUsingYumPluginSecurity() (models.VulnInfos, error) {
|
||||
func (o *redhat) scanCveIDsByCommands(updatable models.Packages) (models.VulnInfos, error) {
|
||||
if o.Distro.Family == config.CentOS {
|
||||
// CentOS has no security channel.
|
||||
// So use yum check-update && parse changelog
|
||||
@@ -689,22 +663,6 @@ func (o *redhat) scanUnsecurePackagesUsingYumPluginSecurity() (models.VulnInfos,
|
||||
}
|
||||
advIDPackNamesList, err := o.parseYumUpdateinfoListAvailable(r.Stdout)
|
||||
|
||||
// get package name, version, rel to be upgrade.
|
||||
cmd = "LANGUAGE=en_US.UTF-8 yum --color=never check-update"
|
||||
r = o.exec(util.PrependProxyEnv(cmd), o.sudo())
|
||||
if !r.isSuccess(0, 100) {
|
||||
//returns an exit code of 100 if there are available updates.
|
||||
return nil, fmt.Errorf("Failed to SSH: %s", r)
|
||||
}
|
||||
updatable, err := o.parseYumCheckUpdateLines(r.Stdout)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to parse %s. err: %s", cmd, err)
|
||||
}
|
||||
o.log.Debugf("%s", pp.Sprintf("%v", updatable))
|
||||
|
||||
// set candidate version info
|
||||
o.Packages.MergeNewVersion(updatable)
|
||||
|
||||
dict := make(map[string]models.Packages)
|
||||
for _, advIDPackNames := range advIDPackNamesList {
|
||||
packages := models.Packages{}
|
||||
@@ -796,8 +754,6 @@ func (o *redhat) parseYumUpdateinfo(stdout string) (result []distroAdvisoryCveID
|
||||
for cveID := range cveIDsSetInThisSection {
|
||||
foundCveIDs = append(foundCveIDs, cveID)
|
||||
}
|
||||
//TODO remove
|
||||
// sort.Strings(foundCveIDs)
|
||||
|
||||
result = append(result, distroAdvisoryCveIDs{
|
||||
DistroAdvisory: advisory,
|
||||
@@ -883,24 +839,6 @@ func (o *redhat) changeSectionState(state int) (newState int) {
|
||||
return newState
|
||||
}
|
||||
|
||||
var rpmPackageArchPattern = regexp.MustCompile(
|
||||
`^[^ ]+\.(i386|i486|i586|i686|k6|athlon|x86_64|noarch|ppc|alpha|sparc)$`)
|
||||
|
||||
func (o *redhat) isRpmPackageNameLine(line string) (bool, error) {
|
||||
s := strings.TrimPrefix(line, "ChangeLog for: ")
|
||||
ss := strings.Split(s, ", ")
|
||||
if len(ss) == 0 {
|
||||
return false, nil
|
||||
}
|
||||
for _, s := range ss {
|
||||
s = strings.TrimRight(s, " \r\n")
|
||||
if !rpmPackageArchPattern.MatchString(s) {
|
||||
return false, nil
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
var yumCveIDPattern = regexp.MustCompile(`(CVE-\d{4}-\d{4,})`)
|
||||
|
||||
func (o *redhat) parseYumUpdateinfoLineToGetCveIDs(line string) []string {
|
||||
@@ -1032,9 +970,10 @@ func (o *redhat) clone() osTypeInterface {
|
||||
|
||||
func (o *redhat) sudo() bool {
|
||||
switch o.Distro.Family {
|
||||
case config.Amazon:
|
||||
case config.Amazon, config.CentOS:
|
||||
return false
|
||||
default:
|
||||
// RHEL
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user