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

Contents of /bin/tracker_service.py

Parent Directory Parent Directory | Revision Log Revision Log


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

Properties

Name Value
svn:mime-type text/script

  ViewVC Help
Powered by ViewVC 1.1.5