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

Contents of /bin/tracker_service.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 27589 - (show annotations) (download) (as text)
Thu Jul 3 09:49:16 2014 UTC (8 weeks ago) by pabs
File MIME type: text/script
File size: 61264 byte(s)
Switch from http to https for qa.d.o/packages.qa.d.o URLs
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(TR(TD(A(url.updateParamsDict({prop : None}), note))))
56 else:
57 note = 'Show ' + desc
58 l.append(TR(TD(A(url.updateParamsDict({prop : '1'}), note))))
59
60 return TABLE(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(STYLE(
90 """h1 { font-size : 144%; }
91 h2 { font-size : 120%; }
92 h3 { font-size : 100%; }
93
94 table { padding-left : 1.5em }
95 td, th { text-align : left;
96 padding-left : 0.25em;
97 padding-right : 0.25em; }
98 td { vertical-align: baseline }
99 span.red { color: red; }
100 span.purple { color: purple; }
101 span.green { color: green; }
102 span.dangerous { color: rgb(191,127,0); }
103 """), SCRIPT('''var old_query_value = "";
104
105 function selectSearch() {
106 document.searchForm.query.focus();
107 }
108
109 function onSearch(query) {
110 if (old_query_value == "") {
111 if (query.length > 5) {
112 old_query_value = query;
113 document.searchForm.submit();
114 } else {
115 old_query_value = query;
116 }
117 }
118 }
119 ''')).toHTML()
120
121 nvd_text = P('''If a "**" is included, the urgency field was automatically
122 assigned by the NVD (National Vulnerability Database). Note that this
123 rating is automatically derived from a set of known factors about the
124 issue (such as access complexity, confidentiality impact, exploitability,
125 remediation level, and others). Human intervention is involved in
126 determining the values of these factors, but the rating itself comes
127 from a fully automated formula.''')
128
129 def __init__(self, socket_name, db_name):
130 webservice_base_class.__init__(self, socket_name)
131 self.db = security_db.DB(db_name)
132 self.register('', self.page_home)
133 self.register('*', self.page_object)
134 self.register('redirect/*', self.page_redirect)
135 self.register('source-package/*', self.page_source_package)
136 self.register('status/release/oldstable',
137 self.page_status_release_oldstable)
138 self.register('status/release/stable', self.page_status_release_stable)
139 self.register('status/release/stable-backports',
140 self.page_status_release_stable_backports)
141 self.register('status/release/oldstable-backports',
142 self.page_status_release_oldstable_backports)
143 self.register('status/release/testing',
144 self.page_status_release_testing)
145 self.register('status/release/unstable',
146 self.page_status_release_unstable)
147 self.register('status/dtsa-candidates',
148 self.page_status_dtsa_candidates)
149 self.register('status/todo', self.page_status_todo)
150 self.register('status/undetermined', self.page_status_undetermined)
151 self.register('status/unimportant', self.page_status_unimportant)
152 self.register('status/itp', self.page_status_itp)
153 self.register('data/unknown-packages', self.page_data_unknown_packages)
154 self.register('data/missing-epochs', self.page_data_missing_epochs)
155 self.register('data/latently-vulnerable',
156 self.page_data_latently_vulnerable)
157 self.register('data/releases', self.page_data_releases)
158 self.register('data/funny-versions', self.page_data_funny_versions)
159 self.register('data/fake-names', self.page_data_fake_names)
160 self.register('data/pts/1', self.page_data_pts)
161 self.register('debsecan/**', self.page_debsecan)
162 self.register('data/report', self.page_report)
163
164 def page_home(self, path, params, url):
165 query = params.get('query', ('',))[0]
166 if query:
167 if '/' in query:
168 return self.page_not_found(url, query)
169 else:
170 return RedirectResult(url.scriptRelativeFull(query))
171
172 return self.create_page(
173 url, 'Security Bug Tracker',
174 [P(
175 """The data in this tracker comes solely from the bug database maintained
176 by Debian's security team located in the testing-security Subversion """,
177 A("https://anonscm.debian.org/viewvc/secure-testing/data/", "repository"),
178 """. The data represented here is derived from: """,
179 A("https://www.debian.org/security/#DSAS", "DSAs"),
180 """ issued by the Security Team; issues tracked in the """,
181 A("https://cve.mitre.org/cve/", "CVE database"),
182 """, issues tracked in the """,
183 A("https://nvd.nist.gov/", "National Vulnerability Database"),
184 """ (NVD), maintained by NIST; and security issues
185 discovered in Debian packages as reported in the BTS."""),
186 P("""All external data (including Debian bug reports and official Debian
187 security advisories) must be added to this database before it appears
188 here. Please help us keep this information up-to-date by """,
189 A(url.scriptRelative("data/report"), "reporting"),
190 """ any discrepancies or change of states that you are
191 aware of and/or help us improve the quality of this information by """,
192 A(url.scriptRelative("data/report"), "participating"),
193 "."),
194 make_menu(
195 url.scriptRelative,
196 ('status/release/unstable',
197 'Vulnerable packages in the unstable suite'),
198 ('status/release/testing',
199 'Vulnerable packages in the testing suite'),
200 ('status/release/stable',
201 'Vulnerable packages in the stable suite'),
202 ('status/release/stable-backports',
203 'Vulnerable packages in backports for stable'),
204 ('status/release/oldstable',
205 'Vulnerable packages in the oldstable suite'),
206 ('status/release/oldstable-backports',
207 'Vulnerable packages in backports for oldstable'),
208 ('status/dtsa-candidates', "Candidates for DTSAs"),
209 ('status/todo', 'TODO items'),
210 ('status/undetermined', 'Packages that may be vulnerable but need to be checked (undetermined issues)'),
211 ('status/unimportant', 'Packages that have open unimportant issues'),
212 ('status/itp', 'ITPs with potential security issues'),
213 ('data/unknown-packages',
214 'Packages names not found in the archive'),
215 ('data/fake-names', 'Tracked issues without a CVE name'),
216 ('data/missing-epochs',
217 'Package versions which might lack an epoch'),
218 ('data/latently-vulnerable',
219 'Packages which are latently vulnerable in unstable'),
220 ('data/funny-versions',
221 'Packages with strange version numbers'),
222 ('data/releases',
223 'Covered Debian releases and architectures (slow)'),
224 self.make_search_button(url)),
225 P("""(You can enter CVE names, Debian bug numbers and package
226 names in the search forms.)"""),
227
228 H2("External interfaces"),
229 P("""If you want to automatically open a relevant web page for
230 some object, use the """,
231 CODE(str(url.scriptRelative("redirect/")), EM("object")),
232 """ URL. If no information is contained in this database,
233 the browser is automatically redirected to the corresponding external
234 data source.""")],
235 search_in_page=True)
236
237 def page_object(self, path, params, url):
238 obj = path[0]
239 return self.page_object_or_redirect(url, obj, False)
240
241 def page_redirect(self, path, params, url):
242 if path == ():
243 obj = ''
244 else:
245 obj = path[0]
246 return self.page_object_or_redirect(url, obj, True)
247
248 def page_object_or_redirect(self, url, obj, redirect):
249 c = self.db.cursor()
250
251 if not obj:
252 # Redirect to start page.
253 return RedirectResult(url.scriptRelativeFull(""))
254
255 # Attempt to decode a bug number. TEMP-nnn bugs (but not
256 # TEMP-nnn-mmm bugs) are treated as bug references, too.
257 bugnumber = 0
258 fake_bug = False
259 try:
260 if obj[0:5] == 'FAKE-' or obj[0:5] == 'TEMP-':
261 bugnumber = int(obj[5:])
262 fake_bug = True
263 else:
264 bugnumber = int(obj)
265 except ValueError:
266 pass
267 if bugnumber:
268 buglist = list(self.db.getBugsFromDebianBug(c, bugnumber))
269 if buglist:
270 return self.page_debian_bug(url, bugnumber, buglist, fake_bug)
271 if redirect:
272 return RedirectResult(self.url_debian_bug(url, str(bugnumber)),
273 permanent=False)
274
275 if 'A' <= obj[0] <= 'Z':
276 # Bug names start with a capital letter.
277 return self.page_bug(url, obj, redirect)
278
279 if self.db.isSourcePackage(c, obj):
280 return RedirectResult(self.url_source_package(url, obj, full=True))
281
282 return self.page_not_found(url, obj)
283
284 def page_bug(self, url, name, redirect):
285 # FIXME: Normalize CAN-* to CVE-* when redirecting. Too many
286 # people still use CAN.
287 if redirect and name[0:4] == 'CAN-':
288 name = 'CVE-' + name[4:]
289
290 cursor = self.db.cursor()
291 try:
292 bug = bugs.BugFromDB(cursor, name)
293 except ValueError:
294 if redirect:
295 if name[0:4] == 'CVE-':
296 return RedirectResult(self.url_cve(url, name),
297 permanent=False)
298 return self.page_not_found(url, name)
299 if bug.name <> name or redirect:
300 # Show the normalized bug name in the browser address bar.
301 return RedirectResult(url.scriptRelativeFull(bug.name))
302
303 page = []
304
305 def gen_header():
306 yield B("Name"), bug.name
307
308 nvd = self.db.getNVD(cursor, bug.name)
309
310 if nvd and nvd.cve_desc:
311 yield B("Description"), nvd.cve_desc
312 elif bug.description:
313 yield B("Description"), bug.description
314
315 source = bug.name.split('-')[0]
316 if source == 'CVE':
317 source_xref = compose(self.make_cve_ref(url, bug.name, 'CVE'),
318 " (at ",
319 self.make_nvd_ref(url, bug.name,
320 'NVD'),
321 "; ",
322 self.make_osssec_bug_ref(url, bug.name, 'oss-sec'),
323 ", ",
324 self.make_osvdb_bug_ref(url, bug.name, 'OSVDB'),
325 ", ",
326 self.make_edb_bug_ref(url, bug.name, 'EDB'),
327 ", ",
328 self.make_rhbug_ref(url, bug.name,
329 'Red Hat'),
330 ", ",
331 self.make_ubuntu_bug_ref(url, bug.name, 'Ubuntu'),
332 ", ",
333 self.make_gentoo_bug_ref(url, bug.name, 'Gentoo'),
334 ", ",
335 self.make_suse_bug_ref(url, bug.name, 'SuSE'),
336 ", ",
337 self.make_mageia_bug_ref(url, bug.name, 'Mageia'),
338 ", ",
339 A(url.absolute('http://oss-security.openwall.org/wiki/vendors'), 'more'),
340 ")")
341 elif source == 'DSA':
342 source_xref = self.make_dsa_ref(url, bug.name, 'Debian')
343 elif source == 'DTSA':
344 source_xref = 'Debian Testing Security 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 page.append(H2("Vulnerable and fixed packages"))
384
385 def gen_source():
386 old_pkg = ''
387 for (package, release, version, vulnerable) \
388 in self.db.getSourcePackages(cursor, bug.name):
389 if package == old_pkg:
390 package = ''
391 else:
392 old_pkg = package
393 package = compose(
394 self.make_source_package_ref(url, package),
395 " (", self.make_pts_ref(url, package, 'PTS'), ")")
396 if vulnerable == 1:
397 vuln = self.make_red('vulnerable')
398 version = self.make_red(version)
399 elif vulnerable == 2:
400 vuln = self.make_purple('undetermined')
401 version = self.make_purple(version)
402 else:
403 vuln = 'fixed'
404
405 yield package, ', '.join(release), version, vuln
406
407 page.append(make_table(gen_source(),
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 (releases, version) in self.db.getSourcePackageVersions(
547 self.db.cursor(), pkg):
548 yield ', '.join(releases), 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 (releases, version) in self.db.getSourcePackageVersions(
555 self.db.cursor(), pkg):
556 for r in releases:
557 if r not in suites:
558 suites = suites + (r,)
559
560 def gen_summary(bugs):
561 for (bug, description) in bugs:
562 status = {}
563 for (package, releases, version, vulnerable) \
564 in self.db.getSourcePackages(self.db.cursor(), bug):
565 for release in releases:
566 if package == pkg:
567 if vulnerable == 1:
568 status[release] = self.make_red('vulnerable')
569 elif vulnerable == 2:
570 status[release] = self.make_purple('undetermined')
571 else:
572 status[release] = self.make_green('fixed')
573 status_row = ()
574 for release in suites:
575 if release in status:
576 status_row = status_row + (status[release],)
577 else:
578 status_row = status_row + (self.make_purple('unknown'),)
579 yield (self.make_xref(url, bug),) + status_row + (description,)
580
581 return self.create_page(
582 url, 'Information on source package ' + pkg,
583 [make_menu(lambda x: x,
584 (self.url_pts(url, pkg),
585 pkg + ' in the Package Tracking System'),
586 (self.url_debian_bug_pkg(url, pkg),
587 pkg + ' in the Bug Tracking System'),
588 (self.url_testing_status(url, pkg),
589 pkg + ' in the testing migration checker')),
590 H2('Available versions'),
591 make_table(gen_versions(), caption=('Release', 'Version')),
592
593 H2('Open issues'),
594 make_table(
595 gen_summary(
596 # open issues
597 self.db.getBugsForSourcePackage(
598 self.db.cursor(), pkg, True, False),
599 ),
600 caption=('Bug',) + suites + ('Description',),
601 replacement='No known open issues.'
602 ),
603
604
605 H2('Open unimportant issues'),
606 make_table(
607 gen_summary(
608 # open unimportant isues
609 self.db.getBugsForSourcePackage(
610 self.db.cursor(), pkg, True, True),
611 ),
612 caption=('Bug',) + suites + ('Description',),
613 replacement='No known unimportant issues.'
614 ),
615
616 H2('Resolved issues'),
617 make_table(gen_bug_list(self.db.getBugsForSourcePackage
618 (self.db.cursor(), pkg, False, True)),
619 caption=('Bug', 'Description'),
620 replacement='No known resolved issues.'),
621
622 H2('Security announcements'),
623 make_table(gen_bug_list(self.db.getDSAsForSourcePackage
624 (self.db.cursor(), pkg)),
625 caption=('DSA', 'Description'),
626 replacement='No known security announcements.')
627 ])
628
629 def page_status_release_stable_oldstable(self, release, params, url):
630 assert release in ('stable', 'oldstable')
631
632 bf = BugFilterNoDSA(params)
633
634 def gen():
635 old_pkg_name = ''
636 for (pkg_name, bug_name, archive, urgency, vulnerable, remote, no_dsa) in \
637 self.db.cursor().execute(
638 """SELECT package, bug, section, urgency, vulnerable, remote, no_dsa
639 FROM %s_status""" % release):
640 if bf.urgencyFiltered(urgency, vulnerable):
641 continue
642 if bf.remoteFiltered(remote):
643 continue
644 if bf.nodsaFiltered(no_dsa):
645 continue
646
647 if pkg_name == old_pkg_name:
648 pkg_name = ''
649 else:
650 old_pkg_name = pkg_name
651 if archive <> 'main':
652 pkg_name = "%s (%s)" % (pkg_name, archive)
653
654 if remote is None:
655 remote = '???'
656 elif remote:
657 remote = 'yes'
658 else:
659 remote = 'no'
660
661 if urgency.startswith('high'):
662 urgency = self.make_red(urgency)
663 elif vulnerable == 2:
664 urgency = self.make_purple(urgency)
665 else:
666 if no_dsa:
667 urgency = urgency + '*'
668
669 yield pkg_name, self.make_xref(url, bug_name), urgency, remote
670
671 return self.create_page(
672 url, 'Vulnerable source packages in the %s suite' % release,
673 [bf.actions(url), BR(),
674 make_table(gen(), caption=("Package", "Bug", "Urgency", "Remote")),
675 P('''If a "*" is included in the urgency field, no DSA is planned
676 for this vulnerability.'''),
677 self.nvd_text])
678
679 def page_status_release_stable(self, path, params, url):
680 return self.page_status_release_stable_oldstable('stable', params, url)
681 def page_status_release_oldstable(self, path, params, url):
682 return self.page_status_release_stable_oldstable('oldstable',
683 params, url)
684
685 def page_status_release_testing(self, path, params, url):
686 bf = BugFilterNoDSA(params)
687
688 def gen():
689 old_pkg_name = ''
690 for (pkg_name, bug_name, archive, urgency, vulnerable,
691 sid_vulnerable, ts_fixed, remote, no_dsa) \
692 in self.db.cursor().execute(
693 """SELECT package, bug, section, urgency, vulnerable,
694 unstable_vulnerable, testing_security_fixed, remote, no_dsa
695 FROM testing_status"""):
696 if bf.urgencyFiltered(urgency, vulnerable):
697 continue
698 if bf.remoteFiltered(remote):
699 continue
700 if bf.nodsaFiltered(no_dsa):
701 continue
702
703 if pkg_name == old_pkg_name:
704 pkg_name = ''
705 else:
706 old_pkg_name = pkg_name
707 if archive <> 'main':
708 pkg_name = "%s (%s)" % (pkg_name, archive)
709
710 if remote is None:
711 remote = '???'
712 elif remote:
713 remote = 'yes'
714 else:
715 remote = 'no'
716
717 if ts_fixed:
718 status = 'fixed in testing-security'
719 else:
720 if sid_vulnerable:
721 status = self.make_red('unstable is vulnerable')
722 else:
723 status = self.make_dangerous('fixed in unstable')
724
725 if urgency.startswith('high'):
726 urgency = self.make_red(urgency)
727 elif vulnerable == 2:
728 urgency = self.make_purple(urgency)
729
730 yield (pkg_name, self.make_xref(url, bug_name),
731 urgency, remote, status)
732
733 return self.create_page(
734 url, 'Vulnerable source packages in the testing suite',
735 [make_menu(url.scriptRelative,
736 ("status/dtsa-candidates", "Candidates for DTSAs")),
737 bf.actions(url), BR(),
738 make_table(gen(), caption=("Package", "Bug", "Urgency", "Remote")),
739 self.nvd_text])
740
741 def page_status_release_unstable_like(self, path, params, url,
742 rel, title):
743 bf = BugFilter(params)
744
745 def gen():
746 old_pkg_name = ''
747 for (pkg_name, bug_name, section, urgency, vulnerable, remote) \
748 in self.db.cursor().execute(
749 """SELECT DISTINCT sp.name, st.bug_name,
750 sp.archive, st.urgency, st.vulnerable,
751 (SELECT range_remote FROM nvd_data
752 WHERE cve_name = st.bug_name)
753 FROM source_package_status AS st, source_packages AS sp
754 WHERE st.vulnerable AND sp.rowid = st.package
755 AND sp.release = ? AND sp.subrelease = ''
756 ORDER BY sp.name, st.bug_name""", (rel,)):
757 if bf.urgencyFiltered(urgency, vulnerable):
758 continue
759 if bf.remoteFiltered(remote):
760 continue
761
762 if pkg_name == old_pkg_name:
763 pkg_name = ''
764 else:
765 old_pkg_name = pkg_name
766 if section <> 'main':
767 pkg_name = "%s (%s)" % (pkg_name, section)
768 else:
769 pkg_name = self.make_xref(url, pkg_name)
770
771 if remote is None:
772 remote = '???'
773 elif remote:
774 remote = 'yes'
775 else:
776 remote = 'no'
777
778 if urgency.startswith('high'):
779 urgency = self.make_red(urgency)
780 elif vulnerable == 2:
781 urgency = self.make_purple(urgency)
782
783 yield pkg_name, self.make_xref(url, bug_name), urgency, remote
784
785 return self.create_page(
786 url, title,
787 [P("""Note that the list below is based on source packages.
788 This means that packages are not listed here once a new,
789 fixed source version has been uploaded to the archive, even
790 if there are still some vulnerably binary packages present
791 in the archive."""),
792 bf.actions(url), BR(),
793 make_table(gen(), caption=('Package', 'Bug', 'Urgency', 'Remote')),
794 self.nvd_text])
795
796 def page_status_release_unstable(self, path, params, url):
797 return self.page_status_release_unstable_like(
798 path, params, url,
799 title='Vulnerable source packages in the unstable suite',
800 rel='sid')
801
802 def page_status_release_stable_backports(self, path, params, url):
803 return self.page_status_release_unstable_like(
804 path, params, url,
805 title='Vulnerable source packages among backports for stable',
806 rel='wheezy-backports')
807
808 def page_status_release_oldstable_backports(self, path, params, url):
809 return self.page_status_release_unstable_like(
810 path, params, url,
811 title='Vulnerable source packages among backports for oldstable',
812 rel='squeeze-backports')
813
814 def page_status_dtsa_candidates(self, path, params, url):
815 bf = BugFilter(params)
816
817 def gen():
818 old_pkg_name = ''
819 for (pkg_name, bug_name, archive, urgency, vulnerable,
820 stable_later, remote) \
821 in self.db.cursor().execute(
822 """SELECT package, bug, section, urgency, vulnerable,
823 (SELECT testing.version_id < stable.version_id
824 FROM source_packages AS testing, source_packages AS stable
825 WHERE testing.name = testing_status.package
826 AND testing.release = 'jessie'
827 AND testing.subrelease = ''
828 AND testing.archive = testing_status.section
829 AND stable.name = testing_status.package
830 AND stable.release = 'jessie'
831 AND stable.subrelease = 'security'
832 AND stable.archive = testing_status.section),
833 (SELECT range_remote FROM nvd_data
834 WHERE cve_name = bug)
835 FROM testing_status
836 WHERE (NOT unstable_vulnerable)
837 AND (NOT testing_security_fixed)"""):
838 if bf.urgencyFiltered(urgency, vulnerable):
839 continue
840 if bf.remoteFiltered(remote):
841 continue
842
843 if pkg_name == old_pkg_name:
844 pkg_name = ''
845 migration = ''
846 else:
847 old_pkg_name = pkg_name
848 migration = A(self.url_testing_status(url, pkg_name),
849 "check")
850 if archive <> 'main':
851 pkg_name = "%s (%s)" % (pkg_name, archive)
852 else:
853 pkg_name = self.make_source_package_ref(url, pkg_name)
854
855 if remote is None:
856 remote = '???'
857 elif remote:
858 remote = 'yes'
859 else:
860 remote = 'no'
861
862 if urgency.startswith('high'):
863 urgency = self.make_red(urgency)
864 elif vulnerable == 2:
865 urgency = self.make_purple(urgency)
866
867 if stable_later:
868 notes = "(fixed in stable?)"
869 else:
870 notes = ''
871
872 yield (pkg_name, migration, self.make_xref(url, bug_name),
873 urgency, remote, notes)
874
875 return self.create_page(
876 url, "Candidates for DTSAs",
877 [P("""The table below lists packages which are fixed
878 in unstable, but unfixed in testing. Use the testing migration
879 checker to find out why they have not entered testing yet."""),
880 make_menu(url.scriptRelative,
881 ("status/release/testing",
882 "List of vulnerable packages in testing")),
883 bf.actions(url), BR(),
884 make_table(gen(),
885 caption=("Package", "Migration", "Bug", "Urgency",
886 "Remote"))])
887
888 def page_status_todo(self, path, params, url):
889 hide_check = params.get('hide_check', False)
890 if hide_check:
891 flags = A(url.updateParamsDict({'hide_check' : None}),
892 'Show "check" TODOs')
893 else:
894 flags = A(url.updateParamsDict({'hide_check' : '1'}),
895 'Hide "check" TODOs')
896
897 def gen():
898 for (bug, description, note) in self.db.getTODOs(hide_check=hide_check):
899 yield self.make_xref(url, bug), description, note
900 return self.create_page(
901 url, 'Bugs with TODO items',
902 [P(flags), make_table(gen(), caption=('Bug', 'Description', 'Note'))])
903
904 def page_status_undetermined(self, path, params, url):
905 def gen():
906 outrel = []
907 old_bug = ''
908 old_pkg = ''
909 old_dsc = ''
910 last_displayed = ''
911 releases = ('sid', 'jessie', 'wheezy', 'squeeze')
912 for (pkg_name, bug_name, release, desc) in self.db.cursor().execute(
913 """SELECT DISTINCT sp.name, st.bug_name, sp.release,
914 bugs.description
915 FROM source_package_status AS st, source_packages AS sp, bugs
916 WHERE st.vulnerable == 2 AND sp.rowid = st.package
917 AND ( sp.release = ? OR sp.release = ? OR sp.release = ?
918 OR sp.release = ? )
919 AND sp.subrelease = '' AND st.bug_name == bugs.name
920 ORDER BY sp.name, st.bug_name""", releases):
921
922 if old_bug == '':
923 old_bug = bug_name
924 old_pkg = pkg_name
925 old_dsc = desc
926 elif old_bug != bug_name:
927 if old_pkg == last_displayed:
928 to_display = ''
929 else:
930 to_display = old_pkg
931 yield to_display, self.make_xref(url, old_bug), old_dsc, ', '.join(outrel)
932 last_displayed = old_pkg
933 old_bug = bug_name
934 old_pkg = pkg_name
935 old_dsc = desc
936 outrel = []
937 outrel.append( release )
938 yield old_pkg, self.make_xref(url, old_bug), old_dsc, ', '.join(outrel)
939
940 return self.create_page(url, 'Packages that may be vulnerable but need to be checked (undetermined issues)',
941 [P("""This page lists packages that may or may not be affected
942 by known issues. This means that some additional work needs to
943 be done to determined whether the package is actually
944 vulnerable or not. This list is a good area for new
945 contributors to make quick and meaningful contributions."""),
946 make_table(gen(), caption=('Package', 'Bug', 'Description', 'Releases'))])
947
948 def page_status_unimportant(self, path, params, url):
949 def gen():
950 outrel = []
951 old_bug = ''
952 old_pkg = ''
953 old_dsc = ''
954 old_name = ''
955 last_displayed = ''
956 releases = ('sid', 'jessie', 'wheezy', 'squeeze')
957 for (pkg_name, bug_name, release, desc) in self.db.cursor().execute(
958 """SELECT DISTINCT sp.name, st.bug_name, sp.release,
959 bugs.description
960 FROM source_package_status AS st, source_packages AS sp, bugs
961 WHERE st.vulnerable > 0 AND sp.rowid = st.package
962 AND ( sp.release = ? OR sp.release = ? OR sp.release = ?
963 OR sp.release = ? ) AND st.urgency == 'unimportant'
964 AND sp.subrelease = '' AND st.bug_name == bugs.name
965 ORDER BY sp.name, st.bug_name""", releases):
966
967 if old_bug == '':
968 old_bug = bug_name
969 old_pkg = pkg_name
970 old_dsc = desc
971 elif old_bug != bug_name:
972 if old_pkg == last_displayed:
973 to_display = ''
974 else:
975 to_display = old_pkg
976 yield to_display, self.make_xref(url, old_bug), old_dsc, ', '.join(outrel)
977 last_displayed = old_pkg
978 old_bug = bug_name
979 old_pkg = pkg_name
980 old_dsc = desc
981 outrel = []
982 outrel.append( release )
983 yield old_pkg, self.make_xref(url, old_bug), old_dsc, ', '.join(outrel)
984
985 return self.create_page(url, 'Packages that have open unimportant issues',
986 [P("""This page lists packages that are affected by issues
987 that are considered unimportant from a security perspective.
988 These issues are thought to be unexploitable or uneffective
989 in most situations (for example, browser denial-of-services)."""),
990 make_table(gen(), caption=('Package', 'Bug', 'Description', 'Releases'))])
991
992 def page_status_itp(self, path, params, url):
993 def gen():
994 old_pkg = ''
995 for pkg, bugs, debian_bugs in self.db.getITPs(self.db.cursor()):
996 if pkg == old_pkg:
997 pkg = ''
998 else:
999 old_pkg = pkg
1000 yield (pkg, self.make_xref_list(url, bugs),
1001 self.make_debian_bug_list(url, debian_bugs))
1002 return self.create_page(
1003 url, "ITPs with potential security issues",
1004 [make_table(gen(), caption=("Package", "Issue", "Debian Bugs"),
1005 replacement="No ITP bugs are currently known.")])
1006
1007 def page_data_unknown_packages(self, path, params, url):
1008 def gen():
1009 for name, bugs in self.db.getUnknownPackages(self.db.cursor()):
1010 yield name, self.make_xref_list(url, bugs)
1011 return self.create_page(
1012 url, "Unknown packages",
1013 [P("""Sometimes, a package referenced in a bug report
1014 cannot be found in the database. This can be the result of a spelling
1015 error, or a historic entry refers to a
1016 package which is no longer in the archive."""),
1017 make_table(gen(), caption=("Package", "Bugs"),
1018 replacement="No unknown packages are referenced in the database.")])
1019
1020 def page_data_missing_epochs(self, path, params, url):
1021 def gen():
1022 old_bug = ''
1023 old_pkg = ''
1024 for bug, pkg, ver1, ver2 in self.db.cursor().execute(
1025 """SELECT DISTINCT bug_name, n.package,
1026 n.fixed_version, sp.version
1027 FROM package_notes AS n, source_packages AS sp
1028 WHERE n.package_kind = 'source'
1029 AND n.fixed_version NOT LIKE '%:%'
1030 AND n.fixed_version <> '0'
1031 AND n.bug_origin = ''
1032 AND sp.name = n.package
1033 AND sp.version LIKE '%:%'
1034 ORDER BY bug_name, package"""):
1035 if bug == old_bug:
1036 bug = ''
1037 else:
1038 old_bug = bug
1039 old_pkg = ''
1040 bug = self.make_xref(url, bug)
1041 if pkg == old_pkg:
1042 pkg = ''
1043 else:
1044 old_pkg = pkg
1045 pkg = self.make_source_package_ref(url, pkg)
1046 yield bug, pkg, ver1, ver2
1047
1048 return self.create_page(
1049 url, "Missing epochs in package versions",
1050 [make_table(gen(),
1051 caption=("Bug", "Package", "Version 1", "Version 2"),
1052 replacement="No source package version with missing epochs.")])
1053
1054 def page_data_latently_vulnerable(self, path, params, url):
1055 def gen():
1056 for pkg, bugs in self.db.cursor().execute(
1057 """SELECT package, string_set(bug_name)
1058 FROM package_notes AS p1
1059 WHERE release <> ''
1060 AND (bug_name LIKE 'CVE-%' OR bug_name LIKE 'TEMP-%')
1061 AND NOT EXISTS (SELECT 1 FROM package_notes AS p2
1062 WHERE p2.bug_name = p1.bug_name
1063 AND p2.package = p1.package
1064 AND release = '')
1065 AND EXISTS (SELECT 1 FROM source_packages
1066 WHERE name = p1.package AND release = 'sid')
1067 GROUP BY package
1068 ORDER BY package"""):
1069 pkg = self.make_source_package_ref(url, pkg)
1070 bugs = bugs.split(',')
1071 yield pkg, self.make_xref_list(url, bugs)
1072
1073 def gen_unimportant():
1074 for pkg, bugs in self.db.cursor().execute(
1075 """SELECT package, string_set(bug_name)
1076 FROM package_notes AS p1
1077 WHERE release <> ''
1078 AND urgency <> 'unimportant'
1079 AND (bug_name LIKE 'CVE-%' OR bug_name LIKE 'TEMP-%')
1080 AND EXISTS (SELECT 1 FROM package_notes AS p2
1081 WHERE p2.bug_name = p1.bug_name
1082 AND p2.package = p1.package
1083 AND release = '')
1084 AND NOT EXISTS (SELECT 1 FROM package_notes AS p2
1085 WHERE p2.bug_name = p1.bug_name
1086 AND p2.package = p1.package
1087 AND urgency <> 'unimportant'
1088 AND release = '')
1089 AND EXISTS (SELECT 1 FROM source_packages
1090 WHERE name = p1.package AND release = 'sid')
1091 GROUP BY package
1092 ORDER BY package"""):
1093 pkg = self.make_source_package_ref(url, pkg)
1094 bugs = bugs.split(',')
1095 yield pkg, self.make_xref_list(url, bugs)
1096
1097 return self.create_page(
1098 url, "Latently vulnerable packages in unstable",
1099 [P(
1100 """A package is latently vulnerable in unstable if it is vulnerable in
1101 any release, and there is no package note for the same vulnerability
1102 and package in unstable (and the package is still available in
1103 unstable, of course)."""),
1104 make_table(gen(),
1105 caption=("Package", "Bugs"),
1106 replacement="No latently vulnerable packages were found."),
1107 P(
1108 """The next table lists issues which are marked unimportant for
1109 unstable, but for which release-specific annotations exist which are
1110 not unimportant."""),
1111 make_table(gen_unimportant(),
1112 caption=("Package", "Bugs"),
1113 replacement=
1114 "No packages with unimportant latent vulnerabilities were found."),
1115 ])
1116
1117 def page_data_releases(self, path, params, url):
1118 def gen():
1119 for (rel, subrel, archive, sources, archs) \
1120 in self.db.availableReleases():
1121 if sources:
1122 sources = 'yes'
1123 else:
1124 sources = 'no'
1125 yield rel, subrel, archive, sources, make_list(archs)
1126 return self.create_page(
1127 url, "Available releases",
1128 [P("""The security issue database is checked against
1129 the Debian releases listed in the table below."""),
1130 make_table(gen(),
1131 caption=("Release", "Subrelease", "Archive",
1132 "Sources", "Architectures"))])
1133
1134 def page_data_funny_versions(self, path, params, url):
1135 def gen():
1136 for name, release, archive, version, source_version \
1137 in self.db.getFunnyPackageVersions():
1138 yield name, release, archive, source_version, version
1139
1140 return self.create_page(
1141 url, "Version conflicts between source/binary packages",
1142 [P("""The table below lists source packages
1143 which have a binary package of the same name, but with a different
1144 version. This means that extra care is necessary to determine
1145 the version of a package which has been fixed. (Note that
1146 the bug tracker prefers source versions to binary versions
1147 in this case.)"""),
1148 make_table(gen(),
1149 caption=("Package",
1150 "Release",
1151 "Archive",
1152 "Source Version",
1153 "Binary Version")),
1154 P("""Technically speaking, these version numbering is fine,
1155 but it makes version-based bug tracking quite difficult for these packages."""),
1156 P("""There are many binary packages which are built from source
1157 packages with different version numbering schemes. However, as
1158 long as none of the binary packages carries the same name as the
1159 source package, most confusion is avoided or can be easily
1160 explained.""")])
1161
1162 def page_data_fake_names(self, path, params, url):
1163 def gen(v):
1164 for (bug, description) in self.db.getFakeBugs(vulnerability=v):
1165 yield self.make_xref(url, bug), description
1166 return self.create_page(
1167 url, "Automatically generated issue names",
1168 [P("""Some issues have not been assigned CVE names, but are still
1169 tracked by this database. In this case, the system automatically assigns
1170 a unique name. These names are not stable and can change when the database
1171 is updated, so they should not be used in external references."""),
1172 P('''The automatically generated names come in two flavors:
1173 the first kind starts with the string "''', CODE("TEMP-000000-"),
1174 '''". This means that no Debian bug has been assigned to this
1175 issue (or a bug has been created and is not recorded in this database).
1176 In the second kind of names, there is a Debian bug for the issue, and the "''',
1177 CODE("000000"), '''"part of the name is replaced with the
1178 Debian bug number.'''),
1179 H2("With unfixed issues"), make_table(gen(1), caption=("Bug", "Description")),
1180 H2("The rest"), make_table(gen(0), caption=("Bug", "Description")),
1181 ])
1182
1183 def page_data_pts(self, path, params, url):
1184 data = []
1185 for pkg, bugs in self.db.cursor().execute(
1186 """SELECT package, COUNT(DISTINCT bug) FROM
1187 (SELECT package, bug, urgency FROM stable_status
1188 UNION ALL SELECT DISTINCT sp.name, st.bug_name, st.urgency
1189 FROM source_package_status AS st, source_packages AS sp
1190 WHERE st.vulnerable AND st.urgency <> 'unimportant'
1191 AND sp.rowid = st.package AND sp.release = 'sid'
1192 AND sp.subrelease = '') x WHERE urgency <> 'unimportant'
1193 GROUP BY package ORDER BY package"""):
1194 data.append(pkg)
1195 data.append(':')
1196 data.append(str(bugs))
1197 data.append('\n')
1198 return BinaryResult(''.join(data))
1199
1200 def page_debsecan(self, path, params, url):
1201 obj = '/'.join(path)
1202 data = self.db.getDebsecan(obj)
1203 if data:
1204 return BinaryResult(data)
1205 else:
1206 return self.create_page(
1207 url, "Object not found",
1208 [P("The requested debsecan object has not been found.")],
1209 status=404)
1210
1211 def create_page(self, url, title, body, search_in_page=False, status=200):
1212 append = body.append
1213 append(HR())
1214 if not search_in_page:
1215 append(self.make_search_button(url))
1216 append(P(A(url.scriptRelative(""), "Home"),
1217 " - ", A(url.absolute("http://secure-testing.debian.net/"),
1218 "Testing Security Team"),
1219 " - ", A(url.absolute("https://www.debian.org/security/"),
1220 "Debian Security"),
1221 " - ", A(url.absolute("https://anonscm.debian.org/viewvc/secure-testing/bin/tracker_service.py?view=markup"),
1222 "Source"),
1223 " ", A(url.absolute("svn://anonscm.debian.org/svn/secure-testing"), "(SVN)"),
1224 ))
1225 if search_in_page:
1226 on_load = "selectSearch()"
1227 else:
1228 on_load = None
1229 return HTMLResult(self.add_title(title, body,
1230 head_contents=self.head_contents,
1231 body_attribs={'onload': on_load}),
1232 doctype=self.html_dtd(),
1233 status=status)
1234
1235 def make_search_button(self, url):
1236 return FORM("Search for package or bug name: ",
1237 INPUT(type='text', name='query',
1238 onkeyup="onSearch(this.value)",
1239 onmousemove="onSearch(this.value)"),
1240 INPUT(type='submit', value='Go'),
1241 ' ',
1242 A(url.scriptRelative("data/report"), "Reporting problems"),
1243 method='get',
1244 action=url.scriptRelative(''))
1245
1246 def url_cve(self, url, name):
1247 return url.absolute("https://cve.mitre.org/cgi-bin/cvename.cgi",
1248 name=name)
1249 def url_nvd(self, url, name):
1250 return url.absolute("https://web.nvd.nist.gov/view/vuln/detail",
1251 vulnId=name)
1252 def url_osssec_bug(self, url, name):
1253 return url.absolute("https://marc.info/", l="oss-security", s=name)
1254 def url_osvdb_bug(self, url, name):
1255 return url.absoluteDict("http://osvdb.org/search/search", {"search[refid]": name})
1256 def url_edb_bug(self, url, name):
1257 name = name[len('CVE-'):] if name.startswith('CVE-') else name
1258 return url.absolute("http://www.exploit-db.com/search/", action="search", filter_cve=name)
1259 def url_rhbug(self, url, name):
1260 return url.absolute("https://bugzilla.redhat.com/show_bug.cgi",
1261 id=name)
1262 def url_ubuntu_bug(self, url, name):
1263 return url.absolute("http://people.canonical.com/~ubuntu-security/cve/%s" % name)
1264 def url_gentoo_bug(self, url, name):
1265 return url.absolute("https://bugs.gentoo.org/show_bug.cgi", id=name)
1266 def url_suse_bug(self, url, name):
1267 return url.absolute("https://bugzilla.novell.com/show_bug.cgi",
1268 id=name)
1269 def url_mageia_bug(self, url, name):
1270 return url.absolute("https://advisories.mageia.org/%s.html" % name)
1271
1272 def url_dsa(self, url, dsa, re_dsa=re.compile(r'^DSA-(\d+)(?:-\d+)?$')):
1273 match = re_dsa.match(dsa)
1274 if match:
1275 # We must determine the year because there is no generic URL.
1276 (number,) = match.groups()
1277 for (date,) in self.db.cursor().execute(
1278 "SELECT release_date FROM bugs WHERE name = ?", (dsa,)):
1279 (y, m, d) = date.split('-')
1280 return url.absolute("https://www.debian.org/security/%d/dsa-%d"
1281 % (int(y), int(number)))
1282 return None
1283
1284 def url_debian_bug(self, url, debian):
1285 return url.absolute("https://bugs.debian.org/cgi-bin/bugreport.cgi",
1286 bug=str(debian))
1287 def url_debian_bug_pkg(self, url, debian):
1288 return url.absolute("https://bugs.debian.org/cgi-bin/pkgreport.cgi",
1289 pkg=debian)
1290 def url_pts(self, url, package):
1291 return url.absolute("https://packages.qa.debian.org/common/index.html",
1292 src=package)
1293 def url_testing_status(self, url, package):
1294 return url.absolute("https://release.debian.org/migration/testing.pl",
1295 package=package)
1296 def url_source_package(self, url, package, full=False):
1297 if full:
1298 return url.scriptRelativeFull("source-package/" + package)
1299 else:
1300 return url.scriptRelative("source-package/" + package)
1301
1302 def make_xref(self, url, name):
1303 return A(url.scriptRelative(name), name)
1304
1305 def make_xref_list(self, url, lst, separator=', '):
1306 return make_list(map(lambda x: self.make_xref(url, x), lst), separator)
1307
1308 def make_debian_bug(self, url, debian):
1309 return A(self.url_debian_bug(url, debian), str(debian))
1310 def make_debian_bug_list(self, url, lst):
1311 return make_list(map(lambda x: self.make_debian_bug(url, x), lst))
1312
1313 def make_cve_ref(self, url, cve, name=None):
1314 if name is None:
1315 name = cve
1316 return A(self.url_cve(url, cve), name)
1317
1318 def make_nvd_ref(self, url, cve, name=None):
1319 if name is None:
1320 name = cve
1321 return A(self.url_nvd(url, cve), name)
1322
1323 def make_osssec_bug_ref(self, url, cve, name=None):
1324 if name is None:
1325 name = cve
1326 return A(self.url_osssec_bug(url, cve), name)
1327
1328 def make_osvdb_bug_ref(self, url, cve, name=None):
1329 if name is None:
1330 name = cve
1331 return A(self.url_osvdb_bug(url, cve), name)
1332
1333 def make_edb_bug_ref(self, url, cve, name=None):
1334 if name is None:
1335 name = cve
1336 return A(self.url_edb_bug(url, cve), name)
1337
1338 def make_rhbug_ref(self, url, cve, name=None):
1339 if name is None:
1340 name = cve
1341 return A(self.url_rhbug(url, cve), name)
1342
1343 def make_ubuntu_bug_ref(self, url, cve, name=None):
1344 if name is None:
1345 name = cve
1346 return A(self.url_ubuntu_bug(url, cve), name)
1347
1348 def make_gentoo_bug_ref(self, url, cve, name=None):
1349 if name is None:
1350 name = cve
1351 return A(self.url_gentoo_bug(url, cve), name)
1352
1353 def make_suse_bug_ref(self, url, cve, name=None):
1354 if name is None:
1355 name = cve
1356 return A(self.url_suse_bug(url, cve), name)
1357
1358 def make_mageia_bug_ref(self, url, cve, name=None):
1359 if name is None:
1360 name = cve
1361 return A(self.url_mageia_bug(url, cve), name)
1362
1363 def make_dsa_ref(self, url, dsa, name=None):
1364 if name is None:
1365 name = dsa
1366 u = self.url_dsa(url, dsa)
1367 if u:
1368 return A(u, name)
1369 else:
1370 return name
1371
1372 def make_pts_ref(self, url, pkg, name=None):
1373 if name is None:
1374 name = pkg
1375 return A(self.url_pts(url, pkg), name)
1376
1377 def make_source_package_ref(self, url, pkg, title=None):
1378 if title is None:
1379 title = pkg
1380 return A(self.url_source_package(url, pkg), title)
1381
1382 def make_red(self, contents):
1383 return SPAN(contents, _class="red")
1384
1385 def make_purple(self, contents):
1386 return SPAN(contents, _class="purple")
1387
1388 def make_green(self, contents):
1389 return SPAN(contents, _class="green")
1390
1391 def make_dangerous(self, contents):
1392 return SPAN(contents, _class="dangerous")
1393
1394 def pre_dispatch(self):
1395 pass
1396
1397 TrackerService(socket_name, db_name).run()

Properties

Name Value
svn:mime-type text/script

  ViewVC Help
Powered by ViewVC 1.1.5