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

Contents of /bin/tracker_service.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3051 - (show annotations) (download) (as text)
Thu Dec 15 11:37:40 2005 UTC (7 years, 5 months ago) by fw
File MIME type: text/script
File size: 41483 byte(s)
lib/python/security_db.py (DB):
  Bump schema version.
(DB.initSchema):
  Add debsecan_data table.
(DB.calculateDebsecan, DB.getDebsecan):
  New methods.

bin/update-db:
  Invoke calculateDebsecan.

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

Properties

Name Value
svn:mime-type text/script

  ViewVC Help
Powered by ViewVC 1.1.5