| 2 |
|
|
| 3 |
import sys |
import sys |
| 4 |
sys.path.insert(0,'../lib/python') |
sys.path.insert(0,'../lib/python') |
|
|
|
|
if len(sys.argv) <> 3: |
|
|
print "usage: python tracker_serivce.py SOCKET-PATH DATABASE-PATH" |
|
|
sys.exit(1) |
|
|
socket_name = sys.argv[1] |
|
|
db_name = sys.argv[2] |
|
|
|
|
| 5 |
import bugs |
import bugs |
| 6 |
import re |
import re |
| 7 |
import security_db |
import security_db |
| 8 |
from web_support import * |
from web_support import * |
| 9 |
|
|
| 10 |
|
if len(sys.argv) not in (3, 5): |
| 11 |
|
print "usage: python tracker_service.py SOCKET-PATH DATABASE-PATH" |
| 12 |
|
print " python tracker_service.py URL HOST PORT DATABASE-PATH" |
| 13 |
|
sys.exit(1) |
| 14 |
|
if len(sys.argv) == 3: |
| 15 |
|
socket_name = sys.argv[1] |
| 16 |
|
db_name = sys.argv[2] |
| 17 |
|
webservice_base_class = WebService |
| 18 |
|
else: |
| 19 |
|
server_base_url = sys.argv[1] |
| 20 |
|
server_address = sys.argv[2] |
| 21 |
|
server_port = int(sys.argv[3]) |
| 22 |
|
socket_name = (server_base_url, server_address, server_port) |
| 23 |
|
db_name = sys.argv[4] |
| 24 |
|
webservice_base_class = WebServiceHTTP |
| 25 |
|
|
| 26 |
class BugFilter: |
class BugFilter: |
| 27 |
def __init__(self, params): |
default_action_list = [('show_high_urgency', 'only high urgencies'), |
| 28 |
self.hide_medium_urgency = int(params.get('hide_medium_urgency', |
('show_medium_urgency', 'only medium and high urgencies'), |
| 29 |
(0,))[0]) |
('show_undetermined_urgency', 'issues that may be vulnerable but need to be checked (shown in purple)'), |
| 30 |
self.hide_non_remote = int(params.get('hide_non_remote', |
('show_unimportant_urgency', 'unimportant issues'), |
| 31 |
(0,))[0]) |
('show_remote_only', 'only remote vulnerabilities')] |
| 32 |
|
def __init__(self, params, action_list=None): |
| 33 |
|
if action_list is None: |
| 34 |
|
self.action_list = self.default_action_list |
| 35 |
|
else: |
| 36 |
|
self.action_list = action_list |
| 37 |
|
self.params = {} |
| 38 |
|
for (prop, desc) in self.action_list: |
| 39 |
|
self.params[prop] = int(params.get(prop, (0,))[0]) |
| 40 |
|
|
| 41 |
def actions(self, url): |
def actions(self, url): |
| 42 |
"""Returns a HTML snippet which can be used to change the filter.""" |
"""Returns a HTML snippet which can be used to change the filter.""" |
| 43 |
if self.hide_medium_urgency: |
|
| 44 |
urg = A(url.updateParams(hide_medium_urgency=None), |
l = [] |
| 45 |
'Show lower urgencies') |
for (prop, desc) in self.action_list: |
| 46 |
else: |
if self.params[prop]: |
| 47 |
urg = A(url.updateParams(hide_medium_urgency='1'), |
if self.params['show_medium_urgency'] and prop == 'show_medium_urgency': |
| 48 |
'Hide lower urgencies') |
note = 'Restore lower than medium urgencies' |
| 49 |
if self.hide_non_remote: |
elif self.params['show_high_urgency'] and prop == 'show_high_urgency': |
| 50 |
rem = A(url.updateParams(hide_non_remote=None), |
note = 'Restore lower than high urgencies' |
| 51 |
'Show local vulnerabilities') |
elif self.params['show_remote_only'] and prop == 'show_remote_only': |
| 52 |
else: |
note = 'Restore local vulnerabilities' |
| 53 |
rem = A(url.updateParams(hide_non_remote='1'), |
else: |
| 54 |
'Hide local vulnerabilities') |
note = 'Hide ' + desc |
| 55 |
return P(urg, ' ', rem) |
l.append(TR(TD(A(url.updateParamsDict({prop : None}), note)))) |
| 56 |
|
else: |
| 57 |
def urgencyFiltered(self, urg): |
note = 'Show ' + desc |
| 58 |
"""Returns True if the urgency urg is filtered.""" |
l.append(TR(TD(A(url.updateParamsDict({prop : '1'}), note)))) |
| 59 |
return self.hide_medium_urgency and urg not in ("high", "unknown", "") |
|
| 60 |
|
return TABLE(l) |
| 61 |
|
|
| 62 |
|
def urgencyFiltered(self, urg, vuln): |
| 63 |
|
"""Returns True for urgencies that should be filtered.""" |
| 64 |
|
filterlow = self.params['show_medium_urgency'] and \ |
| 65 |
|
urg in ('low', 'low**', 'unimportant', |
| 66 |
|
'undetermined', 'not yet assigned') |
| 67 |
|
filtermed = self.params['show_high_urgency'] and \ |
| 68 |
|
urg in ('medium', 'medium**', 'low', 'low**', |
| 69 |
|
'unimportant', 'undetermined', 'not yet assigned') |
| 70 |
|
filterund = not self.params['show_undetermined_urgency'] and vuln == 2 |
| 71 |
|
filteruni = not self.params['show_unimportant_urgency'] \ |
| 72 |
|
and urg == 'unimportant' |
| 73 |
|
return filterlow or filtermed or filterund or filteruni |
| 74 |
|
|
| 75 |
def remoteFiltered(self, remote): |
def remoteFiltered(self, remote): |
| 76 |
"""Returns True if the attack range is filtered.""" |
"""Returns True for only remote flaws if filtered.""" |
| 77 |
return remote is not None and self.hide_non_remote and not remote |
return self.params['show_remote_only'] and not remote and not remote is None |
| 78 |
|
|
| 79 |
|
class BugFilterNoDSA(BugFilter): |
| 80 |
|
def __init__(self, params): |
| 81 |
|
BugFilter.__init__(self, params, self.default_action_list |
| 82 |
|
+ [('show_nodsa', 'issues that are not severe enough to warrant a DSA')]) |
| 83 |
|
|
| 84 |
class TrackerService(WebService): |
def nodsaFiltered(self, nodsa): |
| 85 |
|
"""Returns True for no DSA issues if filtered.""" |
| 86 |
|
return nodsa and not self.params['show_nodsa'] |
| 87 |
|
|
| 88 |
|
class TrackerService(webservice_base_class): |
| 89 |
head_contents = compose(STYLE( |
head_contents = compose(STYLE( |
| 90 |
"""h1 { font-size : 144%; } |
"""h1 { font-size : 144%; } |
| 91 |
h2 { font-size : 120%; } |
h2 { font-size : 120%; } |
| 97 |
padding-right : 0.25em; } |
padding-right : 0.25em; } |
| 98 |
td { vertical-align: baseline } |
td { vertical-align: baseline } |
| 99 |
span.red { color: red; } |
span.red { color: red; } |
| 100 |
|
span.purple { color: purple; } |
| 101 |
span.dangerous { color: rgb(191,127,0); } |
span.dangerous { color: rgb(191,127,0); } |
| 102 |
"""), SCRIPT('''var old_query_value = ""; |
"""), SCRIPT('''var old_query_value = ""; |
| 103 |
|
|
| 117 |
} |
} |
| 118 |
''')).toHTML() |
''')).toHTML() |
| 119 |
|
|
| 120 |
|
nvd_text = P('''If a "**" is included, the urgency field was automatically |
| 121 |
|
assigned by the NVD (National Vulnerability Database). Note that this |
| 122 |
|
rating is automatically derived from a set of known factors about the |
| 123 |
|
issue (such as access complexity, confidentiality impact, exploitability, |
| 124 |
|
remediation level, and others). Human intervention is involved in |
| 125 |
|
determining the values of these factors, but the rating itself comes |
| 126 |
|
from a fully automated formula.''') |
| 127 |
|
|
| 128 |
def __init__(self, socket_name, db_name): |
def __init__(self, socket_name, db_name): |
| 129 |
WebService.__init__(self, socket_name) |
webservice_base_class.__init__(self, socket_name) |
| 130 |
self.db = security_db.DB(db_name) |
self.db = security_db.DB(db_name) |
| 131 |
self.register('', self.page_home) |
self.register('', self.page_home) |
| 132 |
self.register('*', self.page_object) |
self.register('*', self.page_object) |
| 133 |
self.register('redirect/*', self.page_redirect) |
self.register('redirect/*', self.page_redirect) |
| 134 |
self.register('source-package/*', self.page_source_package) |
self.register('source-package/*', self.page_source_package) |
| 135 |
self.register('binary-package/*', self.page_binary_package) |
self.register('status/release/oldstable', |
| 136 |
|
self.page_status_release_oldstable) |
| 137 |
self.register('status/release/stable', self.page_status_release_stable) |
self.register('status/release/stable', self.page_status_release_stable) |
| 138 |
|
self.register('status/release/stable-backports', |
| 139 |
|
self.page_status_release_stable_backports) |
| 140 |
|
self.register('status/release/oldstable-backports', |
| 141 |
|
self.page_status_release_oldstable_backports) |
| 142 |
self.register('status/release/testing', |
self.register('status/release/testing', |
| 143 |
self.page_status_release_testing) |
self.page_status_release_testing) |
| 144 |
self.register('status/release/unstable', |
self.register('status/release/unstable', |
| 146 |
self.register('status/dtsa-candidates', |
self.register('status/dtsa-candidates', |
| 147 |
self.page_status_dtsa_candidates) |
self.page_status_dtsa_candidates) |
| 148 |
self.register('status/todo', self.page_status_todo) |
self.register('status/todo', self.page_status_todo) |
| 149 |
|
self.register('status/undetermined', self.page_status_undetermined) |
| 150 |
|
self.register('status/unimportant', self.page_status_unimportant) |
| 151 |
self.register('status/itp', self.page_status_itp) |
self.register('status/itp', self.page_status_itp) |
| 152 |
self.register('data/unknown-packages', self.page_data_unknown_packages) |
self.register('data/unknown-packages', self.page_data_unknown_packages) |
| 153 |
self.register('data/missing-epochs', self.page_data_missing_epochs) |
self.register('data/missing-epochs', self.page_data_missing_epochs) |
| 154 |
|
self.register('data/latently-vulnerable', |
| 155 |
|
self.page_data_latently_vulnerable) |
| 156 |
self.register('data/releases', self.page_data_releases) |
self.register('data/releases', self.page_data_releases) |
| 157 |
self.register('data/funny-versions', self.page_data_funny_versions) |
self.register('data/funny-versions', self.page_data_funny_versions) |
| 158 |
self.register('data/fake-names', self.page_data_fake_names) |
self.register('data/fake-names', self.page_data_fake_names) |
| 159 |
|
self.register('data/pts/1', self.page_data_pts) |
| 160 |
|
self.register('debsecan/**', self.page_debsecan) |
| 161 |
|
self.register('data/report', self.page_report) |
| 162 |
|
|
| 163 |
def page_home(self, path, params, url): |
def page_home(self, path, params, url): |
| 164 |
query = params.get('query', ('',))[0] |
query = params.get('query', ('',))[0] |
| 171 |
return self.create_page( |
return self.create_page( |
| 172 |
url, 'Security Bug Tracker', |
url, 'Security Bug Tracker', |
| 173 |
[P( |
[P( |
| 174 |
"""This is the experimental issue tracker for Debian's testing |
"""The data in this tracker comes solely from the bug database maintained |
| 175 |
security team. Keep in mind that this is merely a prototype. |
by Debian's security team located in the testing-security Subversion """, |
| 176 |
Please report any problems to """, |
A("http://svn.debian.org/wsvn/secure-testing/data/", "repository"), |
| 177 |
A("mailto:fw@deneb.enyo.de", "Florian Weimer"), |
""". The data represented here is derived from: """, |
| 178 |
""".Note that some of the data presented here is known |
A("http://www.debian.org/security/#DSAS", "DSAs"), |
| 179 |
to be wrong (see below), but the data for the testing suite |
""" issued by the Security Team; issues tracked in the """, |
| 180 |
should be fine."""), |
A("http://cve.mitre.org/cve/", "CVE database"), |
| 181 |
make_menu( |
""", issues tracked in the """, |
| 182 |
|
A("http://nvd.nist.gov/", "National Vulnerability Database"), |
| 183 |
|
""" (NVD), maintained by NIST; and security issues |
| 184 |
|
discovered in Debian packages as reported in the BTS."""), |
| 185 |
|
P("""All external data (including Debian bug reports and official Debian |
| 186 |
|
security advisories) must be added to this database before it appears |
| 187 |
|
here. Please help us keep this information up-to-date by """, |
| 188 |
|
A(url.scriptRelative("data/report"), "reporting"), |
| 189 |
|
""" any discrepancies or change of states that you are |
| 190 |
|
aware of and/or help us improve the quality of this information by """, |
| 191 |
|
A(url.scriptRelative("data/report"), "participating"), |
| 192 |
|
"."), |
| 193 |
|
make_menu( |
| 194 |
url.scriptRelative, |
url.scriptRelative, |
|
('status/release/stable', |
|
|
'Vulnerable packages in the stable suite'), |
|
|
('status/release/testing', |
|
|
'Vulnerable packages in the testing suite'), |
|
| 195 |
('status/release/unstable', |
('status/release/unstable', |
| 196 |
'Vulnerable packages in the unstable suite'), |
'Vulnerable packages in the unstable suite'), |
| 197 |
|
('status/release/testing', |
| 198 |
|
'Vulnerable packages in the testing suite'), |
| 199 |
|
('status/release/stable', |
| 200 |
|
'Vulnerable packages in the stable suite'), |
| 201 |
|
('status/release/oldstable', |
| 202 |
|
'Vulnerable packages in the old stable suite'), |
| 203 |
|
('status/release/stable-backports', |
| 204 |
|
'Vulnerable packages in backports for stable'), |
| 205 |
|
('status/release/oldstable-backports', |
| 206 |
|
'Vulnerable packages in backports for oldstable'), |
| 207 |
('status/dtsa-candidates', "Candidates for DTSAs"), |
('status/dtsa-candidates', "Candidates for DTSAs"), |
| 208 |
('status/todo', 'TODO items'), |
('status/todo', 'TODO items'), |
| 209 |
|
('status/undetermined', 'Packages that may be vulnerable but need to be checked (undetermined issues)'), |
| 210 |
|
('status/unimportant', 'Packages that have open unimportant issues'), |
| 211 |
('status/itp', 'ITPs with potential security issues'), |
('status/itp', 'ITPs with potential security issues'), |
| 212 |
('data/unknown-packages', |
('data/unknown-packages', |
| 213 |
'Packages names not found in the archive'), |
'Packages names not found in the archive'), |
| 214 |
('data/fake-names', 'Tracked issues without a CVE name'), |
('data/fake-names', 'Tracked issues without a CVE name'), |
| 215 |
('data/missing-epochs', |
('data/missing-epochs', |
| 216 |
'Package versions which might lack an epoch'), |
'Package versions which might lack an epoch'), |
| 217 |
|
('data/latently-vulnerable', |
| 218 |
|
'Packages which are latently vulnerable in unstable'), |
| 219 |
('data/funny-versions', |
('data/funny-versions', |
| 220 |
'Packages with strange version numbers'), |
'Packages with strange version numbers'), |
| 221 |
('data/releases', |
('data/releases', |
| 224 |
P("""(You can enter CVE names, Debian bug numbers and package |
P("""(You can enter CVE names, Debian bug numbers and package |
| 225 |
names in the search forms.)"""), |
names in the search forms.)"""), |
| 226 |
|
|
|
H2("Data sources"), |
|
|
P("""Data in this tracker comes solely from the bug database |
|
|
which is maintained by Debian's testing security team in their |
|
|
Subversion repository. All external data (this includes |
|
|
Debian bug reports and official Debian security advisories) |
|
|
must be added to this database before it appears here, and there |
|
|
can be some delay before this happens."""), |
|
|
P("""At the moment, the database only contains information which is |
|
|
relevant for tracking the security status of the stable, testing and |
|
|
unstable suites. This means that data for oldstable is likely wrong."""), |
|
|
P('Data marked "NVD" comes from the ', |
|
|
A(url.absolute('http://nvd.nist.gov/'), |
|
|
'National Vulnerability Database'), |
|
|
' maintained by NIST.'), |
|
|
|
|
| 227 |
H2("External interfaces"), |
H2("External interfaces"), |
| 228 |
P("""If you want to automatically open a relevant web page for |
P("""If you want to automatically open a relevant web page for |
| 229 |
some object, use the """, |
some object, use the """, |
| 238 |
return self.page_object_or_redirect(url, obj, False) |
return self.page_object_or_redirect(url, obj, False) |
| 239 |
|
|
| 240 |
def page_redirect(self, path, params, url): |
def page_redirect(self, path, params, url): |
| 241 |
obj = path[0] |
if path == (): |
| 242 |
|
obj = '' |
| 243 |
|
else: |
| 244 |
|
obj = path[0] |
| 245 |
return self.page_object_or_redirect(url, obj, True) |
return self.page_object_or_redirect(url, obj, True) |
| 246 |
|
|
| 247 |
def page_object_or_redirect(self, url, obj, redirect): |
def page_object_or_redirect(self, url, obj, redirect): |
| 250 |
if not obj: |
if not obj: |
| 251 |
# Redirect to start page. |
# Redirect to start page. |
| 252 |
return RedirectResult(url.scriptRelativeFull("")) |
return RedirectResult(url.scriptRelativeFull("")) |
|
|
|
|
if 'A' <= obj[0] <= 'Z': |
|
|
# Bug names start with a capital letter. |
|
|
return self.page_bug(url, obj, redirect) |
|
| 253 |
|
|
| 254 |
|
# Attempt to decode a bug number. TEMP-nnn bugs (but not |
| 255 |
|
# TEMP-nnn-mmm bugs) are treated as bug references, too. |
| 256 |
bugnumber = 0 |
bugnumber = 0 |
| 257 |
|
fake_bug = False |
| 258 |
try: |
try: |
| 259 |
bugnumber = int(obj) |
if obj[0:5] == 'FAKE-' or obj[0:5] == 'TEMP-': |
| 260 |
|
bugnumber = int(obj[5:]) |
| 261 |
|
fake_bug = True |
| 262 |
|
else: |
| 263 |
|
bugnumber = int(obj) |
| 264 |
except ValueError: |
except ValueError: |
| 265 |
pass |
pass |
| 266 |
if bugnumber: |
if bugnumber: |
| 267 |
buglist = list(self.db.getBugsFromDebianBug(c, bugnumber)) |
buglist = list(self.db.getBugsFromDebianBug(c, bugnumber)) |
| 268 |
if buglist: |
if buglist: |
| 269 |
return self.page_debian_bug(url, bugnumber, buglist) |
return self.page_debian_bug(url, bugnumber, buglist, fake_bug) |
| 270 |
if redirect: |
if redirect: |
| 271 |
return RedirectResult(self.url_debian_bug(url, str(bugnumber)), |
return RedirectResult(self.url_debian_bug(url, str(bugnumber)), |
| 272 |
permanent=False) |
permanent=False) |
| 273 |
|
|
| 274 |
|
if 'A' <= obj[0] <= 'Z': |
| 275 |
|
# Bug names start with a capital letter. |
| 276 |
|
return self.page_bug(url, obj, redirect) |
| 277 |
|
|
| 278 |
if self.db.isSourcePackage(c, obj): |
if self.db.isSourcePackage(c, obj): |
| 279 |
return RedirectResult(self.url_source_package(url, obj, full=True)) |
return RedirectResult(self.url_source_package(url, obj, full=True)) |
|
if self.db.isBinaryPackage(c, obj): |
|
|
return RedirectResult(self.url_binary_package(url ,obj, full=True)) |
|
| 280 |
|
|
| 281 |
return self.page_not_found(url, obj) |
return self.page_not_found(url, obj) |
| 282 |
|
|
| 307 |
source = bug.name.split('-')[0] |
source = bug.name.split('-')[0] |
| 308 |
if source == 'CVE': |
if source == 'CVE': |
| 309 |
source_xref = compose(self.make_cve_ref(url, bug.name, 'CVE'), |
source_xref = compose(self.make_cve_ref(url, bug.name, 'CVE'), |
| 310 |
" (", |
" (at ", |
| 311 |
self.make_nvd_ref(url, bug.name, |
self.make_nvd_ref(url, bug.name, |
| 312 |
'in NVD'), |
'NVD'), |
| 313 |
|
"; ", |
| 314 |
|
self.make_rhbug_ref(url, bug.name, |
| 315 |
|
'RH'), |
| 316 |
")") |
")") |
| 317 |
elif source == 'DSA': |
elif source == 'DSA': |
| 318 |
source_xref = self.make_dsa_ref(url, bug.name, 'Debian') |
source_xref = self.make_dsa_ref(url, bug.name, 'Debian') |
| 319 |
elif source == 'DTSA': |
elif source == 'DTSA': |
| 320 |
source_xref = 'Debian Testing Security Team' |
source_xref = 'Debian Testing Security Team' |
| 321 |
elif source == 'FAKE': |
elif source == 'TEMP': |
| 322 |
source_xref = ( |
source_xref = ( |
| 323 |
'Automatically generated temporary name. Not for external reference.') |
'Automatically generated temporary name. Not for external reference.') |
| 324 |
else: |
else: |
| 327 |
if source_xref: |
if source_xref: |
| 328 |
yield B("Source"), source_xref |
yield B("Source"), source_xref |
| 329 |
|
|
| 330 |
if bug.description: |
nvd = self.db.getNVD(cursor, bug.name) |
| 331 |
|
|
| 332 |
|
if nvd and nvd.cve_desc: |
| 333 |
|
yield B("Description"), nvd.cve_desc |
| 334 |
|
elif bug.description: |
| 335 |
yield B("Description"), bug.description |
yield B("Description"), bug.description |
| 336 |
|
|
| 337 |
xref = list(self.db.getBugXrefs(cursor, bug.name)) |
xref = list(self.db.getBugXrefs(cursor, bug.name)) |
| 338 |
if xref: |
if xref: |
| 339 |
yield B("References"), self.make_xref_list(url, xref) |
yield B("References"), self.make_xref_list(url, xref) |
| 340 |
|
|
|
nvd = self.db.getNVD(cursor, bug.name) |
|
| 341 |
if nvd: |
if nvd: |
|
if nvd.severity: |
|
|
yield B("NVD severity"), nvd.severity.lower() |
|
| 342 |
nvd_range = nvd.rangeString() |
nvd_range = nvd.rangeString() |
| 343 |
if nvd_range: |
if nvd.severity: |
| 344 |
yield B("NVD attack range"), nvd_range |
nvd_severity = nvd.severity.lower() |
| 345 |
|
if nvd_range: |
| 346 |
|
nvd_severity = "%s (attack range: %s)" \ |
| 347 |
|
% (nvd_severity, nvd_range) |
| 348 |
|
yield B("NVD severity"), nvd_severity |
| 349 |
|
|
| 350 |
debian_bugs = bug.getDebianBugs(cursor) |
debian_bugs = bug.getDebianBugs(cursor) |
| 351 |
if debian_bugs: |
if debian_bugs: |
| 354 |
|
|
| 355 |
if not bug.not_for_us: |
if not bug.not_for_us: |
| 356 |
for (release, status, reason) in bug.getStatus(cursor): |
for (release, status, reason) in bug.getStatus(cursor): |
| 357 |
if status <> 'fixed': |
if status == 'undetermined': |
| 358 |
|
reason = self.make_purple(reason) |
| 359 |
|
elif status <> 'fixed': |
| 360 |
reason = self.make_red(reason) |
reason = self.make_red(reason) |
| 361 |
yield B('Status of %s' % release), reason |
yield B('Debian/%s' % release), reason |
| 362 |
|
|
| 363 |
page.append(make_table(gen_header())) |
page.append(make_table(gen_header())) |
| 364 |
|
|
| 376 |
package = compose( |
package = compose( |
| 377 |
self.make_source_package_ref(url, package), |
self.make_source_package_ref(url, package), |
| 378 |
" (", self.make_pts_ref(url, package, 'PTS'), ")") |
" (", self.make_pts_ref(url, package, 'PTS'), ")") |
| 379 |
if vulnerable: |
if vulnerable == 1: |
| 380 |
vuln = self.make_red('vulnerable') |
vuln = self.make_red('vulnerable') |
| 381 |
version = self.make_red(version) |
version = self.make_red(version) |
| 382 |
|
elif vulnerable == 2: |
| 383 |
|
vuln = self.make_purple('undetermined') |
| 384 |
|
version = self.make_purple(version) |
| 385 |
else: |
else: |
| 386 |
vuln = 'fixed' |
vuln = 'fixed' |
| 387 |
|
|
| 391 |
caption=("Source Package", "Release", "Version", "Status"), |
caption=("Source Package", "Release", "Version", "Status"), |
| 392 |
introduction=P('The table below lists information on source packages.'))) |
introduction=P('The table below lists information on source packages.'))) |
| 393 |
|
|
|
def gen_binary(): |
|
|
old_pkg = '' |
|
|
for (packages, releases, version, archs, vulnerable) \ |
|
|
in self.db.getBinaryPackages(cursor, bug.name): |
|
|
pkg = ', '.join(packages) |
|
|
if pkg == old_pkg: |
|
|
packages = '' |
|
|
else: |
|
|
old_pkg = pkg |
|
|
packages = self.make_binary_packages_ref(url, packages) |
|
|
|
|
|
if vulnerable: |
|
|
vuln = self.make_red('vulnerable') |
|
|
version = self.make_red(version) |
|
|
else: |
|
|
vuln = 'fixed' |
|
|
yield (packages, |
|
|
', '.join(releases), |
|
|
version, vuln, |
|
|
', '.join(archs)) |
|
|
|
|
|
page.append(make_table(gen_binary(), |
|
|
caption=("Binary Package", "Release", "Version", "Status", |
|
|
"Architecures"), |
|
|
introduction=P("The next table lists affected binary packages."))) |
|
|
|
|
| 394 |
def gen_data(): |
def gen_data(): |
| 395 |
notes_sorted = bug.notes[:] |
notes_sorted = bug.notes[:] |
| 396 |
notes_sorted.sort(lambda a, b: cmp(a.package, b.package)) |
notes_sorted.sort(lambda a, b: cmp(a.package, b.package)) |
| 407 |
urgency = '' |
urgency = '' |
| 408 |
else: |
else: |
| 409 |
ver = self.make_red('(unfixed)') |
ver = self.make_red('(unfixed)') |
| 410 |
|
if urgency == 'not yet assigned': |
| 411 |
|
urgency = '' |
| 412 |
|
|
| 413 |
pkg = n.package |
pkg = n.package |
| 414 |
pkg_kind = n.package_kind |
pkg_kind = n.package_kind |
| 415 |
if pkg_kind == 'source': |
if pkg_kind == 'source': |
| 416 |
pkg = self.make_source_package_ref(url, pkg) |
pkg = self.make_source_package_ref(url, pkg) |
|
elif pkg_kind == 'binary': |
|
|
pkg = self.make_binary_package_ref(url, pkg) |
|
| 417 |
elif pkg_kind == 'itp': |
elif pkg_kind == 'itp': |
| 418 |
pkg_kind = 'ITP' |
pkg_kind = 'ITP' |
| 419 |
rel = '' |
rel = '' |
| 445 |
|
|
| 446 |
return self.create_page(url, bug.name, page) |
return self.create_page(url, bug.name, page) |
| 447 |
|
|
| 448 |
def page_debian_bug(self, url, bugnumber, buglist): |
def page_debian_bug(self, url, bugnumber, buglist, fake_bug): |
| 449 |
|
if fake_bug: |
| 450 |
|
new_buglist = [] |
| 451 |
|
for b in buglist: |
| 452 |
|
(bug_name, urgency, description) = b |
| 453 |
|
if bug_name[0:5] == 'FAKE-' or bug_name[0:5] == 'TEMP-': |
| 454 |
|
new_buglist.append(b) |
| 455 |
|
if len(new_buglist) > 0: |
| 456 |
|
# Only replace the bug list if there are still fake |
| 457 |
|
# bug reports. |
| 458 |
|
buglist = new_buglist |
| 459 |
|
|
| 460 |
if len(buglist) == 1: |
if len(buglist) == 1: |
| 461 |
# Single issue, redirect. |
# Single issue, redirect. |
| 462 |
return RedirectResult(url.scriptRelativeFull(buglist[0][0])) |
return RedirectResult(url.scriptRelativeFull(buglist[0][0])) |
| 467 |
urgency = "" |
urgency = "" |
| 468 |
yield self.make_xref(url, name), urgency, description |
yield self.make_xref(url, name), urgency, description |
| 469 |
|
|
| 470 |
|
if fake_bug: |
| 471 |
|
intro = """The URL you used contained a non-stable name |
| 472 |
|
based on a Debian bug number. This name cannot be mapped to a specific |
| 473 |
|
issue. """ |
| 474 |
|
else: |
| 475 |
|
intro = "" |
| 476 |
|
|
| 477 |
return self.create_page( |
return self.create_page( |
| 478 |
url, "Information related to Debian bug #%d" % bugnumber, |
url, "Information related to Debian bug #%d" % bugnumber, |
| 479 |
[P("The following issues reference to Debian bug ", |
[P(intro + "The following issues reference to Debian bug ", |
| 480 |
self.make_debian_bug(url, bugnumber), ":"), |
self.make_debian_bug(url, bugnumber), ":"), |
| 481 |
make_table(gen(), |
make_table(gen(), |
| 482 |
caption=("Name", "Urgency", "Description"))]) |
caption=("Name", "Urgency", "Description"))]) |
| 488 |
' matched no results.')], |
' matched no results.')], |
| 489 |
status=404) |
status=404) |
| 490 |
|
|
| 491 |
|
def page_report(self, path, params, url): |
| 492 |
|
return self.create_page( |
| 493 |
|
url, 'Reporting discrepancies in the data', |
| 494 |
|
[P("""The data in this tracker is always in flux, as bugs are fixed and new |
| 495 |
|
issues disclosed, the data contained herein is updated. We strive to |
| 496 |
|
maintain complete and accurate state information, and appreciate any |
| 497 |
|
updates in status, information or new issues."""), |
| 498 |
|
P("There are three ways that you can report updates to this information:"), |
| 499 |
|
make_numbered_list( |
| 500 |
|
[P("""IRC: We can be found at """, |
| 501 |
|
CODE("irc.oftc.net"), |
| 502 |
|
", ", |
| 503 |
|
CODE("#debian-security"), |
| 504 |
|
""". If you have information to report, please go ahead and join |
| 505 |
|
the channel and tell us. Please feel free to state the issue, |
| 506 |
|
regardless if there is someone who has acknowledged you. Many of us |
| 507 |
|
idle on this channel and may not be around when you join, but we read |
| 508 |
|
the backlog and will see what you have said. If you require a |
| 509 |
|
response, do not forget to let us know how to get a hold of you."""), |
| 510 |
|
P("Mailing list: Our mailing list is: ", |
| 511 |
|
A("mailto:debian-security-tracker@lists.debian.org", |
| 512 |
|
"debian-security-tracker@lists.debian.org")), |
| 513 |
|
P("""Helping out: We welcome people who wish to join us in tracking |
| 514 |
|
issues. The process is designed to be easy to learn and participate, |
| 515 |
|
please read our """, |
| 516 |
|
A("http://svn.debian.org/wsvn/secure-testing/doc/narrative_introduction?op=file&rev=0&sc=0", |
| 517 |
|
"Introduction"), |
| 518 |
|
""" to get familiar with how things work. Join us on |
| 519 |
|
our mailing list, and on IRC and request to be added to the Alioth """, |
| 520 |
|
A("http://alioth.debian.org/projects/secure-testing/", "project"), |
| 521 |
|
""". We are really quite friendly. If you have a |
| 522 |
|
question about how things work, don't be afraid to ask, we would like |
| 523 |
|
to improve our documentation and procedures, so feedback is welcome.""")])]) |
| 524 |
|
|
| 525 |
def page_source_package(self, path, params, url): |
def page_source_package(self, path, params, url): |
| 526 |
pkg = path[0] |
pkg = path[0] |
| 527 |
|
|
| 529 |
for (releases, version) in self.db.getSourcePackageVersions( |
for (releases, version) in self.db.getSourcePackageVersions( |
| 530 |
self.db.cursor(), pkg): |
self.db.cursor(), pkg): |
| 531 |
yield ', '.join(releases), version |
yield ', '.join(releases), version |
|
def gen_binary(): |
|
|
for (packages, releases, archs, version) \ |
|
|
in self.db.getBinaryPackagesForSource( |
|
|
self.db.cursor(), pkg): |
|
|
yield (self.make_binary_packages_ref(url, packages), |
|
|
', '.join(releases), version, ', '.join(archs)) |
|
| 532 |
def gen_bug_list(lst): |
def gen_bug_list(lst): |
| 533 |
for (bug, description) in lst: |
for (bug, description) in lst: |
| 534 |
yield self.make_xref(url, bug), description |
yield self.make_xref(url, bug), description |
| 545 |
H2("Available versions"), |
H2("Available versions"), |
| 546 |
make_table(gen_versions(), caption=("Release", "Version")), |
make_table(gen_versions(), caption=("Release", "Version")), |
| 547 |
|
|
|
H2("Available binary packages"), |
|
|
make_table(gen_binary(), |
|
|
caption=('Package', 'Release', 'Version', 'Architectures'), |
|
|
replacement="""No binary packages are recorded in this database. |
|
|
This probably means that the package is architecture-specific, and the |
|
|
architecture is currently not tracked."""), |
|
|
|
|
| 548 |
H2("Open issues"), |
H2("Open issues"), |
| 549 |
make_table(gen_bug_list(self.db.getBugsForSourcePackage |
make_table(gen_bug_list(self.db.getBugsForSourcePackage |
| 550 |
(self.db.cursor(), pkg, True)), |
(self.db.cursor(), pkg, True)), |
| 557 |
caption=('Bug', 'Description'), |
caption=('Bug', 'Description'), |
| 558 |
replacement='No known resolved issues.')]) |
replacement='No known resolved issues.')]) |
| 559 |
|
|
| 560 |
def page_binary_package(self, path, params, url): |
def page_status_release_stable_oldstable(self, release, params, url): |
| 561 |
pkg = path[0] |
assert release in ('stable', 'oldstable') |
| 562 |
|
|
| 563 |
def gen_versions(): |
bf = BugFilterNoDSA(params) |
|
for (releases, source, version, archs) \ |
|
|
in self.db.getBinaryPackageVersions(self.db.cursor(), pkg): |
|
|
yield (', '.join(releases), |
|
|
self.make_source_package_ref(url, source), |
|
|
version, ', '.join(archs)) |
|
|
def gen_bug_list(lst): |
|
|
for (bug, description) in lst: |
|
|
yield self.make_xref(url, bug), description |
|
|
|
|
|
return self.create_page( |
|
|
url, "Information on binary package " + pkg, |
|
|
[make_menu(lambda x: x, |
|
|
(self.url_debian_bug_pkg(url, pkg), |
|
|
pkg + ' in the Bug Tracking System')), |
|
|
H2("Available versions"), |
|
|
make_table(gen_versions(), |
|
|
caption=("Release", "Source", "Version", "Architectures")), |
|
|
|
|
|
H2("Open issues"), |
|
|
make_table(gen_bug_list(self.db.getBugsForBinaryPackage |
|
|
(self.db.cursor(), pkg, True)), |
|
|
caption=('Bug', 'Description'), |
|
|
replacement='No known open issues.'), |
|
|
|
|
|
H2("Resolved issues"), |
|
|
make_table(gen_bug_list(self.db.getBugsForBinaryPackage |
|
|
(self.db.cursor(), pkg, False)), |
|
|
caption=('Bug', 'Description'), |
|
|
replacement='No known resolved issues.'), |
|
|
|
|
|
H2("Non-issues"), |
|
|
make_table(gen_bug_list(self.db.getNonBugsForBinaryPackage |
|
|
(self.db.cursor(), pkg)), |
|
|
caption=('Bug', 'Description'), |
|
|
replacement="""No known issues which do not affect |
|
|
this package, but still reference it.""")]) |
|
|
|
|
|
def page_status_release_stable(self, path, params, url): |
|
|
bf = BugFilter(params) |
|
| 564 |
|
|
| 565 |
def gen(): |
def gen(): |
| 566 |
old_pkg_name = '' |
old_pkg_name = '' |
| 567 |
for (pkg_name, bug_name, archive, urgency, remote) in \ |
for (pkg_name, bug_name, archive, urgency, vulnerable, remote, no_dsa) in \ |
| 568 |
self.db.cursor().execute( |
self.db.cursor().execute( |
| 569 |
"""SELECT package, bug, section, urgency, remote |
"""SELECT package, bug, section, urgency, vulnerable, remote, no_dsa |
| 570 |
FROM stable_status"""): |
FROM %s_status""" % release): |
| 571 |
if bf.urgencyFiltered(urgency): |
if bf.urgencyFiltered(urgency, vulnerable): |
| 572 |
continue |
continue |
| 573 |
if bf.remoteFiltered(remote): |
if bf.remoteFiltered(remote): |
| 574 |
continue |
continue |
| 575 |
|
if bf.nodsaFiltered(no_dsa): |
| 576 |
|
continue |
| 577 |
|
|
| 578 |
if pkg_name == old_pkg_name: |
if pkg_name == old_pkg_name: |
| 579 |
pkg_name = '' |
pkg_name = '' |
| 580 |
else: |
else: |
| 583 |
pkg_name = "%s (%s)" % (pkg_name, archive) |
pkg_name = "%s (%s)" % (pkg_name, archive) |
| 584 |
|
|
| 585 |
if remote is None: |
if remote is None: |
| 586 |
remote = '' |
remote = '???' |
| 587 |
elif remote: |
elif remote: |
| 588 |
remote = 'yes' |
remote = 'yes' |
| 589 |
else: |
else: |
| 590 |
remote = 'no' |
remote = 'no' |
| 591 |
|
|
| 592 |
if urgency == 'unknown': |
if urgency.startswith('high'): |
|
urgency = '' |
|
|
elif urgency == 'high': |
|
| 593 |
urgency = self.make_red(urgency) |
urgency = self.make_red(urgency) |
| 594 |
|
elif vulnerable == 2: |
| 595 |
|
urgency = self.make_purple(urgency) |
| 596 |
|
else: |
| 597 |
|
if no_dsa: |
| 598 |
|
urgency = urgency + '*' |
| 599 |
|
|
| 600 |
yield pkg_name, self.make_xref(url, bug_name), urgency, remote |
yield pkg_name, self.make_xref(url, bug_name), urgency, remote |
| 601 |
|
|
| 602 |
return self.create_page( |
return self.create_page( |
| 603 |
url, 'Vulnerable source packages in the stable suite', |
url, 'Vulnerable source packages in the %s suite' % release, |
| 604 |
[bf.actions(url), |
[bf.actions(url), BR(), |
| 605 |
make_table(gen(), caption=("Package", "Bug", "Urgency", |
make_table(gen(), caption=("Package", "Bug", "Urgency", "Remote")), |
| 606 |
"Remote"))]) |
P('''If a "*" is included in the urgency field, no DSA is planned |
| 607 |
|
for this vulnerability.'''), |
| 608 |
|
self.nvd_text]) |
| 609 |
|
|
| 610 |
|
def page_status_release_stable(self, path, params, url): |
| 611 |
|
return self.page_status_release_stable_oldstable('stable', params, url) |
| 612 |
|
def page_status_release_oldstable(self, path, params, url): |
| 613 |
|
return self.page_status_release_stable_oldstable('oldstable', |
| 614 |
|
params, url) |
| 615 |
|
|
| 616 |
def page_status_release_testing(self, path, params, url): |
def page_status_release_testing(self, path, params, url): |
| 617 |
bf = BugFilter(params) |
bf = BugFilterNoDSA(params) |
| 618 |
|
|
| 619 |
def gen(): |
def gen(): |
| 620 |
old_pkg_name = '' |
old_pkg_name = '' |
| 621 |
for (pkg_name, bug_name, archive, urgency, |
for (pkg_name, bug_name, archive, urgency, vulnerable, |
| 622 |
sid_vulnerable, ts_fixed, remote) in self.db.cursor().execute( |
sid_vulnerable, ts_fixed, remote, no_dsa) \ |
| 623 |
"""SELECT package, bug, section, urgency, unstable_vulnerable, |
in self.db.cursor().execute( |
| 624 |
testing_security_fixed, remote |
"""SELECT package, bug, section, urgency, vulnerable, |
| 625 |
|
unstable_vulnerable, testing_security_fixed, remote, no_dsa |
| 626 |
FROM testing_status"""): |
FROM testing_status"""): |
| 627 |
if bf.urgencyFiltered(urgency): |
if bf.urgencyFiltered(urgency, vulnerable): |
| 628 |
continue |
continue |
| 629 |
if bf.remoteFiltered(remote): |
if bf.remoteFiltered(remote): |
| 630 |
continue |
continue |
| 631 |
|
if bf.nodsaFiltered(no_dsa): |
| 632 |
|
continue |
| 633 |
|
|
| 634 |
if pkg_name == old_pkg_name: |
if pkg_name == old_pkg_name: |
| 635 |
pkg_name = '' |
pkg_name = '' |
| 639 |
pkg_name = "%s (%s)" % (pkg_name, archive) |
pkg_name = "%s (%s)" % (pkg_name, archive) |
| 640 |
|
|
| 641 |
if remote is None: |
if remote is None: |
| 642 |
remote = '' |
remote = '???' |
| 643 |
elif remote: |
elif remote: |
| 644 |
remote = 'yes' |
remote = 'yes' |
| 645 |
else: |
else: |
| 653 |
else: |
else: |
| 654 |
status = self.make_dangerous('fixed in unstable') |
status = self.make_dangerous('fixed in unstable') |
| 655 |
|
|
| 656 |
if urgency == 'unknown': |
if urgency.startswith('high'): |
| 657 |
urgency = '' |
urgency = self.make_red(urgency) |
| 658 |
|
elif vulnerable == 2: |
| 659 |
|
urgency = self.make_purple(urgency) |
| 660 |
|
|
| 661 |
yield (pkg_name, self.make_xref(url, bug_name), |
yield (pkg_name, self.make_xref(url, bug_name), |
| 662 |
urgency, remote, status) |
urgency, remote, status) |
| 665 |
url, 'Vulnerable source packages in the testing suite', |
url, 'Vulnerable source packages in the testing suite', |
| 666 |
[make_menu(url.scriptRelative, |
[make_menu(url.scriptRelative, |
| 667 |
("status/dtsa-candidates", "Candidates for DTSAs")), |
("status/dtsa-candidates", "Candidates for DTSAs")), |
| 668 |
bf.actions(url), |
bf.actions(url), BR(), |
| 669 |
make_table(gen(), caption=("Package", "Bug", "Urgency", |
make_table(gen(), caption=("Package", "Bug", "Urgency", "Remote")), |
| 670 |
"Remote"))]) |
self.nvd_text]) |
| 671 |
|
|
| 672 |
def page_status_release_unstable(self, path, params, url): |
def page_status_release_unstable_like(self, path, params, url, |
| 673 |
|
rel, title): |
| 674 |
bf = BugFilter(params) |
bf = BugFilter(params) |
| 675 |
|
|
| 676 |
def gen(): |
def gen(): |
| 677 |
old_pkg_name = '' |
old_pkg_name = '' |
| 678 |
for (pkg_name, bug_name, section, urgency, remote) \ |
for (pkg_name, bug_name, section, urgency, vulnerable, remote) \ |
| 679 |
in self.db.cursor().execute( |
in self.db.cursor().execute( |
| 680 |
"""SELECT DISTINCT sp.name, st.bug_name, |
"""SELECT DISTINCT sp.name, st.bug_name, |
| 681 |
sp.archive, st.urgency, |
sp.archive, st.urgency, st.vulnerable, |
| 682 |
(SELECT range_remote FROM nvd_data |
(SELECT range_remote FROM nvd_data |
| 683 |
WHERE cve_name = st.bug_name) |
WHERE cve_name = st.bug_name) |
| 684 |
FROM source_package_status AS st, source_packages AS sp |
FROM source_package_status AS st, source_packages AS sp |
| 685 |
WHERE st.vulnerable AND st.urgency <> 'unimportant' |
WHERE st.vulnerable AND sp.rowid = st.package |
| 686 |
AND sp.rowid = st.package AND sp.release = 'sid' |
AND sp.release = ? AND sp.subrelease = '' |
| 687 |
AND sp.subrelease = '' |
ORDER BY sp.name, st.bug_name""", (rel,)): |
| 688 |
ORDER BY sp.name, st.bug_name"""): |
if bf.urgencyFiltered(urgency, vulnerable): |
|
if bf.urgencyFiltered(urgency): |
|
| 689 |
continue |
continue |
| 690 |
if bf.remoteFiltered(remote): |
if bf.remoteFiltered(remote): |
| 691 |
continue |
continue |
| 700 |
pkg_name = self.make_xref(url, pkg_name) |
pkg_name = self.make_xref(url, pkg_name) |
| 701 |
|
|
| 702 |
if remote is None: |
if remote is None: |
| 703 |
remote = '' |
remote = '???' |
| 704 |
elif remote: |
elif remote: |
| 705 |
remote = 'yes' |
remote = 'yes' |
| 706 |
else: |
else: |
| 707 |
remote = 'no' |
remote = 'no' |
| 708 |
|
|
| 709 |
if urgency == 'unknown': |
if urgency.startswith('high'): |
|
urgency = '' |
|
|
elif urgency == 'high': |
|
| 710 |
urgency = self.make_red(urgency) |
urgency = self.make_red(urgency) |
| 711 |
|
elif vulnerable == 2: |
| 712 |
|
urgency = self.make_purple(urgency) |
| 713 |
|
|
| 714 |
yield pkg_name, self.make_xref(url, bug_name), urgency, remote |
yield pkg_name, self.make_xref(url, bug_name), urgency, remote |
| 715 |
|
|
|
|
|
| 716 |
return self.create_page( |
return self.create_page( |
| 717 |
url, 'Vulnerable source packages in the unstable suite', |
url, title, |
| 718 |
[P("""Note that the list below is based on source packages. |
[P("""Note that the list below is based on source packages. |
| 719 |
This means that packages are not listed here once a new, |
This means that packages are not listed here once a new, |
| 720 |
fixed source version has been uploaded to the archive, even |
fixed source version has been uploaded to the archive, even |
| 721 |
if there are still some vulnerably binary packages present |
if there are still some vulnerably binary packages present |
| 722 |
in the archive."""), |
in the archive."""), |
| 723 |
bf.actions(url), |
bf.actions(url), BR(), |
| 724 |
make_table(gen(), caption=('Package', 'Bug', 'Urgency', |
make_table(gen(), caption=('Package', 'Bug', 'Urgency', 'Remote')), |
| 725 |
'Remote'))]) |
self.nvd_text]) |
| 726 |
|
|
| 727 |
|
def page_status_release_unstable(self, path, params, url): |
| 728 |
|
return self.page_status_release_unstable_like( |
| 729 |
|
path, params, url, |
| 730 |
|
title='Vulnerable source packages in the unstable suite', |
| 731 |
|
rel='sid') |
| 732 |
|
|
| 733 |
|
def page_status_release_stable_backports(self, path, params, url): |
| 734 |
|
return self.page_status_release_unstable_like( |
| 735 |
|
path, params, url, |
| 736 |
|
title='Vulnerable source packages among backports for stable', |
| 737 |
|
rel='lenny-backports') |
| 738 |
|
|
| 739 |
|
def page_status_release_oldstable_backports(self, path, params, url): |
| 740 |
|
return self.page_status_release_unstable_like( |
| 741 |
|
path, params, url, |
| 742 |
|
title='Vulnerable source packages among backports for oldstable', |
| 743 |
|
rel='etch-backports') |
| 744 |
|
|
| 745 |
def page_status_dtsa_candidates(self, path, params, url): |
def page_status_dtsa_candidates(self, path, params, url): |
| 746 |
bf = BugFilter(params) |
bf = BugFilter(params) |
| 747 |
|
|
| 748 |
def gen(): |
def gen(): |
| 749 |
old_pkg_name = '' |
old_pkg_name = '' |
| 750 |
for (pkg_name, bug_name, archive, urgency, stable_later, |
for (pkg_name, bug_name, archive, urgency, vulnerable, |
| 751 |
remote) \ |
stable_later, remote) \ |
| 752 |
in self.db.cursor().execute( |
in self.db.cursor().execute( |
| 753 |
"""SELECT package, bug, section, urgency, |
"""SELECT package, bug, section, urgency, vulnerable, |
| 754 |
(SELECT testing.version_id < stable.version_id |
(SELECT testing.version_id < stable.version_id |
| 755 |
FROM source_packages AS testing, source_packages AS stable |
FROM source_packages AS testing, source_packages AS stable |
| 756 |
WHERE testing.name = testing_status.package |
WHERE testing.name = testing_status.package |
| 757 |
AND testing.release = 'etch' |
AND testing.release = 'squeeze' |
| 758 |
AND testing.subrelease = '' |
AND testing.subrelease = '' |
| 759 |
AND testing.archive = testing_status.section |
AND testing.archive = testing_status.section |
| 760 |
AND stable.name = testing_status.package |
AND stable.name = testing_status.package |
| 761 |
AND stable.release = 'sarge' |
AND stable.release = 'lenny' |
| 762 |
AND stable.subrelease = 'security' |
AND stable.subrelease = 'security' |
| 763 |
AND stable.archive = testing_status.section), |
AND stable.archive = testing_status.section), |
| 764 |
(SELECT range_remote FROM nvd_data |
(SELECT range_remote FROM nvd_data |
| 766 |
FROM testing_status |
FROM testing_status |
| 767 |
WHERE (NOT unstable_vulnerable) |
WHERE (NOT unstable_vulnerable) |
| 768 |
AND (NOT testing_security_fixed)"""): |
AND (NOT testing_security_fixed)"""): |
| 769 |
if bf.urgencyFiltered(urgency): |
if bf.urgencyFiltered(urgency, vulnerable): |
| 770 |
continue |
continue |
| 771 |
if bf.remoteFiltered(remote): |
if bf.remoteFiltered(remote): |
| 772 |
continue |
continue |
| 784 |
pkg_name = self.make_source_package_ref(url, pkg_name) |
pkg_name = self.make_source_package_ref(url, pkg_name) |
| 785 |
|
|
| 786 |
if remote is None: |
if remote is None: |
| 787 |
remote = '' |
remote = '???' |
| 788 |
elif remote: |
elif remote: |
| 789 |
remote = 'yes' |
remote = 'yes' |
| 790 |
else: |
else: |
| 791 |
remote = 'no' |
remote = 'no' |
| 792 |
|
|
| 793 |
if urgency == 'unknown': |
if urgency.startswith('high'): |
|
urgency = '' |
|
|
elif urgency == 'high': |
|
| 794 |
urgency = self.make_red(urgency) |
urgency = self.make_red(urgency) |
| 795 |
|
elif vulnerable == 2: |
| 796 |
|
urgency = self.make_purple(urgency) |
| 797 |
|
|
| 798 |
if stable_later: |
if stable_later: |
| 799 |
notes = "(fixed in stable?)" |
notes = "(fixed in stable?)" |
| 811 |
make_menu(url.scriptRelative, |
make_menu(url.scriptRelative, |
| 812 |
("status/release/testing", |
("status/release/testing", |
| 813 |
"List of vulnerable packages in testing")), |
"List of vulnerable packages in testing")), |
| 814 |
bf.actions(url), |
bf.actions(url), BR(), |
| 815 |
make_table(gen(), |
make_table(gen(), |
| 816 |
caption=("Package", "Migration", "Bug", "Urgency", |
caption=("Package", "Migration", "Bug", "Urgency", |
| 817 |
"Remote"))]) |
"Remote"))]) |
| 818 |
|
|
| 819 |
def page_status_todo(self, path, params, url): |
def page_status_todo(self, path, params, url): |
| 820 |
|
hide_check = params.get('hide_check', False) |
| 821 |
|
if hide_check: |
| 822 |
|
flags = A(url.updateParamsDict({'hide_check' : None}), |
| 823 |
|
'Show "check" TODOs') |
| 824 |
|
else: |
| 825 |
|
flags = A(url.updateParamsDict({'hide_check' : '1'}), |
| 826 |
|
'Hide "check" TODOs') |
| 827 |
|
|
| 828 |
def gen(): |
def gen(): |
| 829 |
for (bug, description) in self.db.getTODOs(): |
for (bug, description) in self.db.getTODOs(hide_check=hide_check): |
| 830 |
yield self.make_xref(url, bug), description |
yield self.make_xref(url, bug), description |
| 831 |
return self.create_page( |
return self.create_page( |
| 832 |
url, "Bugs with TODO items", |
url, "Bugs with TODO items", |
| 833 |
[make_table(gen(), |
[P(flags), make_table(gen(), caption=("Bug", "Description"))]) |
| 834 |
caption=("Bug", "Description"))]) |
|
| 835 |
|
def page_status_undetermined(self, path, params, url): |
| 836 |
|
def gen(): |
| 837 |
|
outrel = [] |
| 838 |
|
old_bug = '' |
| 839 |
|
old_pkg = '' |
| 840 |
|
old_dsc = '' |
| 841 |
|
last_displayed = '' |
| 842 |
|
releases = ('sid', 'squeeze', 'lenny', 'etch') |
| 843 |
|
for (pkg_name, bug_name, release, desc) in self.db.cursor().execute( |
| 844 |
|
"""SELECT DISTINCT sp.name, st.bug_name, sp.release, |
| 845 |
|
bugs.description |
| 846 |
|
FROM source_package_status AS st, source_packages AS sp, bugs |
| 847 |
|
WHERE st.vulnerable == 2 AND sp.rowid = st.package |
| 848 |
|
AND ( sp.release = ? OR sp.release = ? OR sp.release = ? |
| 849 |
|
OR sp.release = ? ) |
| 850 |
|
AND sp.subrelease = '' AND st.bug_name == bugs.name |
| 851 |
|
ORDER BY sp.name, st.bug_name""", releases): |
| 852 |
|
|
| 853 |
|
if old_bug == '': |
| 854 |
|
old_bug = bug_name |
| 855 |
|
old_pkg = pkg_name |
| 856 |
|
old_dsc = desc |
| 857 |
|
elif old_bug != bug_name: |
| 858 |
|
if old_pkg == last_displayed: |
| 859 |
|
to_display = '' |
| 860 |
|
else: |
| 861 |
|
to_display = old_pkg |
| 862 |
|
yield to_display, self.make_xref(url, old_bug), old_dsc, ', '.join(outrel) |
| 863 |
|
last_displayed = old_pkg |
| 864 |
|
old_bug = bug_name |
| 865 |
|
old_pkg = pkg_name |
| 866 |
|
old_dsc = desc |
| 867 |
|
outrel = [] |
| 868 |
|
outrel.append( release ) |
| 869 |
|
yield old_pkg, self.make_xref(url, old_bug), old_dsc, ', '.join(outrel) |
| 870 |
|
|
| 871 |
|
return self.create_page(url, 'Packages that may be vulnerable but need to be checked (undetermined issues)', |
| 872 |
|
[P("""This page lists packages that may or may not be affected |
| 873 |
|
by known issues. This means that some additional work needs to |
| 874 |
|
be done to determined whether the package is actually |
| 875 |
|
vulnerable or not. This list is a good area for new |
| 876 |
|
contributors to make quick and meaningful contributions."""), |
| 877 |
|
make_table(gen(), caption=('Package', 'Bug', 'Description', 'Releases'))]) |
| 878 |
|
|
| 879 |
|
def page_status_unimportant(self, path, params, url): |
| 880 |
|
def gen(): |
| 881 |
|
outrel = [] |
| 882 |
|
old_bug = '' |
| 883 |
|
old_pkg = '' |
| 884 |
|
old_dsc = '' |
| 885 |
|
old_name = '' |
| 886 |
|
last_displayed = '' |
| 887 |
|
releases = ('sid', 'squeeze', 'lenny', 'etch') |
| 888 |
|
for (pkg_name, bug_name, release, desc) in self.db.cursor().execute( |
| 889 |
|
"""SELECT DISTINCT sp.name, st.bug_name, sp.release, |
| 890 |
|
bugs.description |
| 891 |
|
FROM source_package_status AS st, source_packages AS sp, bugs |
| 892 |
|
WHERE st.vulnerable > 0 AND sp.rowid = st.package |
| 893 |
|
AND ( sp.release = ? OR sp.release = ? OR sp.release = ? |
| 894 |
|
OR sp.release = ? ) AND st.urgency == 'unimportant' |
| 895 |
|
AND sp.subrelease = '' AND st.bug_name == bugs.name |
| 896 |
|
ORDER BY sp.name, st.bug_name""", releases): |
| 897 |
|
|
| 898 |
|
if old_bug == '': |
| 899 |
|
old_bug = bug_name |
| 900 |
|
old_pkg = pkg_name |
| 901 |
|
old_dsc = desc |
| 902 |
|
elif old_bug != bug_name: |
| 903 |
|
if old_pkg == last_displayed: |
| 904 |
|
to_display = '' |
| 905 |
|
else: |
| 906 |
|
to_display = old_pkg |
| 907 |
|
yield to_display, self.make_xref(url, old_bug), old_dsc, ', '.join(outrel) |
| 908 |
|
last_displayed = old_pkg |
| 909 |
|
old_bug = bug_name |
| 910 |
|
old_pkg = pkg_name |
| 911 |
|
old_dsc = desc |
| 912 |
|
outrel = [] |
| 913 |
|
outrel.append( release ) |
| 914 |
|
yield old_pkg, self.make_xref(url, old_bug), old_dsc, ', '.join(outrel) |
| 915 |
|
|
| 916 |
|
return self.create_page(url, 'Packages that have open unimportant issues', |
| 917 |
|
[P("""This page lists packages that are affected by issues |
| 918 |
|
that are considered unimportant from a security perspective. |
| 919 |
|
These issues are thought to be unexploitable or uneffective |
| 920 |
|
in most situations (for example, browser denial-of-services)."""), |
| 921 |
|
make_table(gen(), caption=('Package', 'Bug', 'Description', 'Releases'))]) |
| 922 |
|
|
| 923 |
def page_status_itp(self, path, params, url): |
def page_status_itp(self, path, params, url): |
| 924 |
def gen(): |
def gen(): |
| 943 |
url, "Unknown packages", |
url, "Unknown packages", |
| 944 |
[P("""Sometimes, a package referenced in a bug report |
[P("""Sometimes, a package referenced in a bug report |
| 945 |
cannot be found in the database. This can be the result of a spelling |
cannot be found in the database. This can be the result of a spelling |
| 946 |
return web_supporterror, or a historic entry refers to a |
error, or a historic entry refers to a |
| 947 |
return web_supportpackage which is no longer in the archive."""), |
package which is no longer in the archive."""), |
| 948 |
make_table(gen(), caption=("Package", "Bugs"), |
make_table(gen(), caption=("Package", "Bugs"), |
| 949 |
replacement="No unknown packages are referenced in the database.")]) |
replacement="No unknown packages are referenced in the database.")]) |
| 950 |
|
|
| 982 |
caption=("Bug", "Package", "Version 1", "Version 2"), |
caption=("Bug", "Package", "Version 1", "Version 2"), |
| 983 |
replacement="No source package version with missing epochs.")]) |
replacement="No source package version with missing epochs.")]) |
| 984 |
|
|
| 985 |
|
def page_data_latently_vulnerable(self, path, params, url): |
| 986 |
|
def gen(): |
| 987 |
|
for pkg, bugs in self.db.cursor().execute( |
| 988 |
|
"""SELECT package, string_set(bug_name) |
| 989 |
|
FROM package_notes AS p1 |
| 990 |
|
WHERE release <> '' |
| 991 |
|
AND (bug_name LIKE 'CVE-%' OR bug_name LIKE 'TEMP-%') |
| 992 |
|
AND NOT EXISTS (SELECT 1 FROM package_notes AS p2 |
| 993 |
|
WHERE p2.bug_name = p1.bug_name |
| 994 |
|
AND p2.package = p1.package |
| 995 |
|
AND release = '') |
| 996 |
|
AND EXISTS (SELECT 1 FROM source_packages |
| 997 |
|
WHERE name = p1.package AND release = 'sid') |
| 998 |
|
GROUP BY package |
| 999 |
|
ORDER BY package"""): |
| 1000 |
|
pkg = self.make_source_package_ref(url, pkg) |
| 1001 |
|
bugs = bugs.split(',') |
| 1002 |
|
yield pkg, self.make_xref_list(url, bugs) |
| 1003 |
|
|
| 1004 |
|
def gen_unimportant(): |
| 1005 |
|
for pkg, bugs in self.db.cursor().execute( |
| 1006 |
|
"""SELECT package, string_set(bug_name) |
| 1007 |
|
FROM package_notes AS p1 |
| 1008 |
|
WHERE release <> '' |
| 1009 |
|
AND urgency <> 'unimportant' |
| 1010 |
|
AND (bug_name LIKE 'CVE-%' OR bug_name LIKE 'TEMP-%') |
| 1011 |
|
AND EXISTS (SELECT 1 FROM package_notes AS p2 |
| 1012 |
|
WHERE p2.bug_name = p1.bug_name |
| 1013 |
|
AND p2.package = p1.package |
| 1014 |
|
AND release = '') |
| 1015 |
|
AND NOT EXISTS (SELECT 1 FROM package_notes AS p2 |
| 1016 |
|
WHERE p2.bug_name = p1.bug_name |
| 1017 |
|
AND p2.package = p1.package |
| 1018 |
|
AND urgency <> 'unimportant' |
| 1019 |
|
AND release = '') |
| 1020 |
|
AND EXISTS (SELECT 1 FROM source_packages |
| 1021 |
|
WHERE name = p1.package AND release = 'sid') |
| 1022 |
|
GROUP BY package |
| 1023 |
|
ORDER BY package"""): |
| 1024 |
|
pkg = self.make_source_package_ref(url, pkg) |
| 1025 |
|
bugs = bugs.split(',') |
| 1026 |
|
yield pkg, self.make_xref_list(url, bugs) |
| 1027 |
|
|
| 1028 |
|
return self.create_page( |
| 1029 |
|
url, "Latently vulnerable packages in unstable", |
| 1030 |
|
[P( |
| 1031 |
|
"""A package is latently vulnerable in unstable if it is vulnerable in |
| 1032 |
|
any release, and there is no package note for the same vulnerability |
| 1033 |
|
and package in unstable (and the package is still available in |
| 1034 |
|
unstable, of course)."""), |
| 1035 |
|
make_table(gen(), |
| 1036 |
|
caption=("Package", "Bugs"), |
| 1037 |
|
replacement="No latently vulnerable packages were found."), |
| 1038 |
|
P( |
| 1039 |
|
"""The next table lists issues which are marked unimportant for |
| 1040 |
|
unstable, but for which release-specific annotations exist which are |
| 1041 |
|
not unimportant."""), |
| 1042 |
|
make_table(gen_unimportant(), |
| 1043 |
|
caption=("Package", "Bugs"), |
| 1044 |
|
replacement= |
| 1045 |
|
"No packages with unimportant latent vulnerabilities were found."), |
| 1046 |
|
]) |
| 1047 |
|
|
| 1048 |
def page_data_releases(self, path, params, url): |
def page_data_releases(self, path, params, url): |
| 1049 |
def gen(): |
def gen(): |
| 1050 |
for (rel, subrel, archive, sources, archs) \ |
for (rel, subrel, archive, sources, archs) \ |
| 1101 |
a unique name. These names are not stable and can change when the database |
a unique name. These names are not stable and can change when the database |
| 1102 |
is updated, so they should not be used in external references."""), |
is updated, so they should not be used in external references."""), |
| 1103 |
P('''The automatically generated names come in two flavors: |
P('''The automatically generated names come in two flavors: |
| 1104 |
the first kind starts with the string "''', CODE("FAKE-000000-"), |
the first kind starts with the string "''', CODE("TEMP-000000-"), |
| 1105 |
'''". This means that no Debian bug has been assigned to this |
'''". This means that no Debian bug has been assigned to this |
| 1106 |
issue (or a bug has been created and is not recorded in this database). |
issue (or a bug has been created and is not recorded in this database). |
| 1107 |
In the second kind of names, there is a Debian bug for the issue, and the "''', |
In the second kind of names, there is a Debian bug for the issue, and the "''', |
| 1110 |
make_table(gen(), |
make_table(gen(), |
| 1111 |
caption=("Bug", "Description"))]) |
caption=("Bug", "Description"))]) |
| 1112 |
|
|
| 1113 |
|
def page_data_pts(self, path, params, url): |
| 1114 |
|
data = [] |
| 1115 |
|
for pkg, bugs in self.db.cursor().execute( |
| 1116 |
|
"""SELECT package, COUNT(DISTINCT bug) FROM |
| 1117 |
|
(SELECT package, bug, urgency FROM stable_status |
| 1118 |
|
UNION ALL SELECT package, bug, urgency FROM oldstable_status |
| 1119 |
|
UNION ALL SELECT DISTINCT sp.name, st.bug_name, st.urgency |
| 1120 |
|
FROM source_package_status AS st, source_packages AS sp |
| 1121 |
|
WHERE st.vulnerable AND st.urgency <> 'unimportant' |
| 1122 |
|
AND sp.rowid = st.package AND sp.release = 'sid' |
| 1123 |
|
AND sp.subrelease = '') x WHERE urgency <> 'unimportant' |
| 1124 |
|
GROUP BY package ORDER BY package"""): |
| 1125 |
|
data.append(pkg) |
| 1126 |
|
data.append(':') |
| 1127 |
|
data.append(str(bugs)) |
| 1128 |
|
data.append('\n') |
| 1129 |
|
return BinaryResult(''.join(data)) |
| 1130 |
|
|
| 1131 |
|
def page_debsecan(self, path, params, url): |
| 1132 |
|
obj = '/'.join(path) |
| 1133 |
|
data = self.db.getDebsecan(obj) |
| 1134 |
|
if data: |
| 1135 |
|
return BinaryResult(data) |
| 1136 |
|
else: |
| 1137 |
|
return self.create_page( |
| 1138 |
|
url, "Object not found", |
| 1139 |
|
[P("The requested debsecan object has not been found.")], |
| 1140 |
|
status=404) |
| 1141 |
|
|
| 1142 |
def create_page(self, url, title, body, search_in_page=False, status=200): |
def create_page(self, url, title, body, search_in_page=False, status=200): |
| 1143 |
append = body.append |
append = body.append |
| 1144 |
append(HR()) |
append(HR()) |
| 1168 |
onkeyup="onSearch(this.value)", |
onkeyup="onSearch(this.value)", |
| 1169 |
onmousemove="onSearch(this.value)"), |
onmousemove="onSearch(this.value)"), |
| 1170 |
INPUT(type='submit', value='Go'), |
INPUT(type='submit', value='Go'), |
| 1171 |
|
' ', |
| 1172 |
|
A(url.scriptRelative("data/report"), "Reporting problems"), |
| 1173 |
method='get', |
method='get', |
| 1174 |
action=url.scriptRelative('')) |
action=url.scriptRelative('')) |
| 1175 |
|
|
| 1177 |
return url.absolute("http://cve.mitre.org/cgi-bin/cvename.cgi", |
return url.absolute("http://cve.mitre.org/cgi-bin/cvename.cgi", |
| 1178 |
name=name) |
name=name) |
| 1179 |
def url_nvd(self, url, name): |
def url_nvd(self, url, name): |
| 1180 |
return url.absolute("http://nvd.nist.gov/nvd.cfm", |
return url.absolute("http://web.nvd.nist.gov/view/vuln/detail", |
| 1181 |
cvename=name) |
vulnId=name) |
| 1182 |
|
def url_rhbug(self, url, name): |
| 1183 |
|
return url.absolute("https://bugzilla.redhat.com/show_bug.cgi", |
| 1184 |
|
id=name) |
| 1185 |
|
|
| 1186 |
def url_dsa(self, url, dsa, re_dsa=re.compile(r'^DSA-(\d+)(?:-\d+)?$')): |
def url_dsa(self, url, dsa, re_dsa=re.compile(r'^DSA-(\d+)(?:-\d+)?$')): |
| 1187 |
match = re_dsa.match(dsa) |
match = re_dsa.match(dsa) |
| 1205 |
return url.absolute("http://packages.qa.debian.org/common/index.html", |
return url.absolute("http://packages.qa.debian.org/common/index.html", |
| 1206 |
src=package) |
src=package) |
| 1207 |
def url_testing_status(self, url, package): |
def url_testing_status(self, url, package): |
| 1208 |
return url.absolute("http://bjorn.haxx.se/debian/testing.pl", |
return url.absolute("http://release.debian.org/migration/testing.pl", |
| 1209 |
package=package) |
package=package) |
| 1210 |
def url_source_package(self, url, package, full=False): |
def url_source_package(self, url, package, full=False): |
| 1211 |
if full: |
if full: |
| 1212 |
return url.scriptRelativeFull("source-package/" + package) |
return url.scriptRelativeFull("source-package/" + package) |
| 1213 |
else: |
else: |
| 1214 |
return url.scriptRelative("source-package/" + package) |
return url.scriptRelative("source-package/" + package) |
|
def url_binary_package(self, url, package, full=False): |
|
|
if full: |
|
|
return url.scriptRelativeFull("binary-package/" + package) |
|
|
else: |
|
|
return url.scriptRelative("binary-package/" + package) |
|
| 1215 |
|
|
| 1216 |
def make_xref(self, url, name): |
def make_xref(self, url, name): |
| 1217 |
return A(url.scriptRelative(name), name) |
return A(url.scriptRelative(name), name) |
| 1233 |
if name is None: |
if name is None: |
| 1234 |
name = cve |
name = cve |
| 1235 |
return A(self.url_nvd(url, cve), name) |
return A(self.url_nvd(url, cve), name) |
| 1236 |
|
|
| 1237 |
|
def make_rhbug_ref(self, url, cve, name=None): |
| 1238 |
|
if name is None: |
| 1239 |
|
name = cve |
| 1240 |
|
return A(self.url_rhbug(url, cve), name) |
| 1241 |
|
|
| 1242 |
def make_dsa_ref(self, url, dsa, name=None): |
def make_dsa_ref(self, url, dsa, name=None): |
| 1243 |
if name is None: |
if name is None: |
| 1257 |
if title is None: |
if title is None: |
| 1258 |
title = pkg |
title = pkg |
| 1259 |
return A(self.url_source_package(url, pkg), title) |
return A(self.url_source_package(url, pkg), title) |
|
def make_binary_package_ref(self, url, pkg, title=None): |
|
|
if title is None: |
|
|
title = pkg |
|
|
return A(self.url_binary_package(url, pkg), title) |
|
|
def make_binary_packages_ref(self, url, lst): |
|
|
assert type(lst) <> types.StringType |
|
|
return make_list(map(lambda x: self.make_binary_package_ref(url, x), |
|
|
lst)) |
|
| 1260 |
|
|
| 1261 |
def make_red(self, contents): |
def make_red(self, contents): |
| 1262 |
return SPAN(contents, _class="red") |
return SPAN(contents, _class="red") |
| 1263 |
|
|
| 1264 |
|
def make_purple(self, contents): |
| 1265 |
|
return SPAN(contents, _class="purple") |
| 1266 |
|
|
| 1267 |
def make_dangerous(self, contents): |
def make_dangerous(self, contents): |
| 1268 |
return SPAN(contents, _class="dangerous") |
return SPAN(contents, _class="dangerous") |