~ubuntu-security/ubuntu-cve-tracker/master

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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#!/usr/bin/env python

# Author: Kees Cook <kees@ubuntu.com>
# Copyright (C) 2009 Canonical Ltd.
#
# This script is distributed under the terms and conditions of the GNU General
# Public License, Version 3 or later. See http://www.gnu.org/copyleft/gpl.html
# for details.
#
# Reports the packages fixed for a given release, along with their CVEs.
#
# ./scripts/report-packages.py hardy
#
# export REL="hardy"; export NAMED=10; (./scripts/report-packages.py --action plot $REL | sort -n -k 8 | awk '{print $1 " " $8}' | tail -n $NAMED; echo -n "others "; ./scripts/report-packages.py --action plot $REL | sort -n -k 8 | head -n -$NAMED | awk '{ sum+=$8 }END{print sum}') | ./scripts/pie-chart.py ; scp pie.png vinyl:outflux.net/html/

import os
import re
import sys
import optparse
import cve_lib, usn_lib

import source_map
source_map = source_map.load()
releases = cve_lib.releases
config = cve_lib.read_config()

parser = optparse.OptionParser()
parser.add_option("-S", "--skip-devel", help="Show only those CVEs *not* in the current devel release", action="store_true")
parser.add_option("-D", "--only-devel", help="Show only those CVEs in the current devel release", action="store_true")
parser.add_option("--db", help="Specify the USN database to load", metavar="FILENAME", default=config['usn_db_copy'])
parser.add_option("-d", "--debug", help="Report debug information while loading", action="store_true")
parser.add_option("--priority", help="Report only CVEs with a matching priority", action="store", metavar="PRIORITY")
parser.add_option("--action", help="Change report style ('list'(default), 'plot'", action="store", metavar="ACTION", default='list')
(opt, args) = parser.parse_args()

if not os.path.exists(opt.db):
    print >>sys.stderr, "Cannot read %s" % (opt.db)
    sys.exit(1)
db = usn_lib.load_database(opt.db)

releases = cve_lib.releases
for eol in cve_lib.eol_releases:
    if eol in releases:
        releases.remove(eol)
if opt.skip_devel and len(cve_lib.devel_release)>0:
    releases.remove(cve_lib.devel_release)

if opt.only_devel:
    releases = [cve_lib.devel_release]

# Global CVE info cache
info = dict()

release = None
if len(args)>0:
    release = args[0]
if release and release not in releases:
    raise ValueError, "'%s' must be one of '%s'" % (release, "', '".join(releases))

def fixed_map(priority=None):
    fixed = dict()
    for usn in sorted(db.keys()):
        if not db[usn].has_key('cves'):
            continue
        for cve in db[usn]['cves']:
            if not cve.startswith('CVE-'):
                continue

            if not release or db[usn]['releases'].has_key(release):
                # Load CVE if it isn't already cached
                if not info.has_key(cve):
                    try:
                        info.setdefault(cve, cve_lib.load_cve(cve_lib.find_cve(cve)))
                    except Exception, e:
                        print >> sys.stderr, "Skipping %s: %s" % (cve, str(e))
                        continue
                # Skip those without PublicDates for the moment
                if info[cve]['PublicDate'].strip() == "":
                    print >>sys.stderr, "%s: empty PublicDate" % (cve)
                    continue

                # Check priority
                # from the all releases or a specific release, find the
                # mapping of CVE priority based on the package that was
                # fixed in the USN.  In the case of multiple match, first
                # most specific wins.
                for rel in db[usn]['releases']:
                    if not release or release == rel:
                        if db[usn]['releases'][rel].has_key('sources'):
                            for pkg in db[usn]['releases'][rel]['sources']:

                                # For now, hard-code list of source packages
                                # we're ignoring.  This will need to be dealt
                                # with in a better way once we have a fuller
                                # understanding of the ramifications of having
                                # multiple source packages for the kernel.
                                if pkg in ['linux-mvl-dove','linux-fsl-imx51','linux-ec2','linux-qcm-msm','linux-ti-omap', 'linux-armadaxp'] and db[usn]['releases'][rel]['sources'].has_key('linux'):
                                    continue
                                # Skip updates duplicated in firefox
                                if pkg in ['xulrunner-1.9.2','thunderbird'] and db[usn]['releases'][rel]['sources'].has_key('firefox'):
                                    continue

                                specificity, cve_priority = cve_lib.contextual_priority(info[cve], pkg, rel)
                                if not priority or cve_priority == priority:
                                    report_pkg = pkg
                                    if cve_lib.pkg_alternates.has_key(pkg):
                                        report_pkg = cve_lib.pkg_alternates[pkg]
                                    fixed.setdefault(report_pkg, dict())
                                    fixed[report_pkg].setdefault(cve_priority, set())
                                    fixed[report_pkg][cve_priority].add(cve)
    return fixed

priorities = ['untriaged'] + cve_lib.priorities

if opt.action == 'list':
    fixed = fixed_map(opt.priority)
    for pkg in fixed:
        print pkg
        for priority in priorities:
            count = 0
            cves = []
            if fixed[pkg].has_key(priority):
                count = len(fixed[pkg][priority])
                cves = sorted(fixed[pkg][priority])
            print "\t%s(%d): %s" % (priority, count, " ".join(cves))
elif opt.action == 'plot':
    fixed = fixed_map(opt.priority)
    for pkg in fixed:
        print pkg,
        total = 0
        for priority in priorities:
            count = 0
            if fixed[pkg].has_key(priority):
                count = len(fixed[pkg][priority])
            print count,
            total += count
        print total
else:
    raise ValueError, "No such --action '%s'" % (opt.action)