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

Contents of /bin/tracker_service.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 12985 - (hide annotations) (download) (as text)
Sun Oct 11 12:04:15 2009 UTC (3 years, 7 months ago) by fw
File MIME type: text/script
File size: 51808 byte(s)
bin/tracker_service.py: implement HTTP invocation

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

Properties

Name Value
svn:mime-type text/script

  ViewVC Help
Powered by ViewVC 1.1.5