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

Contents of /bin/tracker_service.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3051 - (hide annotations) (download) (as text)
Thu Dec 15 11:37:40 2005 UTC (7 years, 6 months ago) by fw
File MIME type: text/script
File size: 41483 byte(s)
lib/python/security_db.py (DB):
  Bump schema version.
(DB.initSchema):
  Add debsecan_data table.
(DB.calculateDebsecan, DB.getDebsecan):
  New methods.

bin/update-db:
  Invoke calculateDebsecan.

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

Properties

Name Value
svn:mime-type text/script

  ViewVC Help
Powered by ViewVC 1.1.5