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

Contents of /bin/tracker_service.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 28539 - (show annotations) (download) (as text)
Mon Sep 1 10:40:19 2014 UTC (7 hours, 55 minutes ago) by carnil
File MIME type: text/script
File size: 61346 byte(s)
add support for squeeze-lts (Closes: #759727 once Florian has applied this to soler.d.o)
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 == 'DLA':
346 source_xref = 'Debian LTS Team'
347 elif source == 'TEMP':
348 source_xref = (
349 'Automatically generated temporary name. Not for external reference.')
350 else:
351 source_xref = None
352
353 if source_xref:
354 yield B("Source"), source_xref
355
356 xref = list(self.db.getBugXrefs(cursor, bug.name))
357 if xref:
358 yield B("References"), self.make_xref_list(url, xref)
359
360 if nvd:
361 nvd_range = nvd.rangeString()
362 if nvd.severity:
363 nvd_severity = nvd.severity.lower()
364 if nvd_range:
365 nvd_severity = "%s (attack range: %s)" \
366 % (nvd_severity, nvd_range)
367 yield B("NVD severity"), nvd_severity
368
369 debian_bugs = bug.getDebianBugs(cursor)
370 if debian_bugs:
371 yield (B("Debian Bugs"),
372 self.make_debian_bug_list(url, debian_bugs))
373
374 if not bug.not_for_us:
375 for (release, status, reason) in bug.getStatus(cursor):
376 if status == 'undetermined':
377 reason = self.make_purple(reason)
378 elif status <> 'fixed':
379 reason = self.make_red(reason)
380 yield B('Debian/%s' % release), reason
381
382 page.append(make_table(gen_header()))
383
384 if bug.notes:
385 page.append(H2("Vulnerable and fixed packages"))
386
387 def gen_source():
388 old_pkg = ''
389 for (package, release, version, vulnerable) \
390 in self.db.getSourcePackages(cursor, bug.name):
391 if package == old_pkg:
392 package = ''
393 else:
394 old_pkg = package
395 package = compose(
396 self.make_source_package_ref(url, package),
397 " (", self.make_pts_ref(url, package, 'PTS'), ")")
398 if vulnerable == 1:
399 vuln = self.make_red('vulnerable')
400 version = self.make_red(version)
401 elif vulnerable == 2:
402 vuln = self.make_purple('undetermined')
403 version = self.make_purple(version)
404 else:
405 vuln = 'fixed'
406
407 yield package, ', '.join(release), version, vuln
408
409 page.append(make_table(gen_source(),
410 caption=("Source Package", "Release", "Version", "Status"),
411 introduction=P('The table below lists information on source packages.')))
412
413 def gen_data():
414 notes_sorted = bug.notes[:]
415 notes_sorted.sort(lambda a, b: cmp(a.package, b.package))
416 for n in notes_sorted:
417 if n.release:
418 rel = str(n.release)
419 else:
420 rel = '(unstable)'
421 urgency = str(n.urgency)
422 if n.fixed_version:
423 ver = str(n.fixed_version)
424 if ver == '0':
425 ver = '(not affected)'
426 urgency = ''
427 else:
428 ver = self.make_red('(unfixed)')
429 if urgency == 'not yet assigned':
430 urgency = ''
431
432 pkg = n.package
433 pkg_kind = n.package_kind
434 if pkg_kind == 'source':
435 pkg = self.make_source_package_ref(url, pkg)
436 elif pkg_kind == 'itp':
437 pkg_kind = 'ITP'
438 rel = ''
439 ver = ''
440 urgency = ''
441
442 bugs = n.bugs
443 bugs.sort()
444 bugs = make_list(
445 map(lambda x: self.make_debian_bug(url, x), bugs))
446 if n.bug_origin:
447 origin = self.make_xref(url, n.bug_origin)
448 else:
449 origin = ''
450 yield (pkg, pkg_kind, rel, ver, urgency, origin, bugs)
451
452 page.append(
453 make_table(gen_data(),
454 caption=("Package", "Type", "Release", "Fixed Version",
455 "Urgency", "Origin", "Debian Bugs"),
456 introduction=P("The information above is based on the following data on fixed versions.")))
457
458 if bug.comments:
459 page.append(H2("Notes"))
460 def gen_comments():
461 for (t, c) in bug.comments:
462 yield c
463 page.append(make_pre(gen_comments()))
464
465 return self.create_page(url, bug.name, page)
466
467 def page_debian_bug(self, url, bugnumber, buglist, fake_bug):
468 if fake_bug:
469 new_buglist = []
470 for b in buglist:
471 (bug_name, urgency, description) = b
472 if bug_name[0:5] == 'FAKE-' or bug_name[0:5] == 'TEMP-':
473 new_buglist.append(b)
474 if len(new_buglist) > 0:
475 # Only replace the bug list if there are still fake
476 # bug reports.
477 buglist = new_buglist
478
479 if len(buglist) == 1:
480 # Single issue, redirect.
481 return RedirectResult(url.scriptRelativeFull(buglist[0][0]))
482
483 def gen():
484 for (name, urgency, description) in buglist:
485 if urgency == "unknown":
486 urgency = ""
487 yield self.make_xref(url, name), urgency, description
488
489 if fake_bug:
490 intro = """The URL you used contained a non-stable name
491 based on a Debian bug number. This name cannot be mapped to a specific
492 issue. """
493 else:
494 intro = ""
495
496 return self.create_page(
497 url, "Information related to Debian bug #%d" % bugnumber,
498 [P(intro + "The following issues reference to Debian bug ",
499 self.make_debian_bug(url, bugnumber), ":"),
500 make_table(gen(),
501 caption=("Name", "Urgency", "Description"))])
502
503 def page_not_found(self, url, query):
504 return self.create_page(url, 'Not found',
505 [P('Your query ',
506 CODE(query),
507 ' matched no results.')],
508 status=404)
509
510 def page_report(self, path, params, url):
511 return self.create_page(
512 url, 'Reporting discrepancies in the data',
513 [P("""The data in this tracker is always in flux, as bugs are fixed and new
514 issues disclosed, the data contained herein is updated. We strive to
515 maintain complete and accurate state information, and appreciate any
516 updates in status, information or new issues."""),
517 P("There are three ways that you can report updates to this information:"),
518 make_numbered_list(
519 [P("""IRC: We can be found at """,
520 CODE("irc.oftc.net"),
521 ", ",
522 CODE("#debian-security"),
523 """. If you have information to report, please go ahead and join
524 the channel and tell us. Please feel free to state the issue,
525 regardless if there is someone who has acknowledged you. Many of us
526 idle on this channel and may not be around when you join, but we read
527 the backlog and will see what you have said. If you require a
528 response, do not forget to let us know how to get a hold of you."""),
529 P("Mailing list: Our mailing list is: ",
530 A("mailto:debian-security-tracker@lists.debian.org",
531 "debian-security-tracker@lists.debian.org")),
532 P("""Helping out: We welcome people who wish to join us in tracking
533 issues. The process is designed to be easy to learn and participate,
534 please read our """,
535 A("http://security-team.debian.org/security_tracker.html",
536 "Introduction"),
537 """ to get familiar with how things work. Join us on
538 our mailing list, and on IRC and request to be added to the Alioth """,
539 A("https://alioth.debian.org/projects/secure-testing/", "project"),
540 """. We are really quite friendly. If you have a
541 question about how things work, don't be afraid to ask, we would like
542 to improve our documentation and procedures, so feedback is welcome.""")])])
543
544 def page_source_package(self, path, params, url):
545 pkg = path[0]
546
547 def gen_versions():
548 for (releases, version) in self.db.getSourcePackageVersions(
549 self.db.cursor(), pkg):
550 yield ', '.join(releases), version
551 def gen_bug_list(lst):
552 for (bug, description) in lst:
553 yield self.make_xref(url, bug), description
554
555 suites = ()
556 for (releases, version) in self.db.getSourcePackageVersions(
557 self.db.cursor(), pkg):
558 for r in releases:
559 if r not in suites:
560 suites = suites + (r,)
561
562 def gen_summary(bugs):
563 for (bug, description) in bugs:
564 status = {}
565 for (package, releases, version, vulnerable) \
566 in self.db.getSourcePackages(self.db.cursor(), bug):
567 for release in releases:
568 if package == pkg:
569 if vulnerable == 1:
570 status[release] = self.make_red('vulnerable')
571 elif vulnerable == 2:
572 status[release] = self.make_purple('undetermined')
573 else:
574 status[release] = self.make_green('fixed')
575 status_row = ()
576 for release in suites:
577 if release in status:
578 status_row = status_row + (status[release],)
579 else:
580 status_row = status_row + (self.make_purple('unknown'),)
581 yield (self.make_xref(url, bug),) + status_row + (description,)
582
583 return self.create_page(
584 url, 'Information on source package ' + pkg,
585 [make_menu(lambda x: x,
586 (self.url_pts(url, pkg),
587 pkg + ' in the Package Tracking System'),
588 (self.url_debian_bug_pkg(url, pkg),
589 pkg + ' in the Bug Tracking System'),
590 (self.url_testing_status(url, pkg),
591 pkg + ' in the testing migration checker')),
592 H2('Available versions'),
593 make_table(gen_versions(), caption=('Release', 'Version')),
594
595 H2('Open issues'),
596 make_table(
597 gen_summary(
598 # open issues
599 self.db.getBugsForSourcePackage(
600 self.db.cursor(), pkg, True, False),
601 ),
602 caption=('Bug',) + suites + ('Description',),
603 replacement='No known open issues.'
604 ),
605
606
607 H2('Open unimportant issues'),
608 make_table(
609 gen_summary(
610 # open unimportant isues
611 self.db.getBugsForSourcePackage(
612 self.db.cursor(), pkg, True, True),
613 ),
614 caption=('Bug',) + suites + ('Description',),
615 replacement='No known unimportant issues.'
616 ),
617
618 H2('Resolved issues'),
619 make_table(gen_bug_list(self.db.getBugsForSourcePackage
620 (self.db.cursor(), pkg, False, True)),
621 caption=('Bug', 'Description'),
622 replacement='No known resolved issues.'),
623
624 H2('Security announcements'),
625 make_table(gen_bug_list(self.db.getDSAsForSourcePackage
626 (self.db.cursor(), pkg)),
627 caption=('DSA', 'Description'),
628 replacement='No known security announcements.')
629 ])
630
631 def page_status_release_stable_oldstable(self, release, params, url):
632 assert release in ('stable', 'oldstable')
633
634 bf = BugFilterNoDSA(params)
635
636 def gen():
637 old_pkg_name = ''
638 for (pkg_name, bug_name, archive, urgency, vulnerable, remote, no_dsa) in \
639 self.db.cursor().execute(
640 """SELECT package, bug, section, urgency, vulnerable, remote, no_dsa
641 FROM %s_status""" % release):
642 if bf.urgencyFiltered(urgency, vulnerable):
643 continue
644 if bf.remoteFiltered(remote):
645 continue
646 if bf.nodsaFiltered(no_dsa):
647 continue
648
649 if pkg_name == old_pkg_name:
650 pkg_name = ''
651 else:
652 old_pkg_name = pkg_name
653 if archive <> 'main':
654 pkg_name = "%s (%s)" % (pkg_name, archive)
655
656 if remote is None:
657 remote = '???'
658 elif remote:
659 remote = 'yes'
660 else:
661 remote = 'no'
662
663 if urgency.startswith('high'):
664 urgency = self.make_red(urgency)
665 elif vulnerable == 2:
666 urgency = self.make_purple(urgency)
667 else:
668 if no_dsa:
669 urgency = urgency + '*'
670
671 yield pkg_name, self.make_xref(url, bug_name), urgency, remote
672
673 return self.create_page(
674 url, 'Vulnerable source packages in the %s suite' % release,
675 [bf.actions(url), BR(),
676 make_table(gen(), caption=("Package", "Bug", "Urgency", "Remote")),
677 P('''If a "*" is included in the urgency field, no DSA is planned
678 for this vulnerability.'''),
679 self.nvd_text])
680
681 def page_status_release_stable(self, path, params, url):
682 return self.page_status_release_stable_oldstable('stable', params, url)
683 def page_status_release_oldstable(self, path, params, url):
684 return self.page_status_release_stable_oldstable('oldstable',
685 params, url)
686
687 def page_status_release_testing(self, path, params, url):
688 bf = BugFilterNoDSA(params)
689
690 def gen():
691 old_pkg_name = ''
692 for (pkg_name, bug_name, archive, urgency, vulnerable,
693 sid_vulnerable, ts_fixed, remote, no_dsa) \
694 in self.db.cursor().execute(
695 """SELECT package, bug, section, urgency, vulnerable,
696 unstable_vulnerable, testing_security_fixed, remote, no_dsa
697 FROM testing_status"""):
698 if bf.urgencyFiltered(urgency, vulnerable):
699 continue
700 if bf.remoteFiltered(remote):
701 continue
702 if bf.nodsaFiltered(no_dsa):
703 continue
704
705 if pkg_name == old_pkg_name:
706 pkg_name = ''
707 else:
708 old_pkg_name = pkg_name
709 if archive <> 'main':
710 pkg_name = "%s (%s)" % (pkg_name, archive)
711
712 if remote is None:
713 remote = '???'
714 elif remote:
715 remote = 'yes'
716 else:
717 remote = 'no'
718
719 if ts_fixed:
720 status = 'fixed in testing-security'
721 else:
722 if sid_vulnerable:
723 status = self.make_red('unstable is vulnerable')
724 else:
725 status = self.make_dangerous('fixed in unstable')
726
727 if urgency.startswith('high'):
728 urgency = self.make_red(urgency)
729 elif vulnerable == 2:
730 urgency = self.make_purple(urgency)
731
732 yield (pkg_name, self.make_xref(url, bug_name),
733 urgency, remote, status)
734
735 return self.create_page(
736 url, 'Vulnerable source packages in the testing suite',
737 [make_menu(url.scriptRelative,
738 ("status/dtsa-candidates", "Candidates for DTSAs")),
739 bf.actions(url), BR(),
740 make_table(gen(), caption=("Package", "Bug", "Urgency", "Remote")),
741 self.nvd_text])
742
743 def page_status_release_unstable_like(self, path, params, url,
744 rel, title):
745 bf = BugFilter(params)
746
747 def gen():
748 old_pkg_name = ''
749 for (pkg_name, bug_name, section, urgency, vulnerable, remote) \
750 in self.db.cursor().execute(
751 """SELECT DISTINCT sp.name, st.bug_name,
752 sp.archive, st.urgency, st.vulnerable,
753 (SELECT range_remote FROM nvd_data
754 WHERE cve_name = st.bug_name)
755 FROM source_package_status AS st, source_packages AS sp
756 WHERE st.vulnerable AND sp.rowid = st.package
757 AND sp.release = ? AND sp.subrelease = ''
758 ORDER BY sp.name, st.bug_name""", (rel,)):
759 if bf.urgencyFiltered(urgency, vulnerable):
760 continue
761 if bf.remoteFiltered(remote):
762 continue
763
764 if pkg_name == old_pkg_name:
765 pkg_name = ''
766 else:
767 old_pkg_name = pkg_name
768 if section <> 'main':
769 pkg_name = "%s (%s)" % (pkg_name, section)
770 else:
771 pkg_name = self.make_xref(url, pkg_name)
772
773 if remote is None:
774 remote = '???'
775 elif remote:
776 remote = 'yes'
777 else:
778 remote = 'no'
779
780 if urgency.startswith('high'):
781 urgency = self.make_red(urgency)
782 elif vulnerable == 2:
783 urgency = self.make_purple(urgency)
784
785 yield pkg_name, self.make_xref(url, bug_name), urgency, remote
786
787 return self.create_page(
788 url, title,
789 [P("""Note that the list below is based on source packages.
790 This means that packages are not listed here once a new,
791 fixed source version has been uploaded to the archive, even
792 if there are still some vulnerably binary packages present
793 in the archive."""),
794 bf.actions(url), BR(),
795 make_table(gen(), caption=('Package', 'Bug', 'Urgency', 'Remote')),
796 self.nvd_text])
797
798 def page_status_release_unstable(self, path, params, url):
799 return self.page_status_release_unstable_like(
800 path, params, url,
801 title='Vulnerable source packages in the unstable suite',
802 rel='sid')
803
804 def page_status_release_stable_backports(self, path, params, url):
805 return self.page_status_release_unstable_like(
806 path, params, url,
807 title='Vulnerable source packages among backports for stable',
808 rel='wheezy-backports')
809
810 def page_status_release_oldstable_backports(self, path, params, url):
811 return self.page_status_release_unstable_like(
812 path, params, url,
813 title='Vulnerable source packages among backports for oldstable',
814 rel='squeeze-backports')
815
816 def page_status_dtsa_candidates(self, path, params, url):
817 bf = BugFilter(params)
818
819 def gen():
820 old_pkg_name = ''
821 for (pkg_name, bug_name, archive, urgency, vulnerable,
822 stable_later, remote) \
823 in self.db.cursor().execute(
824 """SELECT package, bug, section, urgency, vulnerable,
825 (SELECT testing.version_id < stable.version_id
826 FROM source_packages AS testing, source_packages AS stable
827 WHERE testing.name = testing_status.package
828 AND testing.release = 'jessie'
829 AND testing.subrelease = ''
830 AND testing.archive = testing_status.section
831 AND stable.name = testing_status.package
832 AND stable.release = 'jessie'
833 AND stable.subrelease = 'security'
834 AND stable.archive = testing_status.section),
835 (SELECT range_remote FROM nvd_data
836 WHERE cve_name = bug)
837 FROM testing_status
838 WHERE (NOT unstable_vulnerable)
839 AND (NOT testing_security_fixed)"""):
840 if bf.urgencyFiltered(urgency, vulnerable):
841 continue
842 if bf.remoteFiltered(remote):
843 continue
844
845 if pkg_name == old_pkg_name:
846 pkg_name = ''
847 migration = ''
848 else:
849 old_pkg_name = pkg_name
850 migration = A(self.url_testing_status(url, pkg_name),
851 "check")
852 if archive <> 'main':
853 pkg_name = "%s (%s)" % (pkg_name, archive)
854 else:
855 pkg_name = self.make_source_package_ref(url, pkg_name)
856
857 if remote is None:
858 remote = '???'
859 elif remote:
860 remote = 'yes'
861 else:
862 remote = 'no'
863
864 if urgency.startswith('high'):
865 urgency = self.make_red(urgency)
866 elif vulnerable == 2:
867 urgency = self.make_purple(urgency)
868
869 if stable_later:
870 notes = "(fixed in stable?)"
871 else:
872 notes = ''
873
874 yield (pkg_name, migration, self.make_xref(url, bug_name),
875 urgency, remote, notes)
876
877 return self.create_page(
878 url, "Candidates for DTSAs",
879 [P("""The table below lists packages which are fixed
880 in unstable, but unfixed in testing. Use the testing migration
881 checker to find out why they have not entered testing yet."""),
882 make_menu(url.scriptRelative,
883 ("status/release/testing",
884 "List of vulnerable packages in testing")),
885 bf.actions(url), BR(),
886 make_table(gen(),
887 caption=("Package", "Migration", "Bug", "Urgency",
888 "Remote"))])
889
890 def page_status_todo(self, path, params, url):
891 hide_check = params.get('hide_check', False)
892 if hide_check:
893 flags = A(url.updateParamsDict({'hide_check' : None}),
894 'Show "check" TODOs')
895 else:
896 flags = A(url.updateParamsDict({'hide_check' : '1'}),
897 'Hide "check" TODOs')
898
899 def gen():
900 for (bug, description, note) in self.db.getTODOs(hide_check=hide_check):
901 yield self.make_xref(url, bug), description, note
902 return self.create_page(
903 url, 'Bugs with TODO items',
904 [P(flags), make_table(gen(), caption=('Bug', 'Description', 'Note'))])
905
906 def page_status_undetermined(self, path, params, url):
907 def gen():
908 outrel = []
909 old_bug = ''
910 old_pkg = ''
911 old_dsc = ''
912 last_displayed = ''
913 releases = ('sid', 'jessie', 'wheezy', 'squeeze')
914 for (pkg_name, bug_name, release, desc) in self.db.cursor().execute(
915 """SELECT DISTINCT sp.name, st.bug_name, sp.release,
916 bugs.description
917 FROM source_package_status AS st, source_packages AS sp, bugs
918 WHERE st.vulnerable == 2 AND sp.rowid = st.package
919 AND ( sp.release = ? OR sp.release = ? OR sp.release = ?
920 OR sp.release = ? )
921 AND sp.subrelease = '' AND st.bug_name == bugs.name
922 ORDER BY sp.name, st.bug_name""", releases):
923
924 if old_bug == '':
925 old_bug = bug_name
926 old_pkg = pkg_name
927 old_dsc = desc
928 elif old_bug != bug_name:
929 if old_pkg == last_displayed:
930 to_display = ''
931 else:
932 to_display = old_pkg
933 yield to_display, self.make_xref(url, old_bug), old_dsc, ', '.join(outrel)
934 last_displayed = old_pkg
935 old_bug = bug_name
936 old_pkg = pkg_name
937 old_dsc = desc
938 outrel = []
939 outrel.append( release )
940 yield old_pkg, self.make_xref(url, old_bug), old_dsc, ', '.join(outrel)
941
942 return self.create_page(url, 'Packages that may be vulnerable but need to be checked (undetermined issues)',
943 [P("""This page lists packages that may or may not be affected
944 by known issues. This means that some additional work needs to
945 be done to determined whether the package is actually
946 vulnerable or not. This list is a good area for new
947 contributors to make quick and meaningful contributions."""),
948 make_table(gen(), caption=('Package', 'Bug', 'Description', 'Releases'))])
949
950 def page_status_unimportant(self, path, params, url):
951 def gen():
952 outrel = []
953 old_bug = ''
954 old_pkg = ''
955 old_dsc = ''
956 old_name = ''
957 last_displayed = ''
958 releases = ('sid', 'jessie', 'wheezy', 'squeeze')
959 for (pkg_name, bug_name, release, desc) in self.db.cursor().execute(
960 """SELECT DISTINCT sp.name, st.bug_name, sp.release,
961 bugs.description
962 FROM source_package_status AS st, source_packages AS sp, bugs
963 WHERE st.vulnerable > 0 AND sp.rowid = st.package
964 AND ( sp.release = ? OR sp.release = ? OR sp.release = ?
965 OR sp.release = ? ) AND st.urgency == 'unimportant'
966 AND sp.subrelease = '' AND st.bug_name == bugs.name
967 ORDER BY sp.name, st.bug_name""", releases):
968
969 if old_bug == '':
970 old_bug = bug_name
971 old_pkg = pkg_name
972 old_dsc = desc
973 elif old_bug != bug_name:
974 if old_pkg == last_displayed:
975 to_display = ''
976 else:
977 to_display = old_pkg
978 yield to_display, self.make_xref(url, old_bug), old_dsc, ', '.join(outrel)
979 last_displayed = old_pkg
980 old_bug = bug_name
981 old_pkg = pkg_name
982 old_dsc = desc
983 outrel = []
984 outrel.append( release )
985 yield old_pkg, self.make_xref(url, old_bug), old_dsc, ', '.join(outrel)
986
987 return self.create_page(url, 'Packages that have open unimportant issues',
988 [P("""This page lists packages that are affected by issues
989 that are considered unimportant from a security perspective.
990 These issues are thought to be unexploitable or uneffective
991 in most situations (for example, browser denial-of-services)."""),
992 make_table(gen(), caption=('Package', 'Bug', 'Description', 'Releases'))])
993
994 def page_status_itp(self, path, params, url):
995 def gen():
996 old_pkg = ''
997 for pkg, bugs, debian_bugs in self.db.getITPs(self.db.cursor()):
998 if pkg == old_pkg:
999 pkg = ''
1000 else:
1001 old_pkg = pkg
1002 yield (pkg, self.make_xref_list(url, bugs),
1003 self.make_debian_bug_list(url, debian_bugs))
1004 return self.create_page(
1005 url, "ITPs with potential security issues",
1006 [make_table(gen(), caption=("Package", "Issue", "Debian Bugs"),
1007 replacement="No ITP bugs are currently known.")])
1008
1009 def page_data_unknown_packages(self, path, params, url):
1010 def gen():
1011 for name, bugs in self.db.getUnknownPackages(self.db.cursor()):
1012 yield name, self.make_xref_list(url, bugs)
1013 return self.create_page(
1014 url, "Unknown packages",
1015 [P("""Sometimes, a package referenced in a bug report
1016 cannot be found in the database. This can be the result of a spelling
1017 error, or a historic entry refers to a
1018 package which is no longer in the archive."""),
1019 make_table(gen(), caption=("Package", "Bugs"),
1020 replacement="No unknown packages are referenced in the database.")])
1021
1022 def page_data_missing_epochs(self, path, params, url):
1023 def gen():
1024 old_bug = ''
1025 old_pkg = ''
1026 for bug, pkg, ver1, ver2 in self.db.cursor().execute(
1027 """SELECT DISTINCT bug_name, n.package,
1028 n.fixed_version, sp.version
1029 FROM package_notes AS n, source_packages AS sp
1030 WHERE n.package_kind = 'source'
1031 AND n.fixed_version NOT LIKE '%:%'
1032 AND n.fixed_version <> '0'
1033 AND n.bug_origin = ''
1034 AND sp.name = n.package
1035 AND sp.version LIKE '%:%'
1036 ORDER BY bug_name, package"""):
1037 if bug == old_bug:
1038 bug = ''
1039 else:
1040 old_bug = bug
1041 old_pkg = ''
1042 bug = self.make_xref(url, bug)
1043 if pkg == old_pkg:
1044 pkg = ''
1045 else:
1046 old_pkg = pkg
1047 pkg = self.make_source_package_ref(url, pkg)
1048 yield bug, pkg, ver1, ver2
1049
1050 return self.create_page(
1051 url, "Missing epochs in package versions",
1052 [make_table(gen(),
1053 caption=("Bug", "Package", "Version 1", "Version 2"),
1054 replacement="No source package version with missing epochs.")])
1055
1056 def page_data_latently_vulnerable(self, path, params, url):
1057 def gen():
1058 for pkg, bugs in self.db.cursor().execute(
1059 """SELECT package, string_set(bug_name)
1060 FROM package_notes AS p1
1061 WHERE release <> ''
1062 AND (bug_name LIKE 'CVE-%' OR bug_name LIKE 'TEMP-%')
1063 AND NOT EXISTS (SELECT 1 FROM package_notes AS p2
1064 WHERE p2.bug_name = p1.bug_name
1065 AND p2.package = p1.package
1066 AND release = '')
1067 AND EXISTS (SELECT 1 FROM source_packages
1068 WHERE name = p1.package AND release = 'sid')
1069 GROUP BY package
1070 ORDER BY package"""):
1071 pkg = self.make_source_package_ref(url, pkg)
1072 bugs = bugs.split(',')
1073 yield pkg, self.make_xref_list(url, bugs)
1074
1075 def gen_unimportant():
1076 for pkg, bugs in self.db.cursor().execute(
1077 """SELECT package, string_set(bug_name)
1078 FROM package_notes AS p1
1079 WHERE release <> ''
1080 AND urgency <> 'unimportant'
1081 AND (bug_name LIKE 'CVE-%' OR bug_name LIKE 'TEMP-%')
1082 AND EXISTS (SELECT 1 FROM package_notes AS p2
1083 WHERE p2.bug_name = p1.bug_name
1084 AND p2.package = p1.package
1085 AND release = '')
1086 AND NOT EXISTS (SELECT 1 FROM package_notes AS p2
1087 WHERE p2.bug_name = p1.bug_name
1088 AND p2.package = p1.package
1089 AND urgency <> 'unimportant'
1090 AND release = '')
1091 AND EXISTS (SELECT 1 FROM source_packages
1092 WHERE name = p1.package AND release = 'sid')
1093 GROUP BY package
1094 ORDER BY package"""):
1095 pkg = self.make_source_package_ref(url, pkg)
1096 bugs = bugs.split(',')
1097 yield pkg, self.make_xref_list(url, bugs)
1098
1099 return self.create_page(
1100 url, "Latently vulnerable packages in unstable",
1101 [P(
1102 """A package is latently vulnerable in unstable if it is vulnerable in
1103 any release, and there is no package note for the same vulnerability
1104 and package in unstable (and the package is still available in
1105 unstable, of course)."""),
1106 make_table(gen(),
1107 caption=("Package", "Bugs"),
1108 replacement="No latently vulnerable packages were found."),
1109 P(
1110 """The next table lists issues which are marked unimportant for
1111 unstable, but for which release-specific annotations exist which are
1112 not unimportant."""),
1113 make_table(gen_unimportant(),
1114 caption=("Package", "Bugs"),
1115 replacement=
1116 "No packages with unimportant latent vulnerabilities were found."),
1117 ])
1118
1119 def page_data_releases(self, path, params, url):
1120 def gen():
1121 for (rel, subrel, archive, sources, archs) \
1122 in self.db.availableReleases():
1123 if sources:
1124 sources = 'yes'
1125 else:
1126 sources = 'no'
1127 yield rel, subrel, archive, sources, make_list(archs)
1128 return self.create_page(
1129 url, "Available releases",
1130 [P("""The security issue database is checked against
1131 the Debian releases listed in the table below."""),
1132 make_table(gen(),
1133 caption=("Release", "Subrelease", "Archive",
1134 "Sources", "Architectures"))])
1135
1136 def page_data_funny_versions(self, path, params, url):
1137 def gen():
1138 for name, release, archive, version, source_version \
1139 in self.db.getFunnyPackageVersions():
1140 yield name, release, archive, source_version, version
1141
1142 return self.create_page(
1143 url, "Version conflicts between source/binary packages",
1144 [P("""The table below lists source packages
1145 which have a binary package of the same name, but with a different
1146 version. This means that extra care is necessary to determine
1147 the version of a package which has been fixed. (Note that
1148 the bug tracker prefers source versions to binary versions
1149 in this case.)"""),
1150 make_table(gen(),
1151 caption=("Package",
1152 "Release",
1153 "Archive",
1154 "Source Version",
1155 "Binary Version")),
1156 P("""Technically speaking, these version numbering is fine,
1157 but it makes version-based bug tracking quite difficult for these packages."""),
1158 P("""There are many binary packages which are built from source
1159 packages with different version numbering schemes. However, as
1160 long as none of the binary packages carries the same name as the
1161 source package, most confusion is avoided or can be easily
1162 explained.""")])
1163
1164 def page_data_fake_names(self, path, params, url):
1165 def gen(v):
1166 for (bug, description) in self.db.getFakeBugs(vulnerability=v):
1167 yield self.make_xref(url, bug), description
1168 return self.create_page(
1169 url, "Automatically generated issue names",
1170 [P("""Some issues have not been assigned CVE names, but are still
1171 tracked by this database. In this case, the system automatically assigns
1172 a unique name. These names are not stable and can change when the database
1173 is updated, so they should not be used in external references."""),
1174 P('''The automatically generated names come in two flavors:
1175 the first kind starts with the string "''', CODE("TEMP-000000-"),
1176 '''". This means that no Debian bug has been assigned to this
1177 issue (or a bug has been created and is not recorded in this database).
1178 In the second kind of names, there is a Debian bug for the issue, and the "''',
1179 CODE("000000"), '''"part of the name is replaced with the
1180 Debian bug number.'''),
1181 H2("With unfixed issues"), make_table(gen(1), caption=("Bug", "Description")),
1182 H2("The rest"), make_table(gen(0), caption=("Bug", "Description")),
1183 ])
1184
1185 def page_data_pts(self, path, params, url):
1186 data = []
1187 for pkg, bugs in self.db.cursor().execute(
1188 """SELECT package, COUNT(DISTINCT bug) FROM
1189 (SELECT package, bug, urgency FROM stable_status
1190 UNION ALL SELECT DISTINCT sp.name, st.bug_name, st.urgency
1191 FROM source_package_status AS st, source_packages AS sp
1192 WHERE st.vulnerable AND st.urgency <> 'unimportant'
1193 AND sp.rowid = st.package AND sp.release = 'sid'
1194 AND sp.subrelease = '') x WHERE urgency <> 'unimportant'
1195 GROUP BY package ORDER BY package"""):
1196 data.append(pkg)
1197 data.append(':')
1198 data.append(str(bugs))
1199 data.append('\n')
1200 return BinaryResult(''.join(data))
1201
1202 def page_debsecan(self, path, params, url):
1203 obj = '/'.join(path)
1204 data = self.db.getDebsecan(obj)
1205 if data:
1206 return BinaryResult(data)
1207 else:
1208 return self.create_page(
1209 url, "Object not found",
1210 [P("The requested debsecan object has not been found.")],
1211 status=404)
1212
1213 def create_page(self, url, title, body, search_in_page=False, status=200):
1214 append = body.append
1215 append(HR())
1216 if not search_in_page:
1217 append(self.make_search_button(url))
1218 append(P(A(url.scriptRelative(""), "Home"),
1219 " - ", A(url.absolute("http://secure-testing.debian.net/"),
1220 "Testing Security Team"),
1221 " - ", A(url.absolute("https://www.debian.org/security/"),
1222 "Debian Security"),
1223 " - ", A(url.absolute("https://anonscm.debian.org/viewvc/secure-testing/bin/tracker_service.py?view=markup"),
1224 "Source"),
1225 " ", A(url.absolute("svn://anonscm.debian.org/svn/secure-testing"), "(SVN)"),
1226 ))
1227 if search_in_page:
1228 on_load = "selectSearch()"
1229 else:
1230 on_load = None
1231 return HTMLResult(self.add_title(title, body,
1232 head_contents=self.head_contents,
1233 body_attribs={'onload': on_load}),
1234 doctype=self.html_dtd(),
1235 status=status)
1236
1237 def make_search_button(self, url):
1238 return FORM("Search for package or bug name: ",
1239 INPUT(type='text', name='query',
1240 onkeyup="onSearch(this.value)",
1241 onmousemove="onSearch(this.value)"),
1242 INPUT(type='submit', value='Go'),
1243 ' ',
1244 A(url.scriptRelative("data/report"), "Reporting problems"),
1245 method='get',
1246 action=url.scriptRelative(''))
1247
1248 def url_cve(self, url, name):
1249 return url.absolute("https://cve.mitre.org/cgi-bin/cvename.cgi",
1250 name=name)
1251 def url_nvd(self, url, name):
1252 return url.absolute("https://web.nvd.nist.gov/view/vuln/detail",
1253 vulnId=name)
1254 def url_osssec_bug(self, url, name):
1255 return url.absolute("https://marc.info/", l="oss-security", s=name)
1256 def url_osvdb_bug(self, url, name):
1257 return url.absoluteDict("http://osvdb.org/search/search", {"search[refid]": name})
1258 def url_edb_bug(self, url, name):
1259 name = name[len('CVE-'):] if name.startswith('CVE-') else name
1260 return url.absolute("http://www.exploit-db.com/search/", action="search", filter_cve=name)
1261 def url_rhbug(self, url, name):
1262 return url.absolute("https://bugzilla.redhat.com/show_bug.cgi",
1263 id=name)
1264 def url_ubuntu_bug(self, url, name):
1265 return url.absolute("http://people.canonical.com/~ubuntu-security/cve/%s" % name)
1266 def url_gentoo_bug(self, url, name):
1267 return url.absolute("https://bugs.gentoo.org/show_bug.cgi", id=name)
1268 def url_suse_bug(self, url, name):
1269 return url.absolute("https://bugzilla.novell.com/show_bug.cgi",
1270 id=name)
1271 def url_mageia_bug(self, url, name):
1272 return url.absolute("https://advisories.mageia.org/%s.html" % name)
1273
1274 def url_dsa(self, url, dsa, re_dsa=re.compile(r'^DSA-(\d+)(?:-\d+)?$')):
1275 match = re_dsa.match(dsa)
1276 if match:
1277 # We must determine the year because there is no generic URL.
1278 (number,) = match.groups()
1279 for (date,) in self.db.cursor().execute(
1280 "SELECT release_date FROM bugs WHERE name = ?", (dsa,)):
1281 (y, m, d) = date.split('-')
1282 return url.absolute("https://www.debian.org/security/%d/dsa-%d"
1283 % (int(y), int(number)))
1284 return None
1285
1286 def url_debian_bug(self, url, debian):
1287 return url.absolute("https://bugs.debian.org/cgi-bin/bugreport.cgi",
1288 bug=str(debian))
1289 def url_debian_bug_pkg(self, url, debian):
1290 return url.absolute("https://bugs.debian.org/cgi-bin/pkgreport.cgi",
1291 pkg=debian)
1292 def url_pts(self, url, package):
1293 return url.absolute("https://packages.qa.debian.org/common/index.html",
1294 src=package)
1295 def url_testing_status(self, url, package):
1296 return url.absolute("https://release.debian.org/migration/testing.pl",
1297 package=package)
1298 def url_source_package(self, url, package, full=False):
1299 if full:
1300 return url.scriptRelativeFull("source-package/" + package)
1301 else:
1302 return url.scriptRelative("source-package/" + package)
1303
1304 def make_xref(self, url, name):
1305 return A(url.scriptRelative(name), name)
1306
1307 def make_xref_list(self, url, lst, separator=', '):
1308 return make_list(map(lambda x: self.make_xref(url, x), lst), separator)
1309
1310 def make_debian_bug(self, url, debian):
1311 return A(self.url_debian_bug(url, debian), str(debian))
1312 def make_debian_bug_list(self, url, lst):
1313 return make_list(map(lambda x: self.make_debian_bug(url, x), lst))
1314
1315 def make_cve_ref(self, url, cve, name=None):
1316 if name is None:
1317 name = cve
1318 return A(self.url_cve(url, cve), name)
1319
1320 def make_nvd_ref(self, url, cve, name=None):
1321 if name is None:
1322 name = cve
1323 return A(self.url_nvd(url, cve), name)
1324
1325 def make_osssec_bug_ref(self, url, cve, name=None):
1326 if name is None:
1327 name = cve
1328 return A(self.url_osssec_bug(url, cve), name)
1329
1330 def make_osvdb_bug_ref(self, url, cve, name=None):
1331 if name is None:
1332 name = cve
1333 return A(self.url_osvdb_bug(url, cve), name)
1334
1335 def make_edb_bug_ref(self, url, cve, name=None):
1336 if name is None:
1337 name = cve
1338 return A(self.url_edb_bug(url, cve), name)
1339
1340 def make_rhbug_ref(self, url, cve, name=None):
1341 if name is None:
1342 name = cve
1343 return A(self.url_rhbug(url, cve), name)
1344
1345 def make_ubuntu_bug_ref(self, url, cve, name=None):
1346 if name is None:
1347 name = cve
1348 return A(self.url_ubuntu_bug(url, cve), name)
1349
1350 def make_gentoo_bug_ref(self, url, cve, name=None):
1351 if name is None:
1352 name = cve
1353 return A(self.url_gentoo_bug(url, cve), name)
1354
1355 def make_suse_bug_ref(self, url, cve, name=None):
1356 if name is None:
1357 name = cve
1358 return A(self.url_suse_bug(url, cve), name)
1359
1360 def make_mageia_bug_ref(self, url, cve, name=None):
1361 if name is None:
1362 name = cve
1363 return A(self.url_mageia_bug(url, cve), name)
1364
1365 def make_dsa_ref(self, url, dsa, name=None):
1366 if name is None:
1367 name = dsa
1368 u = self.url_dsa(url, dsa)
1369 if u:
1370 return A(u, name)
1371 else:
1372 return name
1373
1374 def make_pts_ref(self, url, pkg, name=None):
1375 if name is None:
1376 name = pkg
1377 return A(self.url_pts(url, pkg), name)
1378
1379 def make_source_package_ref(self, url, pkg, title=None):
1380 if title is None:
1381 title = pkg
1382 return A(self.url_source_package(url, pkg), title)
1383
1384 def make_red(self, contents):
1385 return SPAN(contents, _class="red")
1386
1387 def make_purple(self, contents):
1388 return SPAN(contents, _class="purple")
1389
1390 def make_green(self, contents):
1391 return SPAN(contents, _class="green")
1392
1393 def make_dangerous(self, contents):
1394 return SPAN(contents, _class="dangerous")
1395
1396 def pre_dispatch(self):
1397 pass
1398
1399 TrackerService(socket_name, db_name).run()

Properties

Name Value
svn:mime-type text/script

  ViewVC Help
Powered by ViewVC 1.1.5