aboutsummaryrefslogtreecommitdiff
blob: 5e8bc89e30688a37df235ed7fb9595c0cab794f6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# Copyright 2007-2020 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2

import portage.glsa as glsa
from portage._sets.base import PackageSet
from portage.versions import vercmp
from portage._sets import get_boolean

__all__ = ["SecuritySet", "NewGlsaSet", "NewAffectedSet", "AffectedSet"]


class SecuritySet(PackageSet):
    _operations = ["merge"]
    _skip_applied = False

    description = "package set that includes all packages possibly affected by a GLSA"

    def __init__(self, settings, vardbapi, portdbapi, least_change=True):
        super(SecuritySet, self).__init__()
        self._settings = settings
        self._vardbapi = vardbapi
        self._portdbapi = portdbapi
        self._least_change = least_change

    def getGlsaList(self, skip_applied):
        glsaindexlist = glsa.get_glsa_list(self._settings)
        if skip_applied:
            applied_list = glsa.get_applied_glsas(self._settings)
            glsaindexlist = set(glsaindexlist).difference(applied_list)
            glsaindexlist = list(glsaindexlist)
        glsaindexlist.sort()
        return glsaindexlist

    def load(self):
        glsaindexlist = self.getGlsaList(self._skip_applied)
        atomlist = []
        for glsaid in glsaindexlist:
            myglsa = glsa.Glsa(glsaid, self._settings, self._vardbapi, self._portdbapi)
            # print glsaid, myglsa.isVulnerable(), myglsa.isApplied(), myglsa.getMergeList()
            if self.useGlsa(myglsa):
                atomlist += [
                    "=" + x
                    for x in myglsa.getMergeList(least_change=self._least_change)
                ]
        self._setAtoms(self._reduce(atomlist))

    def _reduce(self, atomlist):
        mydict = {}
        for atom in atomlist[:]:
            cpv = self._portdbapi.xmatch("match-all", atom)[0]
            pkg = self._portdbapi._pkg_str(cpv, None)
            cps = "%s:%s" % (pkg.cp, pkg.slot)
            if not cps in mydict:
                mydict[cps] = (atom, cpv)
            else:
                other_cpv = mydict[cps][1]
                if vercmp(cpv.version, other_cpv.version) > 0:
                    atomlist.remove(mydict[cps][0])
                    mydict[cps] = (atom, cpv)
        return atomlist

    def useGlsa(self, myglsa):
        return True

    def updateAppliedList(self):
        glsaindexlist = self.getGlsaList(True)
        applied_list = glsa.get_applied_glsas(self._settings)
        for glsaid in glsaindexlist:
            myglsa = glsa.Glsa(glsaid, self._settings, self._vardbapi, self._portdbapi)
            if not myglsa.isVulnerable() and not myglsa.nr in applied_list:
                myglsa.inject()

    def singleBuilder(cls, options, settings, trees):
        least_change = not get_boolean(options, "use_emerge_resolver", False)
        return cls(
            settings,
            trees["vartree"].dbapi,
            trees["porttree"].dbapi,
            least_change=least_change,
        )

    singleBuilder = classmethod(singleBuilder)


class NewGlsaSet(SecuritySet):
    _skip_applied = True
    description = (
        "Package set that includes all packages possibly affected by an unapplied GLSA"
    )


class AffectedSet(SecuritySet):
    description = "Package set that includes all packages affected by an unapplied GLSA"

    def useGlsa(self, myglsa):
        return myglsa.isVulnerable()


class NewAffectedSet(AffectedSet):
    _skip_applied = True
    description = "Package set that includes all packages affected by an unapplied GLSA"