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

Contents of /bin/tracker_service.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3594 - (show annotations) (download) (as text)
Sat Mar 11 18:27:37 2006 UTC (7 years, 2 months ago) by fw
File MIME type: text/script
File size: 48610 byte(s)
Incorporate Micah's changes.

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

Properties

Name Value
svn:mime-type text/script

  ViewVC Help
Powered by ViewVC 1.1.5