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

Contents of /bin/tracker_service.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 10526 - (hide annotations) (download) (as text)
Sat Nov 29 10:36:17 2008 UTC (4 years, 6 months ago) by fw
File MIME type: text/script
File size: 49700 byte(s)
bin/tracker_service.py: Remove oldstable from the web front end

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

Properties

Name Value
svn:mime-type text/script

  ViewVC Help
Powered by ViewVC 1.1.5