| 14 |
import security_db |
import security_db |
| 15 |
from web_support import * |
from web_support import * |
| 16 |
|
|
| 17 |
|
class BugFilter: |
| 18 |
|
def __init__(self, params): |
| 19 |
|
self.hide_medium_urgency = int(params.get('hide_medium_urgency', |
| 20 |
|
(0,))[0]) |
| 21 |
|
self.hide_non_remote = int(params.get('hide_non_remote', |
| 22 |
|
(0,))[0]) |
| 23 |
|
|
| 24 |
|
def actions(self, url): |
| 25 |
|
"""Returns a HTML snippet which can be used to change the filter.""" |
| 26 |
|
if self.hide_medium_urgency: |
| 27 |
|
urg = A(url.updateParams(hide_medium_urgency=None), |
| 28 |
|
'Show lower urgencies') |
| 29 |
|
else: |
| 30 |
|
urg = A(url.updateParams(hide_medium_urgency='1'), |
| 31 |
|
'Hide lower urgencies') |
| 32 |
|
if self.hide_non_remote: |
| 33 |
|
rem = A(url.updateParams(hide_non_remote=None), |
| 34 |
|
'Show local vulnerabilities') |
| 35 |
|
else: |
| 36 |
|
rem = A(url.updateParams(hide_non_remote='1'), |
| 37 |
|
'Hide local vulnerabilities') |
| 38 |
|
return P(urg, ' ', rem) |
| 39 |
|
|
| 40 |
|
def urgencyFiltered(self, urg): |
| 41 |
|
"""Returns True if the urgency urg is filtered.""" |
| 42 |
|
return self.hide_medium_urgency and urg not in ("high", "unknown", "") |
| 43 |
|
|
| 44 |
|
def remoteFiltered(self, remote): |
| 45 |
|
"""Returns True if the attack range is filtered.""" |
| 46 |
|
return remote is not None and self.hide_non_remote and not remote |
| 47 |
|
|
| 48 |
class TrackerService(WebService): |
class TrackerService(WebService): |
| 49 |
head_contents = compose(STYLE( |
head_contents = compose(STYLE( |
| 50 |
"""h1 { font-size : 144%; } |
"""h1 { font-size : 144%; } |
| 136 |
('data/releases', |
('data/releases', |
| 137 |
'Covered Debian releases and architectures (slow)'), |
'Covered Debian releases and architectures (slow)'), |
| 138 |
self.make_search_button(url)), |
self.make_search_button(url)), |
| 139 |
P("""(You can enter CAN/CVE names, Debian bug numbers and package |
P("""(You can enter CVE names, Debian bug numbers and package |
| 140 |
names in the search forms.)"""), |
names in the search forms.)"""), |
| 141 |
|
|
| 142 |
H2("A few notes on data sources"), |
H2("Data sources"), |
| 143 |
P("""Data in this tracker comes solely from the bug database |
P("""Data in this tracker comes solely from the bug database |
| 144 |
which is maintained by Debian's testing security team in their |
which is maintained by Debian's testing security team in their |
| 145 |
Subversion repository. All external data (this includes |
Subversion repository. All external data (this includes |
| 149 |
P("""At the moment, the database only contains information which is |
P("""At the moment, the database only contains information which is |
| 150 |
relevant for tracking the security status of the stable, testing and |
relevant for tracking the security status of the stable, testing and |
| 151 |
unstable suites. This means that data for oldstable is likely wrong."""), |
unstable suites. This means that data for oldstable is likely wrong."""), |
| 152 |
|
P('Data marked "NVD" comes from the ', |
| 153 |
|
A(url.absolute('http://nvd.nist.gov/'), |
| 154 |
|
'National Vulnerability Database'), |
| 155 |
|
' maintained by NIST.'), |
| 156 |
|
|
| 157 |
H2("External interfaces"), |
H2("External interfaces"), |
| 158 |
P("""If you want to automatically open a relevant web page for |
P("""If you want to automatically open a relevant web page for |
| 203 |
return self.page_not_found(url, obj) |
return self.page_not_found(url, obj) |
| 204 |
|
|
| 205 |
def page_bug(self, url, name, redirect): |
def page_bug(self, url, name, redirect): |
| 206 |
|
# FIXME: Normalize CAN-* to CVE-* when redirecting. Too many |
| 207 |
|
# people still use CAN. |
| 208 |
|
if redirect and name[0:4] == 'CAN-': |
| 209 |
|
name = 'CVE-' + name[4:] |
| 210 |
|
|
| 211 |
cursor = self.db.cursor() |
cursor = self.db.cursor() |
| 212 |
try: |
try: |
| 213 |
bug = bugs.BugFromDB(cursor, name) |
bug = bugs.BugFromDB(cursor, name) |
| 214 |
except ValueError: |
except ValueError: |
| 215 |
if redirect: |
if redirect: |
| 216 |
if name[0:4] in ('CAN-', 'CVE-'): |
if name[0:4] == 'CVE-': |
| 217 |
return RedirectResult(self.url_cve(url, name), |
return RedirectResult(self.url_cve(url, name), |
| 218 |
permanent=False) |
permanent=False) |
| 219 |
return self.page_not_found(url, name) |
return self.page_not_found(url, name) |
| 227 |
yield B("Name"), bug.name |
yield B("Name"), bug.name |
| 228 |
|
|
| 229 |
source = bug.name.split('-')[0] |
source = bug.name.split('-')[0] |
| 230 |
if source in ('CAN', 'CVE'): |
if source == 'CVE': |
| 231 |
source_xref = compose(self.make_cve_ref(url, bug.name, 'CVE'), |
source_xref = compose(self.make_cve_ref(url, bug.name, 'CVE'), |
| 232 |
" (", |
" (", |
| 233 |
self.make_nvd_ref(url, bug.name, |
self.make_nvd_ref(url, bug.name, |
| 495 |
this package, but still reference it.""")]) |
this package, but still reference it.""")]) |
| 496 |
|
|
| 497 |
def page_status_release_stable(self, path, params, url): |
def page_status_release_stable(self, path, params, url): |
| 498 |
|
bf = BugFilter(params) |
| 499 |
|
|
| 500 |
def gen(): |
def gen(): |
| 501 |
old_pkg_name = '' |
old_pkg_name = '' |
| 502 |
for (pkg_name, bug_name, archive, urgency, remote) in \ |
for (pkg_name, bug_name, archive, urgency, remote) in \ |
| 503 |
self.db.cursor().execute( |
self.db.cursor().execute( |
| 504 |
"""SELECT package, bug, section, urgency, remote |
"""SELECT package, bug, section, urgency, remote |
| 505 |
FROM stable_status"""): |
FROM stable_status"""): |
| 506 |
|
if bf.urgencyFiltered(urgency): |
| 507 |
|
continue |
| 508 |
|
if bf.remoteFiltered(remote): |
| 509 |
|
continue |
| 510 |
|
|
| 511 |
if pkg_name == old_pkg_name: |
if pkg_name == old_pkg_name: |
| 512 |
pkg_name = '' |
pkg_name = '' |
| 513 |
else: |
else: |
| 531 |
|
|
| 532 |
return self.create_page( |
return self.create_page( |
| 533 |
url, 'Vulnerable source packages in the stable suite', |
url, 'Vulnerable source packages in the stable suite', |
| 534 |
[make_table(gen(), caption=("Package", "Bug", "Urgency", |
[bf.actions(url), |
| 535 |
|
make_table(gen(), caption=("Package", "Bug", "Urgency", |
| 536 |
"Remote"))]) |
"Remote"))]) |
| 537 |
|
|
| 538 |
def page_status_release_testing(self, path, params, url): |
def page_status_release_testing(self, path, params, url): |
| 539 |
|
bf = BugFilter(params) |
| 540 |
|
|
| 541 |
def gen(): |
def gen(): |
| 542 |
old_pkg_name = '' |
old_pkg_name = '' |
| 543 |
for (pkg_name, bug_name, archive, urgency, |
for (pkg_name, bug_name, archive, urgency, |
| 545 |
"""SELECT package, bug, section, urgency, unstable_vulnerable, |
"""SELECT package, bug, section, urgency, unstable_vulnerable, |
| 546 |
testing_security_fixed, remote |
testing_security_fixed, remote |
| 547 |
FROM testing_status"""): |
FROM testing_status"""): |
| 548 |
|
if bf.urgencyFiltered(urgency): |
| 549 |
|
continue |
| 550 |
|
if bf.remoteFiltered(remote): |
| 551 |
|
continue |
| 552 |
|
|
| 553 |
if pkg_name == old_pkg_name: |
if pkg_name == old_pkg_name: |
| 554 |
pkg_name = '' |
pkg_name = '' |
| 555 |
else: |
else: |
| 582 |
url, 'Vulnerable source packages in the testing suite', |
url, 'Vulnerable source packages in the testing suite', |
| 583 |
[make_menu(url.scriptRelative, |
[make_menu(url.scriptRelative, |
| 584 |
("status/dtsa-candidates", "Candidates for DTSAs")), |
("status/dtsa-candidates", "Candidates for DTSAs")), |
| 585 |
|
bf.actions(url), |
| 586 |
make_table(gen(), caption=("Package", "Bug", "Urgency", |
make_table(gen(), caption=("Package", "Bug", "Urgency", |
| 587 |
"Remote"))]) |
"Remote"))]) |
| 588 |
|
|
| 589 |
def page_status_release_unstable(self, path, params, url): |
def page_status_release_unstable(self, path, params, url): |
| 590 |
|
bf = BugFilter(params) |
| 591 |
|
|
| 592 |
def gen(): |
def gen(): |
| 593 |
old_pkg_name = '' |
old_pkg_name = '' |
| 594 |
for (pkg_name, bug_name, section, urgency) \ |
for (pkg_name, bug_name, section, urgency, remote) \ |
| 595 |
in self.db.cursor().execute( |
in self.db.cursor().execute( |
| 596 |
"""SELECT DISTINCT sp.name, st.bug_name, |
"""SELECT DISTINCT sp.name, st.bug_name, |
| 597 |
sp.archive, st.urgency |
sp.archive, st.urgency, |
| 598 |
|
(SELECT range_remote FROM nvd_data |
| 599 |
|
WHERE cve_name = st.bug_name) |
| 600 |
FROM source_package_status AS st, source_packages AS sp |
FROM source_package_status AS st, source_packages AS sp |
| 601 |
WHERE st.vulnerable AND st.urgency <> 'unimportant' |
WHERE st.vulnerable AND st.urgency <> 'unimportant' |
| 602 |
AND sp.rowid = st.package AND sp.release = 'sid' |
AND sp.rowid = st.package AND sp.release = 'sid' |
| 603 |
AND sp.subrelease = '' |
AND sp.subrelease = '' |
| 604 |
ORDER BY sp.name, st.bug_name"""): |
ORDER BY sp.name, st.bug_name"""): |
| 605 |
|
if bf.urgencyFiltered(urgency): |
| 606 |
|
continue |
| 607 |
|
if bf.remoteFiltered(remote): |
| 608 |
|
continue |
| 609 |
|
|
| 610 |
if pkg_name == old_pkg_name: |
if pkg_name == old_pkg_name: |
| 611 |
pkg_name = '' |
pkg_name = '' |
| 612 |
else: |
else: |
| 616 |
else: |
else: |
| 617 |
pkg_name = self.make_xref(url, pkg_name) |
pkg_name = self.make_xref(url, pkg_name) |
| 618 |
|
|
| 619 |
|
if remote is None: |
| 620 |
|
remote = '' |
| 621 |
|
elif remote: |
| 622 |
|
remote = 'yes' |
| 623 |
|
else: |
| 624 |
|
remote = 'no' |
| 625 |
|
|
| 626 |
if urgency == 'unknown': |
if urgency == 'unknown': |
| 627 |
urgency = '' |
urgency = '' |
| 628 |
elif urgency == 'high': |
elif urgency == 'high': |
| 629 |
urgency = self.make_red(urgency) |
urgency = self.make_red(urgency) |
| 630 |
|
|
| 631 |
yield pkg_name, self.make_xref(url, bug_name), urgency |
yield pkg_name, self.make_xref(url, bug_name), urgency, remote |
| 632 |
|
|
| 633 |
|
|
| 634 |
return self.create_page( |
return self.create_page( |
| 638 |
fixed source version has been uploaded to the archive, even |
fixed source version has been uploaded to the archive, even |
| 639 |
if there are still some vulnerably binary packages present |
if there are still some vulnerably binary packages present |
| 640 |
in the archive."""), |
in the archive."""), |
| 641 |
make_table(gen(), caption=('Package', 'Bug', 'Urgency'))]) |
bf.actions(url), |
| 642 |
|
make_table(gen(), caption=('Package', 'Bug', 'Urgency', |
| 643 |
|
'Remote'))]) |
| 644 |
|
|
| 645 |
def page_status_dtsa_candidates(self, path, params, url): |
def page_status_dtsa_candidates(self, path, params, url): |
| 646 |
|
bf = BugFilter(params) |
| 647 |
|
|
| 648 |
def gen(): |
def gen(): |
| 649 |
old_pkg_name = '' |
old_pkg_name = '' |
| 650 |
for (pkg_name, bug_name, archive, urgency, stable_later) \ |
for (pkg_name, bug_name, archive, urgency, stable_later, |
| 651 |
|
remote) \ |
| 652 |
in self.db.cursor().execute( |
in self.db.cursor().execute( |
| 653 |
"""SELECT package, bug, section, urgency, |
"""SELECT package, bug, section, urgency, |
| 654 |
(SELECT testing.version_id < stable.version_id |
(SELECT testing.version_id < stable.version_id |
| 660 |
AND stable.name = testing_status.package |
AND stable.name = testing_status.package |
| 661 |
AND stable.release = 'sarge' |
AND stable.release = 'sarge' |
| 662 |
AND stable.subrelease = 'security' |
AND stable.subrelease = 'security' |
| 663 |
AND stable.archive = testing_status.section) |
AND stable.archive = testing_status.section), |
| 664 |
|
(SELECT range_remote FROM nvd_data |
| 665 |
|
WHERE cve_name = bug) |
| 666 |
FROM testing_status |
FROM testing_status |
| 667 |
WHERE (NOT unstable_vulnerable) |
WHERE (NOT unstable_vulnerable) |
| 668 |
AND (NOT testing_security_fixed)"""): |
AND (NOT testing_security_fixed)"""): |
| 669 |
|
if bf.urgencyFiltered(urgency): |
| 670 |
|
continue |
| 671 |
|
if bf.remoteFiltered(remote): |
| 672 |
|
continue |
| 673 |
|
|
| 674 |
if pkg_name == old_pkg_name: |
if pkg_name == old_pkg_name: |
| 675 |
pkg_name = '' |
pkg_name = '' |
| 676 |
migration = '' |
migration = '' |
| 683 |
else: |
else: |
| 684 |
pkg_name = self.make_source_package_ref(url, pkg_name) |
pkg_name = self.make_source_package_ref(url, pkg_name) |
| 685 |
|
|
| 686 |
|
if remote is None: |
| 687 |
|
remote = '' |
| 688 |
|
elif remote: |
| 689 |
|
remote = 'yes' |
| 690 |
|
else: |
| 691 |
|
remote = 'no' |
| 692 |
|
|
| 693 |
if urgency == 'unknown': |
if urgency == 'unknown': |
| 694 |
urgency = '' |
urgency = '' |
| 695 |
elif urgency == 'high': |
elif urgency == 'high': |
| 701 |
notes = '' |
notes = '' |
| 702 |
|
|
| 703 |
yield (pkg_name, migration, self.make_xref(url, bug_name), |
yield (pkg_name, migration, self.make_xref(url, bug_name), |
| 704 |
urgency, notes) |
urgency, remote, notes) |
| 705 |
|
|
| 706 |
return self.create_page( |
return self.create_page( |
| 707 |
url, "Candidates for DTSAs", |
url, "Candidates for DTSAs", |
| 712 |
make_menu(url.scriptRelative, |
make_menu(url.scriptRelative, |
| 713 |
("status/release/testing", |
("status/release/testing", |
| 714 |
"List of vulnerable packages in testing")), |
"List of vulnerable packages in testing")), |
| 715 |
|
bf.actions(url), |
| 716 |
make_table(gen(), |
make_table(gen(), |
| 717 |
caption=("Package", "Migration", "Bug", "Urgency"))]) |
caption=("Package", "Migration", "Bug", "Urgency", |
| 718 |
|
"Remote"))]) |
| 719 |
|
|
| 720 |
def page_status_todo(self, path, params, url): |
def page_status_todo(self, path, params, url): |
| 721 |
def gen(): |
def gen(): |