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

Contents of /bin/tracker_service.py

Parent Directory Parent Directory | Revision Log Revision Log


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

Properties

Name Value
svn:mime-type text/script

  ViewVC Help
Powered by ViewVC 1.1.5