/[secure-testing]/bin/tracker_service.py
ViewVC logotype

Contents of /bin/tracker_service.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3166 - (hide annotations) (download) (as text)
Tue Dec 27 15:08:37 2005 UTC (7 years, 4 months ago) by fw
File MIME type: text/script
File size: 45594 byte(s)
bin/tracker_service.py (TrackerService.page_data_latently_vulnerable):
  Report on "unimportant" urgency.
1 fw 2482 #!/usr/bin/python
2    
3     import sys
4     sys.path.insert(0,'../lib/python')
5    
6     if len(sys.argv) <> 3:
7     print "usage: python tracker_serivce.py SOCKET-PATH DATABASE-PATH"
8     sys.exit(1)
9     socket_name = sys.argv[1]
10     db_name = sys.argv[2]
11    
12     import bugs
13     import re
14     import security_db
15     from web_support import *
16    
17 fw 2491 class BugFilter:
18     def __init__(self, params):
19     self.hide_medium_urgency = int(params.get('hide_medium_urgency',
20     (0,))[0])
21     self.hide_non_remote = int(params.get('hide_non_remote',
22     (0,))[0])
23    
24     def actions(self, url):
25     """Returns a HTML snippet which can be used to change the filter."""
26     if self.hide_medium_urgency:
27     urg = A(url.updateParams(hide_medium_urgency=None),
28     'Show lower urgencies')
29     else:
30     urg = A(url.updateParams(hide_medium_urgency='1'),
31     'Hide lower urgencies')
32     if self.hide_non_remote:
33     rem = A(url.updateParams(hide_non_remote=None),
34     'Show local vulnerabilities')
35     else:
36     rem = A(url.updateParams(hide_non_remote='1'),
37     'Hide local vulnerabilities')
38     return P(urg, ' ', rem)
39    
40     def urgencyFiltered(self, urg):
41     """Returns True if the urgency urg is filtered."""
42     return self.hide_medium_urgency and urg not in ("high", "unknown", "")
43    
44     def remoteFiltered(self, remote):
45     """Returns True if the attack range is filtered."""
46     return remote is not None and self.hide_non_remote and not remote
47    
48 fw 2482 class TrackerService(WebService):
49     head_contents = compose(STYLE(
50     """h1 { font-size : 144%; }
51     h2 { font-size : 120%; }
52     h3 { font-size : 100%; }
53    
54     table { padding-left : 1.5em }
55     td, th { text-align : left;
56     padding-left : 0.25em;
57     padding-right : 0.25em; }
58     td { vertical-align: baseline }
59     span.red { color: red; }
60     span.dangerous { color: rgb(191,127,0); }
61     """), SCRIPT('''var old_query_value = "";
62    
63     function selectSearch() {
64     document.searchForm.query.focus();
65     }
66    
67     function onSearch(query) {
68     if (old_query_value == "") {
69     if (query.length > 5) {
70     old_query_value = query;
71     document.searchForm.submit();
72     } else {
73     old_query_value = query;
74     }
75     }
76     }
77     ''')).toHTML()
78    
79     def __init__(self, socket_name, db_name):
80     WebService.__init__(self, socket_name)
81     self.db = security_db.DB(db_name)
82     self.register('', self.page_home)
83     self.register('*', self.page_object)
84 fw 2485 self.register('redirect/*', self.page_redirect)
85 fw 2482 self.register('source-package/*', self.page_source_package)
86     self.register('binary-package/*', self.page_binary_package)
87 fw 3069 self.register('status/release/oldstable',
88     self.page_status_release_oldstable)
89 fw 2482 self.register('status/release/stable', self.page_status_release_stable)
90     self.register('status/release/testing',
91     self.page_status_release_testing)
92     self.register('status/release/unstable',
93     self.page_status_release_unstable)
94     self.register('status/dtsa-candidates',
95     self.page_status_dtsa_candidates)
96     self.register('status/todo', self.page_status_todo)
97     self.register('status/itp', self.page_status_itp)
98     self.register('data/unknown-packages', self.page_data_unknown_packages)
99     self.register('data/missing-epochs', self.page_data_missing_epochs)
100 fw 3136 self.register('data/latently-vulnerable',
101     self.page_data_latently_vulnerable)
102 fw 2482 self.register('data/releases', self.page_data_releases)
103     self.register('data/funny-versions', self.page_data_funny_versions)
104 fw 2554 self.register('data/fake-names', self.page_data_fake_names)
105 fw 3051 self.register('debsecan/**', self.page_debsecan)
106 fw 2482
107     def page_home(self, path, params, url):
108     query = params.get('query', ('',))[0]
109     if query:
110     if '/' in query:
111     return self.page_not_found(url, query)
112     else:
113     return RedirectResult(url.scriptRelativeFull(query))
114    
115     return self.create_page(
116     url, 'Security Bug Tracker',
117     [P(
118     """This is the experimental issue tracker for Debian's testing
119     security team. Keep in mind that this is merely a prototype.
120     Please report any problems to """,
121     A("mailto:fw@deneb.enyo.de", "Florian Weimer"),
122     """.Note that some of the data presented here is known
123     to be wrong (see below), but the data for the testing suite
124     should be fine."""),
125     make_menu(
126     url.scriptRelative,
127 fw 3071 ('status/release/unstable',
128     'Vulnerable packages in the unstable suite'),
129     ('status/release/testing',
130     'Vulnerable packages in the testing suite'),
131 fw 2482 ('status/release/stable',
132     'Vulnerable packages in the stable suite'),
133 fw 3071 ('status/release/oldstable',
134     'Vulnerable packages in the oldstable suite'),
135 fw 2482 ('status/dtsa-candidates', "Candidates for DTSAs"),
136     ('status/todo', 'TODO items'),
137     ('status/itp', 'ITPs with potential security issues'),
138     ('data/unknown-packages',
139     'Packages names not found in the archive'),
140 fw 2554 ('data/fake-names', 'Tracked issues without a CVE name'),
141 fw 2482 ('data/missing-epochs',
142     'Package versions which might lack an epoch'),
143 fw 3136 ('data/latently-vulnerable',
144     'Packages which are latently vulnerable in unstable'),
145 fw 2482 ('data/funny-versions',
146     'Packages with strange version numbers'),
147     ('data/releases',
148     'Covered Debian releases and architectures (slow)'),
149     self.make_search_button(url)),
150 fw 2495 P("""(You can enter CVE names, Debian bug numbers and package
151 fw 2488 names in the search forms.)"""),
152 fw 2482
153 fw 2489 H2("Data sources"),
154 fw 2482 P("""Data in this tracker comes solely from the bug database
155     which is maintained by Debian's testing security team in their
156     Subversion repository. All external data (this includes
157     Debian bug reports and official Debian security advisories)
158     must be added to this database before it appears here, and there
159     can be some delay before this happens."""),
160     P("""At the moment, the database only contains information which is
161     relevant for tracking the security status of the stable, testing and
162 fw 2488 unstable suites. This means that data for oldstable is likely wrong."""),
163 fw 2489 P('Data marked "NVD" comes from the ',
164     A(url.absolute('http://nvd.nist.gov/'),
165     'National Vulnerability Database'),
166     ' maintained by NIST.'),
167 fw 2488
168     H2("External interfaces"),
169     P("""If you want to automatically open a relevant web page for
170     some object, use the """,
171     CODE(str(url.scriptRelative("redirect/")), EM("object")),
172     """ URL. If no information is contained in this database,
173     the browser is automatically redirected to the corresponding external
174     data source.""")],
175 fw 2482 search_in_page=True)
176    
177     def page_object(self, path, params, url):
178     obj = path[0]
179 fw 2485 return self.page_object_or_redirect(url, obj, False)
180 fw 2482
181 fw 2485 def page_redirect(self, path, params, url):
182     obj = path[0]
183     return self.page_object_or_redirect(url, obj, True)
184    
185     def page_object_or_redirect(self, url, obj, redirect):
186     c = self.db.cursor()
187    
188 fw 2482 if not obj:
189     # Redirect to start page.
190     return RedirectResult(url.scriptRelativeFull(""))
191    
192     if 'A' <= obj[0] <= 'Z':
193     # Bug names start with a capital letter.
194 fw 2485 return self.page_bug(url, obj, redirect)
195 fw 2482
196     bugnumber = 0
197     try:
198     bugnumber = int(obj)
199     except ValueError:
200     pass
201     if bugnumber:
202 fw 2485 buglist = list(self.db.getBugsFromDebianBug(c, bugnumber))
203     if buglist:
204     return self.page_debian_bug(url, bugnumber, buglist)
205     if redirect:
206     return RedirectResult(self.url_debian_bug(url, str(bugnumber)),
207     permanent=False)
208 fw 2482
209     if self.db.isSourcePackage(c, obj):
210     return RedirectResult(self.url_source_package(url, obj, full=True))
211     if self.db.isBinaryPackage(c, obj):
212     return RedirectResult(self.url_binary_package(url ,obj, full=True))
213    
214     return self.page_not_found(url, obj)
215    
216 fw 2485 def page_bug(self, url, name, redirect):
217 fw 2511 # FIXME: Normalize CAN-* to CVE-* when redirecting. Too many
218     # people still use CAN.
219     if redirect and name[0:4] == 'CAN-':
220     name = 'CVE-' + name[4:]
221    
222 fw 2482 cursor = self.db.cursor()
223     try:
224     bug = bugs.BugFromDB(cursor, name)
225     except ValueError:
226 fw 2485 if redirect:
227 fw 2495 if name[0:4] == 'CVE-':
228 fw 2485 return RedirectResult(self.url_cve(url, name),
229     permanent=False)
230 fw 2482 return self.page_not_found(url, name)
231 fw 2485 if bug.name <> name or redirect:
232 fw 2482 # Show the normalized bug name in the browser address bar.
233     return RedirectResult(url.scriptRelativeFull(bug.name))
234    
235     page = []
236    
237     def gen_header():
238     yield B("Name"), bug.name
239    
240     source = bug.name.split('-')[0]
241 fw 2495 if source == 'CVE':
242 fw 2488 source_xref = compose(self.make_cve_ref(url, bug.name, 'CVE'),
243     " (",
244     self.make_nvd_ref(url, bug.name,
245     'in NVD'),
246     ")")
247 fw 2482 elif source == 'DSA':
248     source_xref = self.make_dsa_ref(url, bug.name, 'Debian')
249     elif source == 'DTSA':
250     source_xref = 'Debian Testing Security Team'
251     elif source == 'FAKE':
252     source_xref = (
253     'Automatically generated temporary name. Not for external reference.')
254     else:
255     source_xref = None
256    
257     if source_xref:
258     yield B("Source"), source_xref
259    
260 fw 3078 nvd = self.db.getNVD(cursor, bug.name)
261    
262     if nvd and nvd.cve_desc:
263     yield B("Description"), nvd.cve_desc
264     elif bug.description:
265 fw 2482 yield B("Description"), bug.description
266    
267     xref = list(self.db.getBugXrefs(cursor, bug.name))
268     if xref:
269     yield B("References"), self.make_xref_list(url, xref)
270 fw 2488
271     if nvd:
272 fw 3079 nvd_range = nvd.rangeString()
273 fw 2488 if nvd.severity:
274 fw 3079 nvd_severity = nvd.severity.lower()
275     if nvd_range:
276     nvd_severity = "%s (attack range: %s)" \
277     % (nvd_severity, nvd_range)
278     yield B("NVD severity"), nvd_severity
279 fw 2482
280     debian_bugs = bug.getDebianBugs(cursor)
281     if debian_bugs:
282     yield (B("Debian Bugs"),
283     self.make_debian_bug_list(url, debian_bugs))
284    
285     if not bug.not_for_us:
286     for (release, status, reason) in bug.getStatus(cursor):
287     if status <> 'fixed':
288     reason = self.make_red(reason)
289 fw 3080 yield B('Debian/%s' % release), reason
290 fw 2482
291     page.append(make_table(gen_header()))
292    
293     if bug.notes:
294     page.append(H2("Vulnerable and fixed packages"))
295    
296     def gen_source():
297     old_pkg = ''
298     for (package, release, version, vulnerable) \
299     in self.db.getSourcePackages(cursor, bug.name):
300     if package == old_pkg:
301     package = ''
302     else:
303     old_pkg = package
304     package = compose(
305     self.make_source_package_ref(url, package),
306     " (", self.make_pts_ref(url, package, 'PTS'), ")")
307     if vulnerable:
308     vuln = self.make_red('vulnerable')
309     version = self.make_red(version)
310     else:
311     vuln = 'fixed'
312    
313     yield package, ', '.join(release), version, vuln
314    
315     page.append(make_table(gen_source(),
316     caption=("Source Package", "Release", "Version", "Status"),
317     introduction=P('The table below lists information on source packages.')))
318    
319     def gen_binary():
320     old_pkg = ''
321     for (packages, releases, version, archs, vulnerable) \
322     in self.db.getBinaryPackages(cursor, bug.name):
323     pkg = ', '.join(packages)
324     if pkg == old_pkg:
325     packages = ''
326     else:
327     old_pkg = pkg
328     packages = self.make_binary_packages_ref(url, packages)
329    
330     if vulnerable:
331     vuln = self.make_red('vulnerable')
332     version = self.make_red(version)
333     else:
334     vuln = 'fixed'
335     yield (packages,
336     ', '.join(releases),
337     version, vuln,
338     ', '.join(archs))
339    
340     page.append(make_table(gen_binary(),
341     caption=("Binary Package", "Release", "Version", "Status",
342     "Architecures"),
343     introduction=P("The next table lists affected binary packages.")))
344    
345     def gen_data():
346     notes_sorted = bug.notes[:]
347     notes_sorted.sort(lambda a, b: cmp(a.package, b.package))
348     for n in notes_sorted:
349     if n.release:
350     rel = str(n.release)
351     else:
352     rel = '(unstable)'
353     urgency = str(n.urgency)
354     if n.fixed_version:
355     ver = str(n.fixed_version)
356     if ver == '0':
357     ver = '(not affected)'
358     urgency = ''
359     else:
360     ver = self.make_red('(unfixed)')
361    
362     pkg = n.package
363     pkg_kind = n.package_kind
364     if pkg_kind == 'source':
365     pkg = self.make_source_package_ref(url, pkg)
366     elif pkg_kind == 'binary':
367     pkg = self.make_binary_package_ref(url, pkg)
368     elif pkg_kind == 'itp':
369     pkg_kind = 'ITP'
370     rel = ''
371     ver = ''
372     urgency = ''
373    
374     bugs = n.bugs
375     bugs.sort()
376     bugs = make_list(
377     map(lambda x: self.make_debian_bug(url, x), bugs))
378     if n.bug_origin:
379     origin = self.make_xref(url, n.bug_origin)
380     else:
381     origin = ''
382     yield (pkg, pkg_kind, rel, ver, urgency, origin, bugs)
383    
384     page.append(
385     make_table(gen_data(),
386     caption=("Package", "Type", "Release", "Fixed Version",
387     "Urgency", "Origin", "Debian Bugs"),
388     introduction=P("The information above is based on the following data on fixed versions.")))
389    
390     if bug.comments:
391     page.append(H2("Notes"))
392     def gen_comments():
393     for (t, c) in bug.comments:
394     yield c
395     page.append(make_pre(gen_comments()))
396    
397     return self.create_page(url, bug.name, page)
398    
399 fw 2485 def page_debian_bug(self, url, bugnumber, buglist):
400     if len(buglist) == 1:
401     # Single issue, redirect.
402     return RedirectResult(url.scriptRelativeFull(buglist[0][0]))
403 fw 2482
404 fw 2485 def gen():
405     for (name, urgency, description) in buglist:
406     if urgency == "unknown":
407     urgency = ""
408     yield self.make_xref(url, name), urgency, description
409 fw 2482
410 fw 2485 return self.create_page(
411     url, "Information related to Debian bug #%d" % bugnumber,
412     [P("The following issues reference to Debian bug ",
413     self.make_debian_bug(url, bugnumber), ":"),
414     make_table(gen(),
415     caption=("Name", "Urgency", "Description"))])
416 fw 2482
417     def page_not_found(self, url, query):
418     return self.create_page(url, 'Not found',
419     [P('Your query ',
420     CODE(query),
421     ' matched no results.')],
422     status=404)
423    
424     def page_source_package(self, path, params, url):
425     pkg = path[0]
426    
427     def gen_versions():
428     for (releases, version) in self.db.getSourcePackageVersions(
429     self.db.cursor(), pkg):
430     yield ', '.join(releases), version
431     def gen_binary():
432     for (packages, releases, archs, version) \
433     in self.db.getBinaryPackagesForSource(
434     self.db.cursor(), pkg):
435     yield (self.make_binary_packages_ref(url, packages),
436     ', '.join(releases), version, ', '.join(archs))
437     def gen_bug_list(lst):
438     for (bug, description) in lst:
439     yield self.make_xref(url, bug), description
440    
441     return self.create_page(
442     url, "Information on source package " + pkg,
443     [make_menu(lambda x: x,
444     (self.url_pts(url, pkg),
445     pkg + ' in the Package Tracking System'),
446     (self.url_debian_bug_pkg(url, pkg),
447     pkg + ' in the Bug Tracking System'),
448     (self.url_testing_status(url, pkg),
449     pkg + ' in the testing migration checker')),
450     H2("Available versions"),
451     make_table(gen_versions(), caption=("Release", "Version")),
452    
453     H2("Available binary packages"),
454     make_table(gen_binary(),
455     caption=('Package', 'Release', 'Version', 'Architectures'),
456     replacement="""No binary packages are recorded in this database.
457     This probably means that the package is architecture-specific, and the
458     architecture is currently not tracked."""),
459    
460     H2("Open issues"),
461     make_table(gen_bug_list(self.db.getBugsForSourcePackage
462     (self.db.cursor(), pkg, True)),
463     caption=('Bug', 'Description'),
464     replacement='No known open issues.'),
465    
466     H2("Resolved issues"),
467     make_table(gen_bug_list(self.db.getBugsForSourcePackage
468     (self.db.cursor(), pkg, False)),
469     caption=('Bug', 'Description'),
470     replacement='No known resolved issues.')])
471    
472     def page_binary_package(self, path, params, url):
473     pkg = path[0]
474    
475     def gen_versions():
476     for (releases, source, version, archs) \
477     in self.db.getBinaryPackageVersions(self.db.cursor(), pkg):
478     yield (', '.join(releases),
479     self.make_source_package_ref(url, source),
480     version, ', '.join(archs))
481     def gen_bug_list(lst):
482     for (bug, description) in lst:
483     yield self.make_xref(url, bug), description
484    
485     return self.create_page(
486     url, "Information on binary package " + pkg,
487     [make_menu(lambda x: x,
488     (self.url_debian_bug_pkg(url, pkg),
489     pkg + ' in the Bug Tracking System')),
490     H2("Available versions"),
491     make_table(gen_versions(),
492     caption=("Release", "Source", "Version", "Architectures")),
493    
494     H2("Open issues"),
495     make_table(gen_bug_list(self.db.getBugsForBinaryPackage
496     (self.db.cursor(), pkg, True)),
497     caption=('Bug', 'Description'),
498     replacement='No known open issues.'),
499    
500     H2("Resolved issues"),
501     make_table(gen_bug_list(self.db.getBugsForBinaryPackage
502     (self.db.cursor(), pkg, False)),
503     caption=('Bug', 'Description'),
504     replacement='No known resolved issues.'),
505    
506     H2("Non-issues"),
507     make_table(gen_bug_list(self.db.getNonBugsForBinaryPackage
508     (self.db.cursor(), pkg)),
509     caption=('Bug', 'Description'),
510     replacement="""No known issues which do not affect
511     this package, but still reference it.""")])
512    
513 fw 3069 def page_status_release_stable_oldstable(self, release, params, url):
514     assert release in ('stable', 'oldstable')
515    
516 fw 2491 bf = BugFilter(params)
517    
518 fw 2482 def gen():
519     old_pkg_name = ''
520 fw 2488 for (pkg_name, bug_name, archive, urgency, remote) in \
521 fw 2482 self.db.cursor().execute(
522 fw 2488 """SELECT package, bug, section, urgency, remote
523 fw 3069 FROM %s_status""" % release):
524 fw 2491 if bf.urgencyFiltered(urgency):
525     continue
526     if bf.remoteFiltered(remote):
527     continue
528    
529 fw 2482 if pkg_name == old_pkg_name:
530     pkg_name = ''
531     else:
532     old_pkg_name = pkg_name
533     if archive <> 'main':
534     pkg_name = "%s (%s)" % (pkg_name, archive)
535    
536 fw 2488 if remote is None:
537     remote = ''
538     elif remote:
539     remote = 'yes'
540     else:
541     remote = 'no'
542    
543 fw 2482 if urgency == 'unknown':
544     urgency = ''
545     elif urgency == 'high':
546     urgency = self.make_red(urgency)
547    
548 fw 2488 yield pkg_name, self.make_xref(url, bug_name), urgency, remote
549 fw 2482
550     return self.create_page(
551 fw 3069 url, 'Vulnerable source packages in the %s suite' % release,
552 fw 2491 [bf.actions(url),
553     make_table(gen(), caption=("Package", "Bug", "Urgency",
554 fw 2488 "Remote"))])
555 fw 3069
556     def page_status_release_stable(self, path, params, url):
557     return self.page_status_release_stable_oldstable('stable', params, url)
558     def page_status_release_oldstable(self, path, params, url):
559     return self.page_status_release_stable_oldstable('oldstable',
560     params, url)
561 fw 2482
562     def page_status_release_testing(self, path, params, url):
563 fw 2491 bf = BugFilter(params)
564    
565 fw 2482 def gen():
566     old_pkg_name = ''
567     for (pkg_name, bug_name, archive, urgency,
568 fw 2488 sid_vulnerable, ts_fixed, remote) in self.db.cursor().execute(
569 fw 2482 """SELECT package, bug, section, urgency, unstable_vulnerable,
570 fw 2488 testing_security_fixed, remote
571 fw 2482 FROM testing_status"""):
572 fw 2491 if bf.urgencyFiltered(urgency):
573     continue
574     if bf.remoteFiltered(remote):
575     continue
576    
577 fw 2482 if pkg_name == old_pkg_name:
578     pkg_name = ''
579     else:
580     old_pkg_name = pkg_name
581     if archive <> 'main':
582     pkg_name = "%s (%s)" % (pkg_name, archive)
583    
584 fw 2488 if remote is None:
585     remote = ''
586     elif remote:
587     remote = 'yes'
588     else:
589     remote = 'no'
590    
591 fw 2482 if ts_fixed:
592     status = 'fixed in testing-security'
593     else:
594     if sid_vulnerable:
595     status = self.make_red('unstable is vulnerable')
596     else:
597     status = self.make_dangerous('fixed in unstable')
598    
599     if urgency == 'unknown':
600     urgency = ''
601    
602     yield (pkg_name, self.make_xref(url, bug_name),
603 fw 2488 urgency, remote, status)
604 fw 2482
605     return self.create_page(
606     url, 'Vulnerable source packages in the testing suite',
607     [make_menu(url.scriptRelative,
608     ("status/dtsa-candidates", "Candidates for DTSAs")),
609 fw 2491 bf.actions(url),
610 fw 2488 make_table(gen(), caption=("Package", "Bug", "Urgency",
611     "Remote"))])
612 fw 2482
613     def page_status_release_unstable(self, path, params, url):
614 fw 2491 bf = BugFilter(params)
615    
616 fw 2482 def gen():
617     old_pkg_name = ''
618 fw 2491 for (pkg_name, bug_name, section, urgency, remote) \
619 fw 2482 in self.db.cursor().execute(
620     """SELECT DISTINCT sp.name, st.bug_name,
621 fw 2491 sp.archive, st.urgency,
622     (SELECT range_remote FROM nvd_data
623     WHERE cve_name = st.bug_name)
624 fw 2482 FROM source_package_status AS st, source_packages AS sp
625     WHERE st.vulnerable AND st.urgency <> 'unimportant'
626     AND sp.rowid = st.package AND sp.release = 'sid'
627     AND sp.subrelease = ''
628     ORDER BY sp.name, st.bug_name"""):
629 fw 2491 if bf.urgencyFiltered(urgency):
630     continue
631     if bf.remoteFiltered(remote):
632     continue
633    
634 fw 2482 if pkg_name == old_pkg_name:
635     pkg_name = ''
636     else:
637     old_pkg_name = pkg_name
638     if section <> 'main':
639     pkg_name = "%s (%s)" % (pkg_name, section)
640     else:
641     pkg_name = self.make_xref(url, pkg_name)
642    
643 fw 2491 if remote is None:
644     remote = ''
645     elif remote:
646     remote = 'yes'
647     else:
648     remote = 'no'
649    
650 fw 2482 if urgency == 'unknown':
651     urgency = ''
652     elif urgency == 'high':
653     urgency = self.make_red(urgency)
654    
655 fw 2491 yield pkg_name, self.make_xref(url, bug_name), urgency, remote
656 fw 2482
657    
658     return self.create_page(
659 fw 3014 url, 'Vulnerable source packages in the unstable suite',
660 fw 2482 [P("""Note that the list below is based on source packages.
661     This means that packages are not listed here once a new,
662     fixed source version has been uploaded to the archive, even
663     if there are still some vulnerably binary packages present
664     in the archive."""),
665 fw 2491 bf.actions(url),
666     make_table(gen(), caption=('Package', 'Bug', 'Urgency',
667     'Remote'))])
668 fw 2482
669     def page_status_dtsa_candidates(self, path, params, url):
670 fw 2491 bf = BugFilter(params)
671    
672 fw 2482 def gen():
673     old_pkg_name = ''
674 fw 2491 for (pkg_name, bug_name, archive, urgency, stable_later,
675     remote) \
676 fw 2482 in self.db.cursor().execute(
677     """SELECT package, bug, section, urgency,
678     (SELECT testing.version_id < stable.version_id
679     FROM source_packages AS testing, source_packages AS stable
680     WHERE testing.name = testing_status.package
681     AND testing.release = 'etch'
682     AND testing.subrelease = ''
683     AND testing.archive = testing_status.section
684     AND stable.name = testing_status.package
685     AND stable.release = 'sarge'
686     AND stable.subrelease = 'security'
687 fw 2491 AND stable.archive = testing_status.section),
688     (SELECT range_remote FROM nvd_data
689     WHERE cve_name = bug)
690 fw 2482 FROM testing_status
691     WHERE (NOT unstable_vulnerable)
692     AND (NOT testing_security_fixed)"""):
693 fw 2491 if bf.urgencyFiltered(urgency):
694     continue
695     if bf.remoteFiltered(remote):
696     continue
697    
698 fw 2482 if pkg_name == old_pkg_name:
699     pkg_name = ''
700     migration = ''
701     else:
702     old_pkg_name = pkg_name
703     migration = A(self.url_testing_status(url, pkg_name),
704     "check")
705     if archive <> 'main':
706     pkg_name = "%s (%s)" % (pkg_name, archive)
707     else:
708     pkg_name = self.make_source_package_ref(url, pkg_name)
709    
710 fw 2491 if remote is None:
711     remote = ''
712     elif remote:
713     remote = 'yes'
714     else:
715     remote = 'no'
716    
717 fw 2482 if urgency == 'unknown':
718     urgency = ''
719     elif urgency == 'high':
720     urgency = self.make_red(urgency)
721    
722     if stable_later:
723     notes = "(fixed in stable?)"
724     else:
725     notes = ''
726    
727     yield (pkg_name, migration, self.make_xref(url, bug_name),
728 fw 2491 urgency, remote, notes)
729 fw 2482
730     return self.create_page(
731     url, "Candidates for DTSAs",
732     [P("""The table below lists packages which are fixed
733     in unstable, but unfixed in testing. Use the testing migration
734 fw 2679 checker to find out why they have not entered testing yet."""),
735 fw 2482 make_menu(url.scriptRelative,
736     ("status/release/testing",
737     "List of vulnerable packages in testing")),
738 fw 2491 bf.actions(url),
739 fw 2482 make_table(gen(),
740 fw 2491 caption=("Package", "Migration", "Bug", "Urgency",
741     "Remote"))])
742 fw 2482
743     def page_status_todo(self, path, params, url):
744     def gen():
745     for (bug, description) in self.db.getTODOs():
746     yield self.make_xref(url, bug), description
747     return self.create_page(
748     url, "Bugs with TODO items",
749     [make_table(gen(),
750     caption=("Bug", "Description"))])
751    
752     def page_status_itp(self, path, params, url):
753     def gen():
754     old_pkg = ''
755     for pkg, bugs, debian_bugs in self.db.getITPs(self.db.cursor()):
756     if pkg == old_pkg:
757     pkg = ''
758     else:
759     old_pkg = pkg
760     yield (pkg, self.make_xref_list(url, bugs),
761     self.make_debian_bug_list(url, debian_bugs))
762     return self.create_page(
763     url, "ITPs with potential security issues",
764     [make_table(gen(), caption=("Package", "Issue", "Debian Bugs"),
765     replacement="No ITP bugs are currently known.")])
766    
767     def page_data_unknown_packages(self, path, params, url):
768     def gen():
769     for name, bugs in self.db.getUnknownPackages(self.db.cursor()):
770     yield name, self.make_xref_list(url, bugs)
771     return self.create_page(
772     url, "Unknown packages",
773     [P("""Sometimes, a package referenced in a bug report
774     cannot be found in the database. This can be the result of a spelling
775     return web_supporterror, or a historic entry refers to a
776     return web_supportpackage which is no longer in the archive."""),
777     make_table(gen(), caption=("Package", "Bugs"),
778     replacement="No unknown packages are referenced in the database.")])
779    
780     def page_data_missing_epochs(self, path, params, url):
781     def gen():
782     old_bug = ''
783     old_pkg = ''
784     for bug, pkg, ver1, ver2 in self.db.cursor().execute(
785     """SELECT DISTINCT bug_name, n.package,
786     n.fixed_version, sp.version
787     FROM package_notes AS n, source_packages AS sp
788     WHERE n.package_kind = 'source'
789     AND n.fixed_version NOT LIKE '%:%'
790     AND n.fixed_version <> '0'
791     AND n.bug_origin = ''
792     AND sp.name = n.package
793     AND sp.version LIKE '%:%'
794     ORDER BY bug_name, package"""):
795     if bug == old_bug:
796     bug = ''
797     else:
798     old_bug = bug
799     old_pkg = ''
800     bug = self.make_xref(url, bug)
801     if pkg == old_pkg:
802     pkg = ''
803     else:
804     old_pkg = pkg
805     pkg = self.make_source_package_ref(url, pkg)
806     yield bug, pkg, ver1, ver2
807    
808     return self.create_page(
809     url, "Missing epochs in package versions",
810     [make_table(gen(),
811     caption=("Bug", "Package", "Version 1", "Version 2"),
812     replacement="No source package version with missing epochs.")])
813    
814 fw 3136 def page_data_latently_vulnerable(self, path, params, url):
815     def gen():
816     for pkg, bugs in self.db.cursor().execute(
817     """SELECT package, string_set(bug_name)
818     FROM package_notes AS p1
819     WHERE release <> ''
820     AND (bug_name LIKE 'CVE-%' OR bug_name LIKE 'FAKE-%')
821     AND NOT EXISTS (SELECT 1 FROM package_notes AS p2
822     WHERE p2.bug_name = p1.bug_name
823     AND p2.package = p1.package
824     AND release = '')
825     AND EXISTS (SELECT 1 FROM source_packages
826     WHERE name = p1.package AND release = 'sid')
827     GROUP BY package
828     ORDER BY package"""):
829     pkg = self.make_source_package_ref(url, pkg)
830     bugs = bugs.split(',')
831     yield pkg, self.make_xref_list(url, bugs)
832    
833 fw 3166 def gen_unimportant():
834     for pkg, bugs in self.db.cursor().execute(
835     """SELECT package, string_set(bug_name)
836     FROM package_notes AS p1
837     WHERE release <> ''
838     AND urgency <> 'unimportant'
839     AND (bug_name LIKE 'CVE-%' OR bug_name LIKE 'FAKE-%')
840     AND EXISTS (SELECT 1 FROM package_notes AS p2
841     WHERE p2.bug_name = p1.bug_name
842     AND p2.package = p1.package
843     AND release = '')
844     AND NOT EXISTS (SELECT 1 FROM package_notes AS p2
845     WHERE p2.bug_name = p1.bug_name
846     AND p2.package = p1.package
847     AND urgency <> 'unimportant'
848     AND release = '')
849     AND EXISTS (SELECT 1 FROM source_packages
850     WHERE name = p1.package AND release = 'sid')
851     GROUP BY package
852     ORDER BY package"""):
853     pkg = self.make_source_package_ref(url, pkg)
854     bugs = bugs.split(',')
855     yield pkg, self.make_xref_list(url, bugs)
856    
857 fw 3136 return self.create_page(
858     url, "Latently vulnerable packages in unstable",
859     [P(
860     """A package is latently vulnerable in unstable if it is vulnerable in
861     any release, and there is no package note for the same vulnerability
862     and package in unstable (and the package is still available in
863     unstable, of course)."""),
864     make_table(gen(),
865     caption=("Package", "Bugs"),
866 fw 3166 replacement="No latently vulnerable packages were found."),
867     P(
868     """The next table lists issues which are marked unimportant for
869     unstable, but for which release-specific annotations exist which are
870     not unimportant."""),
871     make_table(gen_unimportant(),
872     caption=("Package", "Bugs"),
873     replacement=
874     "No packages with unimportant latent vulnerabilities were found."),
875     ])
876 fw 3136
877 fw 2482 def page_data_releases(self, path, params, url):
878     def gen():
879     for (rel, subrel, archive, sources, archs) \
880     in self.db.availableReleases():
881     if sources:
882     sources = 'yes'
883     else:
884     sources = 'no'
885     yield rel, subrel, archive, sources, make_list(archs)
886     return self.create_page(
887     url, "Available releases",
888     [P("""The security issue database is checked against
889     the Debian releases listed in the table below."""),
890     make_table(gen(),
891     caption=("Release", "Subrelease", "Archive",
892     "Sources", "Architectures"))])
893    
894     def page_data_funny_versions(self, path, params, url):
895     def gen():
896     for name, release, archive, version, source_version \
897     in self.db.getFunnyPackageVersions():
898     yield name, release, archive, source_version, version
899    
900     return self.create_page(
901     url, "Version conflicts between source/binary packages",
902     [P("""The table below lists source packages
903     which have a binary package of the same name, but with a different
904     version. This means that extra care is necessary to determine
905     the version of a package which has been fixed. (Note that
906     the bug tracker prefers source versions to binary versions
907     in this case.)"""),
908     make_table(gen(),
909     caption=("Package",
910     "Release",
911     "Archive",
912     "Source Version",
913     "Binary Version")),
914     P("""Technically speaking, these version numbering is fine,
915     but it makes version-based bug tracking quite difficult for these packages."""),
916     P("""There are many binary packages which are built from source
917     packages with different version numbering schemes. However, as
918     long as none of the binary packages carries the same name as the
919     source package, most confusion is avoided or can be easily
920     explained.""")])
921    
922 fw 2554 def page_data_fake_names(self, path, params, url):
923     def gen():
924     for (bug, description) in self.db.getFakeBugs():
925     yield self.make_xref(url, bug), description
926     return self.create_page(
927     url, "Automatically generated issue names",
928     [P("""Some issues have not been assigned CVE names, but are still
929     tracked by this database. In this case, the system automatically assigns
930     a unique name. These names are not stable and can change when the database
931     is updated, so they should not be used in external references."""),
932     P('''The automatically generated names come in two flavors:
933     the first kind starts with the string "''', CODE("FAKE-000000-"),
934     '''". This means that no Debian bug has been assigned to this
935     issue (or a bug has been created and is not recorded in this database).
936     In the second kind of names, there is a Debian bug for the issue, and the "''',
937     CODE("000000"), '''"part of the name is replaced with the
938     Debian bug number.'''),
939     make_table(gen(),
940     caption=("Bug", "Description"))])
941    
942 fw 3051 def page_debsecan(self, path, params, url):
943     obj = '/'.join(path)
944     data = self.db.getDebsecan(obj)
945     if data:
946     return BinaryResult(data)
947     else:
948     return self.create_page(
949     url, "Object not found",
950     [P("The requested debsecan object has not been found.")],
951     status=404)
952    
953 fw 2482 def create_page(self, url, title, body, search_in_page=False, status=200):
954     append = body.append
955     append(HR())
956     if not search_in_page:
957     append(self.make_search_button(url))
958     append(P(A(url.scriptRelative(""), "Home"),
959     " - ", A(url.absolute("http://secure-testing.debian.net/"),
960     "Testing Security Team"),
961     " - ", A(url.absolute("http://www.debian.org/security/"),
962     "Debian Security"),
963     " - ", A(url.absolute
964     ("http://www.enyo.de/fw/impressum.html"),
965     "Imprint")))
966     if search_in_page:
967     on_load = "selectSearch()"
968     else:
969     on_load = None
970     return HTMLResult(self.add_title(title, body,
971     head_contents=self.head_contents,
972     body_attribs={'onload': on_load}),
973     doctype=self.html_dtd(),
974     status=status)
975    
976     def make_search_button(self, url):
977     return FORM("Search for package or bug name: ",
978     INPUT(type='text', name='query',
979     onkeyup="onSearch(this.value)",
980     onmousemove="onSearch(this.value)"),
981     INPUT(type='submit', value='Go'),
982     method='get',
983     action=url.scriptRelative(''))
984    
985     def url_cve(self, url, name):
986     return url.absolute("http://cve.mitre.org/cgi-bin/cvename.cgi",
987     name=name)
988 fw 2488 def url_nvd(self, url, name):
989     return url.absolute("http://nvd.nist.gov/nvd.cfm",
990     cvename=name)
991    
992 fw 2482 def url_dsa(self, url, dsa, re_dsa=re.compile(r'^DSA-(\d+)(?:-\d+)?$')):
993     match = re_dsa.match(dsa)
994     if match:
995     # We must determine the year because there is no generic URL.
996     (number,) = match.groups()
997     for (date,) in self.db.cursor().execute(
998     "SELECT release_date FROM bugs WHERE name = ?", (dsa,)):
999     (y, m, d) = date.split('-')
1000     return url.absolute("http://www.debian.org/security/%d/dsa-%d"
1001     % (int(y), int(number)))
1002     return None
1003    
1004     def url_debian_bug(self, url, debian):
1005     return url.absolute("http://bugs.debian.org/cgi-bin/bugreport.cgi",
1006     bug=str(debian))
1007     def url_debian_bug_pkg(self, url, debian):
1008     return url.absolute("http://bugs.debian.org/cgi-bin/pkgreport.cgi",
1009     pkg=debian)
1010     def url_pts(self, url, package):
1011     return url.absolute("http://packages.qa.debian.org/common/index.html",
1012     src=package)
1013     def url_testing_status(self, url, package):
1014     return url.absolute("http://bjorn.haxx.se/debian/testing.pl",
1015     package=package)
1016     def url_source_package(self, url, package, full=False):
1017     if full:
1018     return url.scriptRelativeFull("source-package/" + package)
1019     else:
1020     return url.scriptRelative("source-package/" + package)
1021     def url_binary_package(self, url, package, full=False):
1022     if full:
1023     return url.scriptRelativeFull("binary-package/" + package)
1024     else:
1025     return url.scriptRelative("binary-package/" + package)
1026    
1027     def make_xref(self, url, name):
1028     return A(url.scriptRelative(name), name)
1029    
1030     def make_xref_list(self, url, lst, separator=', '):
1031     return make_list(map(lambda x: self.make_xref(url, x), lst), separator)
1032    
1033     def make_debian_bug(self, url, debian):
1034     return A(self.url_debian_bug(url, debian), str(debian))
1035     def make_debian_bug_list(self, url, lst):
1036     return make_list(map(lambda x: self.make_debian_bug(url, x), lst))
1037    
1038     def make_cve_ref(self, url, cve, name=None):
1039     if name is None:
1040     name = cve
1041     return A(self.url_cve(url, cve), name)
1042    
1043 fw 2488 def make_nvd_ref(self, url, cve, name=None):
1044     if name is None:
1045     name = cve
1046     return A(self.url_nvd(url, cve), name)
1047    
1048 fw 2482 def make_dsa_ref(self, url, dsa, name=None):
1049     if name is None:
1050     name = dsa
1051     u = self.url_dsa(url, dsa)
1052     if u:
1053     return A(u, name)
1054     else:
1055     return name
1056    
1057     def make_pts_ref(self, url, pkg, name=None):
1058     if name is None:
1059     name = pkg
1060     return A(self.url_pts(url, pkg), name)
1061    
1062     def make_source_package_ref(self, url, pkg, title=None):
1063     if title is None:
1064     title = pkg
1065     return A(self.url_source_package(url, pkg), title)
1066     def make_binary_package_ref(self, url, pkg, title=None):
1067     if title is None:
1068     title = pkg
1069     return A(self.url_binary_package(url, pkg), title)
1070     def make_binary_packages_ref(self, url, lst):
1071     assert type(lst) <> types.StringType
1072     return make_list(map(lambda x: self.make_binary_package_ref(url, x),
1073     lst))
1074    
1075     def make_red(self, contents):
1076     return SPAN(contents, _class="red")
1077    
1078     def make_dangerous(self, contents):
1079     return SPAN(contents, _class="dangerous")
1080    
1081     def pre_dispatch(self):
1082     self.db.refresh()
1083    
1084     TrackerService(socket_name, db_name).run()

Properties

Name Value
svn:mime-type text/script

  ViewVC Help
Powered by ViewVC 1.1.5