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

Contents of /bin/tracker_service.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2554 - (show annotations) (download) (as text)
Mon Oct 24 14:43:04 2005 UTC (7 years, 6 months ago) by fw
File MIME type: text/script
File size: 41094 byte(s)
Add a summary page for tracked bugs without a CVE name.

lib/python/security_db.py (DB.getFakeBugs):
  New method.

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

Properties

Name Value
svn:mime-type text/script

  ViewVC Help
Powered by ViewVC 1.1.5