root/releases/pkgcore-checks/0.3.5/pkgcore_checks/glsa_scan.py @ ferringb%2540gmail.com-20070207174621-yb3eqrqc6jtmdgse

Revision ferringb%2540gmail.com-20070207174621-yb3eqrqc6jtmdgse, 4.6 KB (checked in by Brian Harring <ferringb@…>, 2 years ago)

kill off to_str, no longer used; use short_desc and long_desc properties instead

Line 
1# Copyright: 2006 Brian Harring <ferringb@gmail.com>
2# License: GPL2
3
4import os, optparse
5
6from pkgcore_checks import base
7from pkgcore.util.demandload import demandload
8demandload(globals(), "pkgcore.pkgsets.glsa:GlsaDirSet "
9    "pkgcore.restrictions:packages,values "
10    "pkgcore.util:xml,osutils "
11    "pkgcore.restrictions.util:collect_package_restrictions "
12    "warnings ")
13
14
15class VulnerablePackage(base.Result):
16
17    """Packages marked as vulnerable by GLSAs"""
18
19    __slots__ = ("category", "package", "version", "arch", "glsa")
20    threshold = base.versioned_feed
21
22    def __init__(self, pkg, glsa):
23        base.Result.__init__(self)
24        self._store_cpv(pkg)
25        arches = set()
26        for v in collect_package_restrictions(glsa, ["keywords"]):
27            if isinstance(v.restriction, values.ContainmentMatch):
28                arches.update(x.lstrip("~") for x in v.restriction.vals)
29            else:
30                raise Exception("unexpected restriction sequence- %s in %s" %
31                    (v.restriction, glsa))
32        keys = set(x.lstrip("~") for x in pkg.keywords if not x.startswith("-"))
33        if arches:
34            self.arch = tuple(sorted(arches.intersection(keys)))
35            assert self.arch
36        else:
37            self.arch = tuple(sorted(keys))
38        self.glsa = str(glsa)
39   
40    @property
41    def short_desc(self):
42        return "vulnerable via %s, keywords %s" % (self.glsa, self.arch)
43
44
45class TreeVulnerabilitiesReport(base.Template):
46    """
47    Scan for vulnerabile ebuilds in the tree
48   
49    requires a GLSA directory for vuln. info
50    """
51
52    feed_type = base.versioned_feed
53    known_results = (VulnerablePackage,)
54
55    @staticmethod
56    def mangle_option_parser(parser):
57        parser.add_option(
58            "--glsa-dir", action='store', type='string', dest='glsa_location',
59            help="source directoy for glsas; tries to autodetermine it, may "
60            "be required if no glsa dirs are known")
61
62    @staticmethod
63    def check_values(values):
64        values.glsa_enabled = True
65        glsa_loc = values.glsa_location
66        if glsa_loc is not None:
67            if not os.path.isdir(glsa_loc):
68                raise optparse.OptionValueError("--glsa-dir '%r' doesn't "
69                    "exist" % glsa_loc)
70        else:
71            if not values.repo_bases:
72                raise optparse.OptionValueError(
73                    'Need a target repo or --overlayed-repo that is a single '
74                    'UnconfiguredTree for license checks')
75            for repo_base in values.repo_bases:
76                candidate = os.path.join(repo_base, "metadata", "glsa")
77                if os.path.isdir(candidate):
78                    if glsa_loc is None:
79                        glsa_loc = candidate
80                    else:
81                        raise optparse.OptionValueError(
82                            'multiple glsa sources is unsupported (detected '
83                            '%s and %s). Pick one with --glsa-dir.' % (
84                                glsa_loc, candidate))
85            if glsa_loc is None:
86                # form of 'optional' limiting; if they are using -c, force the
87                # error, else disable
88                if values.checks_to_run:
89                    raise optparse.OptionValueError("--glsa-dir must be "
90                        "specified, couldn't identify glsa src from %r" %
91                            values.src_repo)
92                values.glsa_enabled = False
93                warnings.warn("disabling GLSA checks due to no glsa source "
94                    "being found, and the check not being explicitly enabled; "
95                    "this behaviour may change")
96                return
97
98        values.glsa_location = osutils.abspath(glsa_loc)
99
100    def __init__(self, options):
101        base.Template.__init__(self, options)
102        self.options = options
103        self.glsa_dir = options.glsa_location
104        self.enabled = False
105        self.vulns = {}
106
107    def start(self):
108        if not self.options.glsa_enabled:
109            return
110        # this is a bit brittle
111        for r in GlsaDirSet(self.glsa_dir):
112            if len(r) > 2:
113                self.vulns.setdefault(r[0].key,
114                    []).append(packages.AndRestriction(*r[1:]))
115            else:
116                self.vulns.setdefault(r[0].key, []).append(r[1])
117
118    def finish(self, reporter):
119        self.vulns.clear()
120
121    def feed(self, pkg, reporter):
122        if not self.options.glsa_enabled:
123            return
124        for vuln in self.vulns.get(pkg.key, []):
125            if vuln.match(pkg):
126                reporter.add_report(VulnerablePackage(pkg, vuln))
Note: See TracBrowser for help on using the browser.