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

Contents of /bin/tracker_service.py

Parent Directory Parent Directory | Revision Log Revision Log


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

Properties

Name Value
svn:mime-type text/script

  ViewVC Help
Powered by ViewVC 1.1.5