refactor(scan): remove yum-security related code (#836)
* refactor(scan): remove yum-security related code * fix(reporting): error if no OVAL entry
This commit is contained in:
		@@ -100,18 +100,6 @@ func (o rootPrivAmazon) repoquery() bool {
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o rootPrivAmazon) yumRepolist() bool {
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o rootPrivAmazon) yumUpdateInfo() bool {
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o rootPrivAmazon) yumChangelog() bool {
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o rootPrivAmazon) yumMakeCache() bool {
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -59,11 +59,7 @@ func (o *centos) depsFastRoot() []string {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *centos) depsDeep() []string {
 | 
			
		||||
	return []string{
 | 
			
		||||
		"yum-utils",
 | 
			
		||||
		"yum-plugin-ps",
 | 
			
		||||
		"yum-plugin-changelog",
 | 
			
		||||
	}
 | 
			
		||||
	return o.depsFastRoot()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *centos) checkIfSudoNoPasswd() error {
 | 
			
		||||
@@ -107,18 +103,6 @@ func (o rootPrivCentos) repoquery() bool {
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o rootPrivCentos) yumRepolist() bool {
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o rootPrivCentos) yumUpdateInfo() bool {
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o rootPrivCentos) yumChangelog() bool {
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o rootPrivCentos) yumMakeCache() bool {
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -52,59 +52,11 @@ func (o *oracle) depsFast() []string {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *oracle) depsFastRoot() []string {
 | 
			
		||||
	if o.getServerInfo().Mode.IsOffline() {
 | 
			
		||||
		//TODO
 | 
			
		||||
		// return []string{"yum-plugin-ps"}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	majorVersion, _ := o.Distro.MajorVersion()
 | 
			
		||||
	switch majorVersion {
 | 
			
		||||
	case 5:
 | 
			
		||||
		return []string{
 | 
			
		||||
			"yum-utils",
 | 
			
		||||
			"yum-security",
 | 
			
		||||
		}
 | 
			
		||||
	case 6:
 | 
			
		||||
		return []string{
 | 
			
		||||
			"yum-utils",
 | 
			
		||||
			"yum-plugin-security",
 | 
			
		||||
			//TODO
 | 
			
		||||
			// return []string{"yum-plugin-ps"}
 | 
			
		||||
		}
 | 
			
		||||
	default:
 | 
			
		||||
		return []string{
 | 
			
		||||
			"yum-utils",
 | 
			
		||||
			//TODO
 | 
			
		||||
			// return []string{"yum-plugin-ps"}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return []string{"yum-utils"}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *oracle) depsDeep() []string {
 | 
			
		||||
	majorVersion, _ := o.Distro.MajorVersion()
 | 
			
		||||
	switch majorVersion {
 | 
			
		||||
	case 5:
 | 
			
		||||
		return []string{
 | 
			
		||||
			"yum-utils",
 | 
			
		||||
			"yum-security",
 | 
			
		||||
			"yum-changelog",
 | 
			
		||||
		}
 | 
			
		||||
	case 6:
 | 
			
		||||
		return []string{
 | 
			
		||||
			"yum-utils",
 | 
			
		||||
			"yum-plugin-security",
 | 
			
		||||
			"yum-plugin-changelog",
 | 
			
		||||
			//TODO
 | 
			
		||||
			// return []string{"yum-plugin-ps"}
 | 
			
		||||
		}
 | 
			
		||||
	default:
 | 
			
		||||
		return []string{
 | 
			
		||||
			"yum-utils",
 | 
			
		||||
			"yum-plugin-changelog",
 | 
			
		||||
			//TODO
 | 
			
		||||
			// return []string{"yum-plugin-ps"}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return o.depsFastRoot()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *oracle) checkIfSudoNoPasswd() error {
 | 
			
		||||
@@ -126,21 +78,7 @@ func (o *oracle) sudoNoPasswdCmdsFastRoot() []cmd {
 | 
			
		||||
	if o.getServerInfo().Mode.IsOffline() {
 | 
			
		||||
		return cmds
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	majorVersion, _ := o.Distro.MajorVersion()
 | 
			
		||||
	if majorVersion < 6 {
 | 
			
		||||
		return []cmd{
 | 
			
		||||
			{"yum repolist --color=never", exitStatusZero},
 | 
			
		||||
			{"yum list-security --security --color=never", exitStatusZero},
 | 
			
		||||
			{"yum info-security --color=never", exitStatusZero},
 | 
			
		||||
			{"repoquery -h", exitStatusZero},
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return append(cmds,
 | 
			
		||||
		cmd{"yum repolist --color=never", exitStatusZero},
 | 
			
		||||
		cmd{"yum updateinfo list updates --security --color=never", exitStatusZero},
 | 
			
		||||
		cmd{"yum updateinfo updates --security --color=never", exitStatusZero},
 | 
			
		||||
		cmd{"repoquery -h", exitStatusZero})
 | 
			
		||||
	return append(cmds, cmd{"repoquery -h", exitStatusZero})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *oracle) sudoNoPasswdCmdsDeep() []cmd {
 | 
			
		||||
@@ -153,19 +91,6 @@ func (o rootPrivOracle) repoquery() bool {
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o rootPrivOracle) yumRepolist() bool {
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o rootPrivOracle) yumUpdateInfo() bool {
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// root privilege isn't needed
 | 
			
		||||
func (o rootPrivOracle) yumChangelog() bool {
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o rootPrivOracle) yumMakeCache() bool {
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -22,7 +22,6 @@ import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"regexp"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/future-architect/vuls/config"
 | 
			
		||||
	"github.com/future-architect/vuls/models"
 | 
			
		||||
@@ -142,9 +141,6 @@ type redhatBase struct {
 | 
			
		||||
 | 
			
		||||
type rootPriv interface {
 | 
			
		||||
	repoquery() bool
 | 
			
		||||
	yumRepolist() bool
 | 
			
		||||
	yumUpdateInfo() bool
 | 
			
		||||
	yumChangelog() bool
 | 
			
		||||
	yumMakeCache() bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -237,12 +233,7 @@ func (o *redhatBase) scanPackages() error {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if o.getServerInfo().Mode.IsOffline() {
 | 
			
		||||
		switch o.Distro.Family {
 | 
			
		||||
		case config.Amazon:
 | 
			
		||||
			// nop
 | 
			
		||||
		default:
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
		return nil
 | 
			
		||||
	} else if o.Distro.Family == config.RedHat {
 | 
			
		||||
		if o.getServerInfo().Mode.IsFast() {
 | 
			
		||||
			return nil
 | 
			
		||||
@@ -259,13 +250,6 @@ func (o *redhatBase) scanPackages() error {
 | 
			
		||||
		installed.MergeNewVersion(updatable)
 | 
			
		||||
		o.Packages = installed
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var unsecures models.VulnInfos
 | 
			
		||||
	if unsecures, err = o.scanUnsecurePackages(updatable); err != nil {
 | 
			
		||||
		o.log.Errorf("Failed to scan vulnerable packages: %s", err)
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	o.VulnInfos = unsecures
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -457,24 +441,6 @@ func (o *redhatBase) isExecScanUsingYum() bool {
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *redhatBase) isExecFillChangelogs() bool {
 | 
			
		||||
	if o.getServerInfo().Mode.IsOffline() {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	// Amazon linux has no changelos for updates
 | 
			
		||||
	return o.getServerInfo().Mode.IsDeep() &&
 | 
			
		||||
		o.Distro.Family != config.Amazon
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *redhatBase) isExecScanChangelogs() bool {
 | 
			
		||||
	if o.getServerInfo().Mode.IsOffline() ||
 | 
			
		||||
		o.getServerInfo().Mode.IsFast() ||
 | 
			
		||||
		o.getServerInfo().Mode.IsFastRoot() {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *redhatBase) isExecYumPS() bool {
 | 
			
		||||
	// RedHat has no yum-ps
 | 
			
		||||
	switch o.Distro.Family {
 | 
			
		||||
@@ -526,658 +492,6 @@ func (o *redhatBase) isExecNeedsRestarting() bool {
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *redhatBase) scanUnsecurePackages(updatable models.Packages) (models.VulnInfos, error) {
 | 
			
		||||
	if o.isExecFillChangelogs() {
 | 
			
		||||
		if err := o.fillChangelogs(updatable); err != nil {
 | 
			
		||||
			err = xerrors.Errorf("Failed to fetch changelogs: %w", err)
 | 
			
		||||
			o.log.Warnf("err: %+v", err)
 | 
			
		||||
			o.warns = append(o.warns, err)
 | 
			
		||||
			// Only warning this error
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if o.isExecScanUsingYum() {
 | 
			
		||||
		return o.scanUsingYum(updatable)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Parse changelog because CentOS does not have security channel...
 | 
			
		||||
	if o.isExecScanChangelogs() {
 | 
			
		||||
		return o.scanChangelogs(updatable)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return models.VulnInfos{}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *redhatBase) 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 _, name := range names {
 | 
			
		||||
		if o.Packages[name].Changelog.Contents == "" {
 | 
			
		||||
			emptyChangelogPackNames = append(emptyChangelogPackNames, name)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *redhatBase) getAvailableChangelogs(packNames []string) (map[string]string, error) {
 | 
			
		||||
	yumopts := ""
 | 
			
		||||
	if 0 < len(o.getServerInfo().Enablerepo) {
 | 
			
		||||
		yumopts = " --enablerepo=" + strings.Join(o.getServerInfo().Enablerepo, ",")
 | 
			
		||||
	}
 | 
			
		||||
	if config.Conf.SkipBroken {
 | 
			
		||||
		yumopts += " --skip-broken"
 | 
			
		||||
	}
 | 
			
		||||
	if o.hasYumColorOption() {
 | 
			
		||||
		yumopts += " --color=never"
 | 
			
		||||
	}
 | 
			
		||||
	cmd := `yum changelog all updates %s %s | grep -A 1000000 "==================== Updated Packages ===================="`
 | 
			
		||||
	cmd = fmt.Sprintf(cmd, yumopts, strings.Join(packNames, " "))
 | 
			
		||||
 | 
			
		||||
	r := o.exec(util.PrependProxyEnv(cmd), o.sudo.yumChangelog())
 | 
			
		||||
	if !r.isSuccess(0, 1) {
 | 
			
		||||
		return nil, xerrors.Errorf("Failed to SSH: %s", r)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return o.divideChangelogsIntoEachPackages(r.Stdout), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Divide available change logs of all updatable packages into each package's changelog
 | 
			
		||||
func (o *redhatBase) 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, "==================== Updated Packages ====================") {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		if len(strings.TrimSpace(line)) != 0 && 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 *redhatBase) 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 {
 | 
			
		||||
			var detectionMethod string
 | 
			
		||||
			diff, err := o.getDiffChangelog(pack, changelogs[s])
 | 
			
		||||
			if err == nil {
 | 
			
		||||
				detectionMethod = models.ChangelogExactMatchStr
 | 
			
		||||
			} else {
 | 
			
		||||
				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)
 | 
			
		||||
						if len(diff) == 0 {
 | 
			
		||||
							detectionMethod = models.FailedToGetChangelog
 | 
			
		||||
						} else {
 | 
			
		||||
							detectionMethod = models.FailedToFindVersionInChangelog
 | 
			
		||||
							diff = ""
 | 
			
		||||
						}
 | 
			
		||||
					} else {
 | 
			
		||||
						o.log.Debugf("Found the version in changelog without epoch: %s-%s-%s",
 | 
			
		||||
							pack.Name, pack.Version, pack.Release)
 | 
			
		||||
						detectionMethod = models.ChangelogLenientMatchStr
 | 
			
		||||
					}
 | 
			
		||||
				} else {
 | 
			
		||||
					if len(diff) == 0 {
 | 
			
		||||
						detectionMethod = models.FailedToGetChangelog
 | 
			
		||||
					} else {
 | 
			
		||||
						detectionMethod = models.FailedToFindVersionInChangelog
 | 
			
		||||
						diff = ""
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			pack = o.Packages[name]
 | 
			
		||||
			pack.Changelog = models.Changelog{
 | 
			
		||||
				Contents: diff,
 | 
			
		||||
				Method:   models.DetectionMethod(detectionMethod),
 | 
			
		||||
			}
 | 
			
		||||
			o.Packages[name] = pack
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *redhatBase) 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, "]")
 | 
			
		||||
 | 
			
		||||
		// On Amazon often end with email address. <aaa@aaa.com> Go to next line
 | 
			
		||||
		if strings.HasPrefix(v, "<") && strings.HasSuffix(v, ">") {
 | 
			
		||||
			diff = append(diff, line)
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		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,
 | 
			
		||||
			xerrors.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 *redhatBase) scanChangelogs(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.AffectedPackages = append(v.AffectedPackages, models.PackageFixStatus{Name: name})
 | 
			
		||||
				vinfos[cid] = v
 | 
			
		||||
			} else {
 | 
			
		||||
				vinfos[cid] = models.VulnInfo{
 | 
			
		||||
					CveID:            cid,
 | 
			
		||||
					AffectedPackages: models.PackageFixStatuses{{Name: name}},
 | 
			
		||||
					Confidences:      models.Confidences{models.ChangelogExactMatch},
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return vinfos, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type distroAdvisoryCveIDs struct {
 | 
			
		||||
	DistroAdvisory models.DistroAdvisory
 | 
			
		||||
	CveIDs         []string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Scaning unsecure packages using yum-plugin-security.
 | 
			
		||||
// Amazon, RHEL, Oracle Linux
 | 
			
		||||
func (o *redhatBase) scanUsingYum(updatable models.Packages) (models.VulnInfos, error) {
 | 
			
		||||
	if o.Distro.Family == config.CentOS {
 | 
			
		||||
		// CentOS has no security channel.
 | 
			
		||||
		return nil, xerrors.New(
 | 
			
		||||
			"yum updateinfo is not suppported on CentOS")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// get advisoryID(RHSA, ALAS, ELSA) - package name,version
 | 
			
		||||
	major, err := (o.Distro.MajorVersion())
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, xerrors.Errorf("Not implemented yet: %s, err: %w", o.Distro, err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var cmd string
 | 
			
		||||
	if (o.Distro.Family == config.RedHat || o.Distro.Family == config.Oracle) && major > 5 {
 | 
			
		||||
		cmd = "yum repolist --color=never"
 | 
			
		||||
		r := o.exec(util.PrependProxyEnv(cmd), o.sudo.yumRepolist())
 | 
			
		||||
		if !r.isSuccess() {
 | 
			
		||||
			return nil, xerrors.Errorf("Failed to SSH: %s", r)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (o.Distro.Family == config.RedHat || o.Distro.Family == config.Oracle) && major == 5 {
 | 
			
		||||
		cmd = "yum list-security --security"
 | 
			
		||||
		if o.hasYumColorOption() {
 | 
			
		||||
			cmd += " --color=never"
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		cmd = "yum updateinfo list updates --security --color=never"
 | 
			
		||||
	}
 | 
			
		||||
	r := o.exec(util.PrependProxyEnv(cmd), o.sudo.yumUpdateInfo())
 | 
			
		||||
	if !r.isSuccess() {
 | 
			
		||||
		return nil, xerrors.Errorf("Failed to SSH: %s", r)
 | 
			
		||||
	}
 | 
			
		||||
	advIDPackNamesList, err := o.parseYumUpdateinfoListAvailable(r.Stdout)
 | 
			
		||||
 | 
			
		||||
	dict := make(map[string]models.Packages)
 | 
			
		||||
	for _, advIDPackNames := range advIDPackNamesList {
 | 
			
		||||
		packages := models.Packages{}
 | 
			
		||||
		for _, packName := range advIDPackNames.PackNames {
 | 
			
		||||
			pack, found := updatable[packName]
 | 
			
		||||
			if !found {
 | 
			
		||||
				return nil, xerrors.Errorf(
 | 
			
		||||
					"Package not found. pack: %#v", packName)
 | 
			
		||||
			}
 | 
			
		||||
			packages[pack.Name] = pack
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		dict[advIDPackNames.AdvisoryID] = packages
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// get advisoryID(RHSA, ALAS, ELSA) - CVE IDs
 | 
			
		||||
	if (o.Distro.Family == config.RedHat || o.Distro.Family == config.Oracle) && major == 5 {
 | 
			
		||||
		cmd = "yum info-security"
 | 
			
		||||
		if o.hasYumColorOption() {
 | 
			
		||||
			cmd += " --color=never"
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		cmd = "yum updateinfo updates --security --color=never"
 | 
			
		||||
	}
 | 
			
		||||
	r = o.exec(util.PrependProxyEnv(cmd), o.sudo.yumUpdateInfo())
 | 
			
		||||
	if !r.isSuccess() {
 | 
			
		||||
		return nil, xerrors.Errorf("Failed to SSH: %s", r)
 | 
			
		||||
	}
 | 
			
		||||
	advisoryCveIDsList, err := o.parseYumUpdateinfo(r.Stdout)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// All information collected.
 | 
			
		||||
	// Convert to VulnInfos.
 | 
			
		||||
	vinfos := models.VulnInfos{}
 | 
			
		||||
	for _, advIDCveIDs := range advisoryCveIDsList {
 | 
			
		||||
		for _, cveID := range advIDCveIDs.CveIDs {
 | 
			
		||||
			vinfo, found := vinfos[cveID]
 | 
			
		||||
			if found {
 | 
			
		||||
				advAppended := append(vinfo.DistroAdvisories, advIDCveIDs.DistroAdvisory)
 | 
			
		||||
				vinfo.DistroAdvisories = advAppended
 | 
			
		||||
 | 
			
		||||
				packs := dict[advIDCveIDs.DistroAdvisory.AdvisoryID]
 | 
			
		||||
				for _, pack := range packs {
 | 
			
		||||
					vinfo.AffectedPackages = append(vinfo.AffectedPackages,
 | 
			
		||||
						models.PackageFixStatus{Name: pack.Name})
 | 
			
		||||
				}
 | 
			
		||||
			} else {
 | 
			
		||||
				packs := dict[advIDCveIDs.DistroAdvisory.AdvisoryID]
 | 
			
		||||
				affected := models.PackageFixStatuses{}
 | 
			
		||||
				for _, p := range packs {
 | 
			
		||||
					affected = append(affected, models.PackageFixStatus{Name: p.Name})
 | 
			
		||||
				}
 | 
			
		||||
				vinfo = models.VulnInfo{
 | 
			
		||||
					CveID:            cveID,
 | 
			
		||||
					DistroAdvisories: []models.DistroAdvisory{advIDCveIDs.DistroAdvisory},
 | 
			
		||||
					AffectedPackages: affected,
 | 
			
		||||
					Confidences:      models.Confidences{models.YumUpdateSecurityMatch},
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			vinfos[cveID] = vinfo
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return vinfos, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var horizontalRulePattern = regexp.MustCompile(`^=+$`)
 | 
			
		||||
 | 
			
		||||
func (o *redhatBase) parseYumUpdateinfo(stdout string) (result []distroAdvisoryCveIDs, err error) {
 | 
			
		||||
	sectionState := Outside
 | 
			
		||||
	lines := strings.Split(stdout, "\n")
 | 
			
		||||
	lines = append(lines, "=============")
 | 
			
		||||
 | 
			
		||||
	// Amazon Linux AMI Security Information
 | 
			
		||||
	advisory := models.DistroAdvisory{}
 | 
			
		||||
 | 
			
		||||
	cveIDsSetInThisSection := make(map[string]bool)
 | 
			
		||||
 | 
			
		||||
	// use this flag to Collect CVE IDs in CVEs field.
 | 
			
		||||
	inDesctiption, inCves := false, false
 | 
			
		||||
 | 
			
		||||
	for _, line := range lines {
 | 
			
		||||
		line = strings.TrimSpace(line)
 | 
			
		||||
 | 
			
		||||
		// find the new section pattern
 | 
			
		||||
		if horizontalRulePattern.MatchString(line) {
 | 
			
		||||
			// set previous section's result to return-variable
 | 
			
		||||
			if sectionState == Content {
 | 
			
		||||
				foundCveIDs := []string{}
 | 
			
		||||
				for cveID := range cveIDsSetInThisSection {
 | 
			
		||||
					foundCveIDs = append(foundCveIDs, cveID)
 | 
			
		||||
				}
 | 
			
		||||
				result = append(result, distroAdvisoryCveIDs{
 | 
			
		||||
					DistroAdvisory: advisory,
 | 
			
		||||
					CveIDs:         foundCveIDs,
 | 
			
		||||
				})
 | 
			
		||||
 | 
			
		||||
				// reset for next section.
 | 
			
		||||
				cveIDsSetInThisSection = make(map[string]bool)
 | 
			
		||||
				inDesctiption, inCves = false, false
 | 
			
		||||
				advisory = models.DistroAdvisory{}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// Go to next section
 | 
			
		||||
			sectionState = o.changeSectionState(sectionState)
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		switch sectionState {
 | 
			
		||||
		case Header:
 | 
			
		||||
			switch o.Distro.Family {
 | 
			
		||||
			case config.CentOS:
 | 
			
		||||
				// CentOS has no security channel.
 | 
			
		||||
				return result, xerrors.New(
 | 
			
		||||
					"yum updateinfo is not suppported on CentOS")
 | 
			
		||||
			case config.RedHat, config.Amazon, config.Oracle:
 | 
			
		||||
				// nop
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		case Content:
 | 
			
		||||
			if found := o.isDescriptionLine(line); found {
 | 
			
		||||
				inDesctiption, inCves = true, false
 | 
			
		||||
				ss := strings.Split(line, " : ")
 | 
			
		||||
				advisory.Description += fmt.Sprintf("%s\n",
 | 
			
		||||
					strings.Join(ss[1:], " : "))
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// severity
 | 
			
		||||
			if severity, found := o.parseYumUpdateinfoToGetSeverity(line); found {
 | 
			
		||||
				advisory.Severity = severity
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// No need to parse in description except severity
 | 
			
		||||
			if inDesctiption {
 | 
			
		||||
				if ss := strings.Split(line, ": "); 1 < len(ss) {
 | 
			
		||||
					advisory.Description += fmt.Sprintf("%s\n",
 | 
			
		||||
						strings.Join(ss[1:], ": "))
 | 
			
		||||
				}
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if found := o.isCvesHeaderLine(line); found {
 | 
			
		||||
				inCves = true
 | 
			
		||||
				ss := strings.Split(line, "CVEs : ")
 | 
			
		||||
				line = strings.Join(ss[1:], " ")
 | 
			
		||||
				cveIDs := o.parseYumUpdateinfoLineToGetCveIDs(line)
 | 
			
		||||
				for _, cveID := range cveIDs {
 | 
			
		||||
					cveIDsSetInThisSection[cveID] = true
 | 
			
		||||
				}
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if inCves {
 | 
			
		||||
				cveIDs := o.parseYumUpdateinfoLineToGetCveIDs(line)
 | 
			
		||||
				for _, cveID := range cveIDs {
 | 
			
		||||
					cveIDsSetInThisSection[cveID] = true
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			advisoryID, found := o.parseYumUpdateinfoToGetAdvisoryID(line)
 | 
			
		||||
			if found {
 | 
			
		||||
				advisory.AdvisoryID = advisoryID
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			issued, found := o.parseYumUpdateinfoLineToGetIssued(line)
 | 
			
		||||
			if found {
 | 
			
		||||
				advisory.Issued = issued
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			updated, found := o.parseYumUpdateinfoLineToGetUpdated(line)
 | 
			
		||||
			if found {
 | 
			
		||||
				advisory.Updated = updated
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// state
 | 
			
		||||
const (
 | 
			
		||||
	Outside = iota
 | 
			
		||||
	Header  = iota
 | 
			
		||||
	Content = iota
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func (o *redhatBase) changeSectionState(state int) (newState int) {
 | 
			
		||||
	switch state {
 | 
			
		||||
	case Outside, Content:
 | 
			
		||||
		newState = Header
 | 
			
		||||
	case Header:
 | 
			
		||||
		newState = Content
 | 
			
		||||
	}
 | 
			
		||||
	return newState
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *redhatBase) isCvesHeaderLine(line string) bool {
 | 
			
		||||
	return strings.Contains(line, "CVEs : ")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var yumCveIDPattern = regexp.MustCompile(`(CVE-\d{4}-\d{4,})`)
 | 
			
		||||
 | 
			
		||||
func (o *redhatBase) parseYumUpdateinfoLineToGetCveIDs(line string) []string {
 | 
			
		||||
	return yumCveIDPattern.FindAllString(line, -1)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var yumAdvisoryIDPattern = regexp.MustCompile(`^ *Update ID : (.*)$`)
 | 
			
		||||
 | 
			
		||||
func (o *redhatBase) parseYumUpdateinfoToGetAdvisoryID(line string) (advisoryID string, found bool) {
 | 
			
		||||
	result := yumAdvisoryIDPattern.FindStringSubmatch(line)
 | 
			
		||||
	if len(result) != 2 {
 | 
			
		||||
		return "", false
 | 
			
		||||
	}
 | 
			
		||||
	return strings.TrimSpace(result[1]), true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var yumIssuedPattern = regexp.MustCompile(`^\s*Issued : (\d{4}-\d{2}-\d{2})`)
 | 
			
		||||
 | 
			
		||||
func (o *redhatBase) parseYumUpdateinfoLineToGetIssued(line string) (date time.Time, found bool) {
 | 
			
		||||
	return o.parseYumUpdateinfoLineToGetDate(line, yumIssuedPattern)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var yumUpdatedPattern = regexp.MustCompile(`^\s*Updated : (\d{4}-\d{2}-\d{2})`)
 | 
			
		||||
 | 
			
		||||
func (o *redhatBase) parseYumUpdateinfoLineToGetUpdated(line string) (date time.Time, found bool) {
 | 
			
		||||
	return o.parseYumUpdateinfoLineToGetDate(line, yumUpdatedPattern)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *redhatBase) parseYumUpdateinfoLineToGetDate(line string, regexpPattern *regexp.Regexp) (date time.Time, found bool) {
 | 
			
		||||
	result := regexpPattern.FindStringSubmatch(line)
 | 
			
		||||
	if len(result) != 2 {
 | 
			
		||||
		return date, false
 | 
			
		||||
	}
 | 
			
		||||
	t, err := time.Parse("2006-01-02", result[1])
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return date, false
 | 
			
		||||
	}
 | 
			
		||||
	return t, true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var yumDescriptionPattern = regexp.MustCompile(`^\s*Description : `)
 | 
			
		||||
 | 
			
		||||
func (o *redhatBase) isDescriptionLine(line string) bool {
 | 
			
		||||
	return yumDescriptionPattern.MatchString(line)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var yumSeverityPattern = regexp.MustCompile(`^ *Severity : (.*)$`)
 | 
			
		||||
 | 
			
		||||
func (o *redhatBase) parseYumUpdateinfoToGetSeverity(line string) (severity string, found bool) {
 | 
			
		||||
	result := yumSeverityPattern.FindStringSubmatch(line)
 | 
			
		||||
	if len(result) != 2 {
 | 
			
		||||
		return "", false
 | 
			
		||||
	}
 | 
			
		||||
	return strings.TrimSpace(result[1]), true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type advisoryIDPacks struct {
 | 
			
		||||
	AdvisoryID string
 | 
			
		||||
	PackNames  []string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type advisoryIDPacksList []advisoryIDPacks
 | 
			
		||||
 | 
			
		||||
func (list advisoryIDPacksList) find(advisoryID string) (advisoryIDPacks, bool) {
 | 
			
		||||
	for _, a := range list {
 | 
			
		||||
		if a.AdvisoryID == advisoryID {
 | 
			
		||||
			return a, true
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return advisoryIDPacks{}, false
 | 
			
		||||
}
 | 
			
		||||
func (o *redhatBase) extractPackNameVerRel(nameVerRel string) (name, ver, rel string) {
 | 
			
		||||
	fields := strings.Split(nameVerRel, ".")
 | 
			
		||||
	archTrimed := strings.Join(fields[0:len(fields)-1], ".")
 | 
			
		||||
 | 
			
		||||
	fields = strings.Split(archTrimed, "-")
 | 
			
		||||
	rel = fields[len(fields)-1]
 | 
			
		||||
	ver = fields[len(fields)-2]
 | 
			
		||||
	name = strings.Join(fields[0:(len(fields)-2)], "-")
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// parseYumUpdateinfoListAvailable collect AdvisorID(RHSA, ALAS, ELSA), packages
 | 
			
		||||
func (o *redhatBase) parseYumUpdateinfoListAvailable(stdout string) (advisoryIDPacksList, error) {
 | 
			
		||||
	result := []advisoryIDPacks{}
 | 
			
		||||
	lines := strings.Split(stdout, "\n")
 | 
			
		||||
	for _, line := range lines {
 | 
			
		||||
 | 
			
		||||
		if !(strings.HasPrefix(line, "RHSA") ||
 | 
			
		||||
			strings.HasPrefix(line, "ALAS") ||
 | 
			
		||||
			strings.HasPrefix(line, "ELSA")) {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		fields := strings.Fields(line)
 | 
			
		||||
		if len(fields) != 3 {
 | 
			
		||||
			return []advisoryIDPacks{}, xerrors.Errorf(
 | 
			
		||||
				"Unknown format. line: %s", line)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// extract fields
 | 
			
		||||
		advisoryID := fields[0]
 | 
			
		||||
		packVersion := fields[2]
 | 
			
		||||
		packName, _, _ := o.extractPackNameVerRel(packVersion)
 | 
			
		||||
 | 
			
		||||
		found := false
 | 
			
		||||
		for i, s := range result {
 | 
			
		||||
			if s.AdvisoryID == advisoryID {
 | 
			
		||||
				names := s.PackNames
 | 
			
		||||
				names = append(names, packName)
 | 
			
		||||
				result[i].PackNames = names
 | 
			
		||||
				found = true
 | 
			
		||||
				break
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if !found {
 | 
			
		||||
			result = append(result, advisoryIDPacks{
 | 
			
		||||
				AdvisoryID: advisoryID,
 | 
			
		||||
				PackNames:  []string{packName},
 | 
			
		||||
			})
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return result, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *redhatBase) yumPS() error {
 | 
			
		||||
	cmd := "LANGUAGE=en_US.UTF-8 yum info yum"
 | 
			
		||||
	r := o.exec(util.PrependProxyEnv(cmd), noSudo)
 | 
			
		||||
 
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										62
									
								
								scan/rhel.go
									
									
									
									
									
								
							
							
						
						
									
										62
									
								
								scan/rhel.go
									
									
									
									
									
								
							@@ -53,47 +53,11 @@ func (o *rhel) depsFastRoot() []string {
 | 
			
		||||
	if o.getServerInfo().Mode.IsOffline() {
 | 
			
		||||
		return []string{}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	majorVersion, _ := o.Distro.MajorVersion()
 | 
			
		||||
	switch majorVersion {
 | 
			
		||||
	case 5:
 | 
			
		||||
		return []string{
 | 
			
		||||
			"yum-utils",
 | 
			
		||||
			"yum-security",
 | 
			
		||||
		}
 | 
			
		||||
	case 6:
 | 
			
		||||
		return []string{
 | 
			
		||||
			"yum-utils",
 | 
			
		||||
			"yum-plugin-security",
 | 
			
		||||
		}
 | 
			
		||||
	default:
 | 
			
		||||
		return []string{
 | 
			
		||||
			"yum-utils",
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return []string{"yum-utils"}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *rhel) depsDeep() []string {
 | 
			
		||||
	majorVersion, _ := o.Distro.MajorVersion()
 | 
			
		||||
	switch majorVersion {
 | 
			
		||||
	case 5:
 | 
			
		||||
		return []string{
 | 
			
		||||
			"yum-utils",
 | 
			
		||||
			"yum-security",
 | 
			
		||||
			"yum-changelog",
 | 
			
		||||
		}
 | 
			
		||||
	case 6:
 | 
			
		||||
		return []string{
 | 
			
		||||
			"yum-utils",
 | 
			
		||||
			"yum-plugin-security",
 | 
			
		||||
			"yum-plugin-changelog",
 | 
			
		||||
		}
 | 
			
		||||
	default:
 | 
			
		||||
		return []string{
 | 
			
		||||
			"yum-utils",
 | 
			
		||||
			"yum-plugin-changelog",
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return o.depsFastRoot()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *rhel) checkIfSudoNoPasswd() error {
 | 
			
		||||
@@ -118,25 +82,17 @@ func (o *rhel) sudoNoPasswdCmdsFastRoot() []cmd {
 | 
			
		||||
	majorVersion, _ := o.Distro.MajorVersion()
 | 
			
		||||
	if majorVersion < 6 {
 | 
			
		||||
		return []cmd{
 | 
			
		||||
			// {"needs-restarting", exitStatusZero},
 | 
			
		||||
			{"yum repolist --color=never", exitStatusZero},
 | 
			
		||||
			{"yum list-security --security --color=never", exitStatusZero},
 | 
			
		||||
			{"yum info-security --color=never", exitStatusZero},
 | 
			
		||||
			{"repoquery -h", exitStatusZero},
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return []cmd{
 | 
			
		||||
		{"yum repolist --color=never", exitStatusZero},
 | 
			
		||||
		{"yum updateinfo list updates --security --color=never", exitStatusZero},
 | 
			
		||||
		{"yum updateinfo updates --security --color=never ", exitStatusZero},
 | 
			
		||||
		{"repoquery -h", exitStatusZero},
 | 
			
		||||
		{"needs-restarting", exitStatusZero},
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o *rhel) sudoNoPasswdCmdsDeep() []cmd {
 | 
			
		||||
	return append(o.sudoNoPasswdCmdsFastRoot(),
 | 
			
		||||
		cmd{"yum changelog all updates --color=never", exitStatusZero})
 | 
			
		||||
	return o.sudoNoPasswdCmdsFastRoot()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type rootPrivRHEL struct{}
 | 
			
		||||
@@ -145,18 +101,6 @@ func (o rootPrivRHEL) repoquery() bool {
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o rootPrivRHEL) yumRepolist() bool {
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o rootPrivRHEL) yumUpdateInfo() bool {
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o rootPrivRHEL) yumChangelog() bool {
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (o rootPrivRHEL) yumMakeCache() bool {
 | 
			
		||||
	return true
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user