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

Diff of /bin/tracker_service.py

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 2489 by fw, Thu Oct 20 09:03:51 2005 UTC revision 12985 by fw, Sun Oct 11 12:04:15 2009 UTC
# Line 2  Line 2 
2    
3  import sys  import sys
4  sys.path.insert(0,'../lib/python')  sys.path.insert(0,'../lib/python')
   
 if len(sys.argv) <> 3:  
     print "usage: python tracker_serivce.py SOCKET-PATH DATABASE-PATH"  
     sys.exit(1)  
 socket_name = sys.argv[1]  
 db_name = sys.argv[2]  
   
5  import bugs  import bugs
6  import re  import re
7  import security_db  import security_db
8  from web_support import *  from web_support import *
9    
10  class TrackerService(WebService):  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 = [("hide_medium_urgency", "lower urgencies"),
28                               ("hide_non_remote", "local vulnerabilities")]
29        def __init__(self, params, action_list=None):
30            if action_list is None:
31                self.action_list = self.default_action_list
32            else:
33                self.action_list = action_list
34            self.params = {}
35            for (prop, desc) in self.action_list:
36                self.params[prop] = int(params.get(prop, (0,))[0])
37    
38        def actions(self, url):
39            """Returns a HTML snippet which can be used to change the filter."""
40    
41            l = []
42            for (prop, desc) in self.action_list:
43                if self.params[prop]:
44                    a = A(url.updateParamsDict({prop : None}),
45                          'Show ' + desc)
46                else:
47                    a = A(url.updateParamsDict({prop : '1'}),
48                          'Hide ' + desc)
49                l.append(a)
50                l.append(' ')
51    
52            return apply(P, l[:-1])
53    
54        def urgencyFiltered(self, urg):
55            """Returns True if the urgency urg is filtered."""
56            return self.params['hide_medium_urgency'] \
57                   and urg not in ("high", "unknown", "")
58    
59        def remoteFiltered(self, remote):
60            """Returns True if the attack range is filtered."""
61            return remote is not None and self.params['hide_non_remote'] \
62                   and not remote
63    
64    class BugFilterNoDSA(BugFilter):
65        def __init__(self, params):
66            BugFilter.__init__(self, params, self.default_action_list
67                + [('hide_nodsa', 'non-DSA vulnerabilities')])
68            self.hide_nodsa = int(params.get('hide_nodsa',(0,))[0])
69    
70        def nodsaFiltered(self, nodsa):
71            """Returns True if no DSA will be issued for the bug."""
72            return nodsa and self.params['hide_nodsa']
73    
74    class TrackerService(webservice_base_class):
75      head_contents = compose(STYLE(      head_contents = compose(STYLE(
76          """h1 { font-size : 144%; }          """h1 { font-size : 144%; }
77  h2 { font-size : 120%; }  h2 { font-size : 120%; }
# Line 46  function onSearch(query) { Line 103  function onSearch(query) {
103  ''')).toHTML()  ''')).toHTML()
104    
105      def __init__(self, socket_name, db_name):      def __init__(self, socket_name, db_name):
106          WebService.__init__(self, socket_name)          webservice_base_class.__init__(self, socket_name)
107          self.db = security_db.DB(db_name)          self.db = security_db.DB(db_name)
108          self.register('', self.page_home)          self.register('', self.page_home)
109          self.register('*', self.page_object)          self.register('*', self.page_object)
110          self.register('redirect/*', self.page_redirect)          self.register('redirect/*', self.page_redirect)
111          self.register('source-package/*', self.page_source_package)          self.register('source-package/*', self.page_source_package)
112          self.register('binary-package/*', self.page_binary_package)          self.register('binary-package/*', self.page_binary_package)
113            self.register('status/release/oldstable',
114                          self.page_status_release_oldstable)
115          self.register('status/release/stable', self.page_status_release_stable)          self.register('status/release/stable', self.page_status_release_stable)
116            self.register('status/release/stable-backports',
117                          self.page_status_release_stable_backports)
118            self.register('status/release/oldstable-backports',
119                          self.page_status_release_oldstable_backports)
120          self.register('status/release/testing',          self.register('status/release/testing',
121                        self.page_status_release_testing)                        self.page_status_release_testing)
122          self.register('status/release/unstable',          self.register('status/release/unstable',
# Line 64  function onSearch(query) { Line 127  function onSearch(query) {
127          self.register('status/itp', self.page_status_itp)          self.register('status/itp', self.page_status_itp)
128          self.register('data/unknown-packages', self.page_data_unknown_packages)          self.register('data/unknown-packages', self.page_data_unknown_packages)
129          self.register('data/missing-epochs', self.page_data_missing_epochs)          self.register('data/missing-epochs', self.page_data_missing_epochs)
130            self.register('data/latently-vulnerable',
131                          self.page_data_latently_vulnerable)
132          self.register('data/releases', self.page_data_releases)          self.register('data/releases', self.page_data_releases)
133          self.register('data/funny-versions', self.page_data_funny_versions)          self.register('data/funny-versions', self.page_data_funny_versions)
134            self.register('data/fake-names', self.page_data_fake_names)
135            self.register('debsecan/**', self.page_debsecan)
136            self.register('data/report', self.page_report)
137    
138      def page_home(self, path, params, url):      def page_home(self, path, params, url):
139          query = params.get('query', ('',))[0]          query = params.get('query', ('',))[0]
# Line 78  function onSearch(query) { Line 146  function onSearch(query) {
146          return self.create_page(          return self.create_page(
147              url, 'Security Bug Tracker',              url, 'Security Bug Tracker',
148              [P(              [P(
149              """This is the experimental issue tracker for Debian's testing              """The data in this tracker comes solely from the bug database maintained
150  security team.  Keep in mind that this is merely a prototype.  by Debian's security team located in the testing-security Subversion """,
151  Please report any problems to """,              A("http://svn.debian.org/wsvn/secure-testing/data", "repository"),
152              A("mailto:fw@deneb.enyo.de", "Florian Weimer"),              """.  The data represented here is derived from: """,
153              """.Note that some of the data presented here is known              A("http://www.debian.org/security/#DSAS", "DSAs"),
154  to be wrong (see below), but the data for the testing suite              """ issued by the Security Team; issues tracked in the """,
155  should be fine."""),              A("http://cve.mitre.org/cve/", "CVE database"),
156                                   make_menu(              """, issues tracked in the """,
157                A("http://nvd.nist.gov/", "National Vulnerability Database"),
158                """ (NVD), maintained by NIST; and security issues
159    discovered in Debian packages as reported in the BTS."""),
160                 P("""All external data (including Debian bug reports and official Debian
161    security advisories) must be added to this database before it appears
162    here. Please help us keep this information up-to-date by """,
163                   A(url.scriptRelative("data/report"), "reporting"),
164                   """ any discrepancies or change of states that you are
165    aware of and/or help us improve the quality of this information by """,
166                   A(url.scriptRelative("data/report"), "participating"),
167                   "."),
168                make_menu(
169              url.scriptRelative,              url.scriptRelative,
             ('status/release/stable',  
              'Vulnerable packages in the stable suite'),  
             ('status/release/testing',  
              'Vulnerable packages in the testing suite'),  
170              ('status/release/unstable',              ('status/release/unstable',
171               'Vulnerable packages in the unstable suite'),               'Vulnerable packages in the unstable suite'),
172                ('status/release/testing',
173                 'Vulnerable packages in the testing suite'),
174                ('status/release/stable',
175                 'Vulnerable packages in the stable suite'),
176                ('status/release/oldstable',
177                 'Vulnerable packages in the old stable suite'),
178                ('status/release/stable-backports',
179                 'Vulnerable packages in backports for stable'),
180                ('status/release/oldstable-backports',
181                 'Vulnerable packages in backports for oldstable'),
182              ('status/dtsa-candidates', "Candidates for DTSAs"),              ('status/dtsa-candidates', "Candidates for DTSAs"),
183              ('status/todo', 'TODO items'),              ('status/todo', 'TODO items'),
184              ('status/itp', 'ITPs with potential security issues'),              ('status/itp', 'ITPs with potential security issues'),
185              ('data/unknown-packages',              ('data/unknown-packages',
186               'Packages names not found in the archive'),               'Packages names not found in the archive'),
187                ('data/fake-names', 'Tracked issues without a CVE name'),
188              ('data/missing-epochs',              ('data/missing-epochs',
189               'Package versions which might lack an epoch'),               'Package versions which might lack an epoch'),
190                ('data/latently-vulnerable',
191                 'Packages which are latently vulnerable in unstable'),
192              ('data/funny-versions',              ('data/funny-versions',
193               'Packages with strange version numbers'),               'Packages with strange version numbers'),
194              ('data/releases',              ('data/releases',
195               'Covered Debian releases and architectures (slow)'),               'Covered Debian releases and architectures (slow)'),
196              self.make_search_button(url)),              self.make_search_button(url)),
197               P("""(You can enter CAN/CVE names, Debian bug numbers and package               P("""(You can enter CVE names, Debian bug numbers and package
198  names in the search forms.)"""),  names in the search forms.)"""),
199    
              H2("Data sources"),  
              P("""Data in this tracker comes solely from the bug database  
 which is maintained by Debian's testing security team in their  
 Subversion repository.  All external data (this includes  
 Debian bug reports and official Debian security advisories)  
 must be added to this database before it appears here, and there  
 can be some delay before this happens."""),  
              P("""At the moment, the database only contains information which is  
 relevant for tracking the security status of the stable, testing and  
 unstable suites.  This means that data for oldstable is likely wrong."""),  
              P('Data marked "NVD" comes from the ',  
                A(url.absolute('http://nvd.nist.gov/'),  
                  'National Vulnerability Database'),  
                ' maintained by NIST.'),  
   
200               H2("External interfaces"),               H2("External interfaces"),
201               P("""If you want to automatically open a relevant web page for               P("""If you want to automatically open a relevant web page for
202  some object, use the """,  some object, use the """,
# Line 146  data source.""")], Line 220  data source.""")],
220          if not obj:          if not obj:
221              # Redirect to start page.              # Redirect to start page.
222              return RedirectResult(url.scriptRelativeFull(""))              return RedirectResult(url.scriptRelativeFull(""))
   
         if 'A' <= obj[0] <= 'Z':  
             # Bug names start with a capital letter.  
             return self.page_bug(url, obj, redirect)  
223    
224            # Attempt to decode a bug number.  TEMP-nnn bugs (but not
225            # TEMP-nnn-mmm bugs) are treated as bug references, too.
226          bugnumber = 0          bugnumber = 0
227            fake_bug = False
228          try:          try:
229              bugnumber = int(obj)              if obj[0:5] == 'FAKE-' or obj[0:5] == 'TEMP-':
230                    bugnumber = int(obj[5:])
231                    fake_bug = True
232                else:
233                    bugnumber = int(obj)
234          except ValueError:          except ValueError:
235              pass              pass
236          if bugnumber:          if bugnumber:
237              buglist = list(self.db.getBugsFromDebianBug(c, bugnumber))              buglist = list(self.db.getBugsFromDebianBug(c, bugnumber))
238              if buglist:              if buglist:
239                  return self.page_debian_bug(url, bugnumber, buglist)                  return self.page_debian_bug(url, bugnumber, buglist, fake_bug)
240              if redirect:              if redirect:
241                  return RedirectResult(self.url_debian_bug(url, str(bugnumber)),                  return RedirectResult(self.url_debian_bug(url, str(bugnumber)),
242                                        permanent=False)                                        permanent=False)
243    
244            if 'A' <= obj[0] <= 'Z':
245                # Bug names start with a capital letter.
246                return self.page_bug(url, obj, redirect)
247    
248          if self.db.isSourcePackage(c, obj):          if self.db.isSourcePackage(c, obj):
249              return RedirectResult(self.url_source_package(url, obj, full=True))              return RedirectResult(self.url_source_package(url, obj, full=True))
250          if  self.db.isBinaryPackage(c, obj):          if  self.db.isBinaryPackage(c, obj):
# Line 172  data source.""")], Line 253  data source.""")],
253          return self.page_not_found(url, obj)          return self.page_not_found(url, obj)
254    
255      def page_bug(self, url, name, redirect):      def page_bug(self, url, name, redirect):
256            # FIXME: Normalize CAN-* to CVE-* when redirecting.  Too many
257            # people still use CAN.
258            if redirect and name[0:4] == 'CAN-':
259                name = 'CVE-' + name[4:]
260    
261          cursor = self.db.cursor()          cursor = self.db.cursor()
262          try:          try:
263              bug = bugs.BugFromDB(cursor, name)              bug = bugs.BugFromDB(cursor, name)
264          except ValueError:          except ValueError:
265              if redirect:              if redirect:
266                  if name[0:4] in ('CAN-', 'CVE-'):                  if name[0:4] == 'CVE-':
267                      return RedirectResult(self.url_cve(url, name),                      return RedirectResult(self.url_cve(url, name),
268                                            permanent=False)                                            permanent=False)
269              return self.page_not_found(url, name)              return self.page_not_found(url, name)
# Line 191  data source.""")], Line 277  data source.""")],
277              yield B("Name"), bug.name              yield B("Name"), bug.name
278    
279              source = bug.name.split('-')[0]              source = bug.name.split('-')[0]
280              if source in ('CAN', 'CVE'):              if source == 'CVE':
281                  source_xref = compose(self.make_cve_ref(url, bug.name, 'CVE'),                  source_xref = compose(self.make_cve_ref(url, bug.name, 'CVE'),
282                                        " (",                                        " (",
283                                        self.make_nvd_ref(url, bug.name,                                        self.make_nvd_ref(url, bug.name,
# Line 201  data source.""")], Line 287  data source.""")],
287                  source_xref = self.make_dsa_ref(url, bug.name, 'Debian')                  source_xref = self.make_dsa_ref(url, bug.name, 'Debian')
288              elif source == 'DTSA':              elif source == 'DTSA':
289                  source_xref = 'Debian Testing Security Team'                  source_xref = 'Debian Testing Security Team'
290              elif source == 'FAKE':              elif source == 'TEMP':
291                  source_xref = (                  source_xref = (
292          'Automatically generated temporary name.  Not for external reference.')          'Automatically generated temporary name.  Not for external reference.')
293              else:              else:
# Line 210  data source.""")], Line 296  data source.""")],
296              if source_xref:              if source_xref:
297                  yield B("Source"), source_xref                  yield B("Source"), source_xref
298    
299              if bug.description:              nvd = self.db.getNVD(cursor, bug.name)
300    
301                if nvd and nvd.cve_desc:
302                    yield B("Description"), nvd.cve_desc
303                elif bug.description:
304                  yield B("Description"), bug.description                  yield B("Description"), bug.description
305    
306              xref = list(self.db.getBugXrefs(cursor, bug.name))              xref = list(self.db.getBugXrefs(cursor, bug.name))
307              if xref:              if xref:
308                  yield B("References"), self.make_xref_list(url, xref)                  yield B("References"), self.make_xref_list(url, xref)
309    
             nvd = self.db.getNVD(cursor, bug.name)  
310              if nvd:              if nvd:
                 if nvd.severity:  
                     yield B("NVD severity"), nvd.severity.lower()  
311                  nvd_range = nvd.rangeString()                  nvd_range = nvd.rangeString()
312                  if nvd_range:                  if nvd.severity:
313                      yield B("NVD attack range"), nvd_range                      nvd_severity = nvd.severity.lower()
314                        if nvd_range:
315                            nvd_severity = "%s (attack range: %s)" \
316                                           % (nvd_severity, nvd_range)
317                        yield B("NVD severity"), nvd_severity
318    
319              debian_bugs = bug.getDebianBugs(cursor)              debian_bugs = bug.getDebianBugs(cursor)
320              if debian_bugs:              if debian_bugs:
# Line 234  data source.""")], Line 325  data source.""")],
325                  for (release, status, reason) in bug.getStatus(cursor):                  for (release, status, reason) in bug.getStatus(cursor):
326                      if status <> 'fixed':                      if status <> 'fixed':
327                          reason = self.make_red(reason)                          reason = self.make_red(reason)
328                      yield B('Status of %s' % release), reason                      yield B('Debian/%s' % release), reason
329    
330          page.append(make_table(gen_header()))          page.append(make_table(gen_header()))
331    
# Line 344  data source.""")], Line 435  data source.""")],
435    
436          return self.create_page(url, bug.name, page)          return self.create_page(url, bug.name, page)
437    
438      def page_debian_bug(self, url, bugnumber, buglist):      def page_debian_bug(self, url, bugnumber, buglist, fake_bug):
439            if fake_bug:
440                new_buglist = []
441                for b in buglist:
442                    (bug_name, urgency, description) = b
443                    if bug_name[0:5] == 'FAKE-' or bug_name[0:5] == 'TEMP-':
444                        new_buglist.append(b)
445                if len(new_buglist) > 0:
446                    # Only replace the bug list if there are still fake
447                    # bug reports.
448                    buglist = new_buglist
449    
450          if len(buglist) == 1:          if len(buglist) == 1:
451              # Single issue, redirect.              # Single issue, redirect.
452              return RedirectResult(url.scriptRelativeFull(buglist[0][0]))              return RedirectResult(url.scriptRelativeFull(buglist[0][0]))
# Line 355  data source.""")], Line 457  data source.""")],
457                      urgency = ""                      urgency = ""
458                  yield self.make_xref(url, name), urgency, description                  yield self.make_xref(url, name), urgency, description
459    
460            if fake_bug:
461                intro = """The URL you used contained a non-stable name
462    based on a Debian bug number.  This name cannot be mapped to a specific
463    issue. """
464            else:
465                intro = ""
466    
467          return self.create_page(          return self.create_page(
468              url, "Information related to Debian bug #%d" % bugnumber,              url, "Information related to Debian bug #%d" % bugnumber,
469              [P("The following issues reference to Debian bug ",              [P(intro + "The following issues reference to Debian bug ",
470                 self.make_debian_bug(url, bugnumber), ":"),                 self.make_debian_bug(url, bugnumber), ":"),
471               make_table(gen(),               make_table(gen(),
472                          caption=("Name", "Urgency", "Description"))])                          caption=("Name", "Urgency", "Description"))])
# Line 369  data source.""")], Line 478  data source.""")],
478                                     ' matched no results.')],                                     ' matched no results.')],
479                                  status=404)                                  status=404)
480    
481        def page_report(self, path, params, url):
482            return self.create_page(
483                url, 'Reporting discrepancies in the data',
484                [P("""The data in this tracker is always in flux, as bugs are fixed and new
485    issues disclosed, the data contained herein is updated. We strive to
486    maintain complete and accurate state information, and appreciate any
487    updates in status, information or new issues."""),
488                 P("There are three ways that you can report updates to this information:"),
489                 make_numbered_list(
490                [P("""IRC: We can be found at """,
491                   CODE("irc.oftc.net"),
492                   ", ",
493                   CODE("#debian-security"),
494        """. If you have information to report, please go ahead and join
495    the channel and tell us.  Please feel free to state the issue,
496    regardless if there is someone who has acknowledged you. Many of us
497    idle on this channel and may not be around when you join, but we read
498    the backlog and will see what you have said. If you require a
499    response, do not forget to let us know how to get a hold of you."""),
500                 P("Mailing list: Our mailing list is: ",
501                   A("mailto:debian-security-tracker@lists.debian.org",
502                     "debian-security-tracker@lists.debian.org")),
503                 P("""Helping out: We welcome people who wish to join us in tracking
504    issues. The process is designed to be easy to learn and participate,
505    please read our """,
506                   A("http://svn.debian.org/wsvn/secure-testing/doc/narrative_introduction?op=file&rev=0&sc=0",
507                     "Introduction"),
508                   """ to get familiar with how things work.  Join us on
509    our mailing list, and on IRC and request to be added to the Alioth """,
510                   A("http://alioth.debian.org/projects/secure-testing/", "project"),
511                   """. We are really quite friendly. If you have a
512    question about how things work, don't be afraid to ask, we would like
513    to improve our documentation and procedures, so feedback is welcome.""")])])
514    
515      def page_source_package(self, path, params, url):      def page_source_package(self, path, params, url):
516          pkg = path[0]          pkg = path[0]
517    
# Line 458  architecture is currently not tracked."" Line 601  architecture is currently not tracked.""
601                      replacement="""No known issues which do not affect                      replacement="""No known issues which do not affect
602  this package, but still reference it.""")])  this package, but still reference it.""")])
603    
604      def page_status_release_stable(self, path, params, url):      def page_status_release_stable_oldstable(self, release, params, url):
605            assert release in ('stable', 'oldstable')
606    
607            bf = BugFilterNoDSA(params)
608    
609          def gen():          def gen():
610              old_pkg_name = ''              old_pkg_name = ''
611              for (pkg_name, bug_name, archive, urgency, remote) in \              for (pkg_name, bug_name, archive, urgency, remote, no_dsa) in \
612                      self.db.cursor().execute(                      self.db.cursor().execute(
613                  """SELECT package, bug, section, urgency, remote                  """SELECT package, bug, section, urgency, remote, no_dsa
614                  FROM stable_status"""):                  FROM %s_status""" % release):
615                    if bf.urgencyFiltered(urgency):
616                        continue
617                    if bf.remoteFiltered(remote):
618                        continue
619                    if bf.nodsaFiltered(no_dsa):
620                        continue
621    
622                  if pkg_name == old_pkg_name:                  if pkg_name == old_pkg_name:
623                      pkg_name = ''                      pkg_name = ''
624                  else:                  else:
# Line 480  this package, but still reference it.""" Line 634  this package, but still reference it."""
634                      remote = 'no'                      remote = 'no'
635    
636                  if urgency == 'unknown':                  if urgency == 'unknown':
637                      urgency = ''                      if no_dsa:
638                            urgency = 'no DSA'
639                        else:
640                            urgency = ''
641                  elif urgency == 'high':                  elif urgency == 'high':
642                      urgency = self.make_red(urgency)                      urgency = self.make_red(urgency)
643                    else:
644                        if no_dsa:
645                            urgency = urgency + '*'
646    
647                  yield pkg_name, self.make_xref(url, bug_name), urgency, remote                  yield pkg_name, self.make_xref(url, bug_name), urgency, remote
648    
649          return self.create_page(          return self.create_page(
650              url, 'Vulnerable source packages in the stable suite',              url, 'Vulnerable source packages in the %s suite' % release,
651              [make_table(gen(), caption=("Package", "Bug", "Urgency",              [bf.actions(url),
652                                          "Remote"))])               make_table(gen(), caption=("Package", "Bug", "Urgency",
653                                            "Remote")),
654                 P('''(If a "*" is included in the urgency field, no DSA is planned
655    for this vulnerability.)''')])
656    
657        def page_status_release_stable(self, path, params, url):
658            return self.page_status_release_stable_oldstable('stable', params, url)
659        def page_status_release_oldstable(self, path, params, url):
660            return self.page_status_release_stable_oldstable('oldstable',
661                                                             params, url)
662    
663      def page_status_release_testing(self, path, params, url):      def page_status_release_testing(self, path, params, url):
664            bf = BugFilterNoDSA(params)
665    
666          def gen():          def gen():
667              old_pkg_name = ''              old_pkg_name = ''
668              for (pkg_name, bug_name, archive, urgency,              for (pkg_name, bug_name, archive, urgency,
669                   sid_vulnerable, ts_fixed, remote) in self.db.cursor().execute(                   sid_vulnerable, ts_fixed, remote, no_dsa) \
670                     in self.db.cursor().execute(
671                  """SELECT package, bug, section, urgency, unstable_vulnerable,                  """SELECT package, bug, section, urgency, unstable_vulnerable,
672                  testing_security_fixed, remote                  testing_security_fixed, remote, no_dsa
673                  FROM testing_status"""):                  FROM testing_status"""):
674                    if bf.urgencyFiltered(urgency):
675                        continue
676                    if bf.remoteFiltered(remote):
677                        continue
678                    if bf.nodsaFiltered(no_dsa):
679                        continue
680    
681                  if pkg_name == old_pkg_name:                  if pkg_name == old_pkg_name:
682                      pkg_name = ''                      pkg_name = ''
683                  else:                  else:
# Line 531  this package, but still reference it.""" Line 710  this package, but still reference it."""
710              url, 'Vulnerable source packages in the testing suite',              url, 'Vulnerable source packages in the testing suite',
711              [make_menu(url.scriptRelative,              [make_menu(url.scriptRelative,
712                         ("status/dtsa-candidates", "Candidates for DTSAs")),                         ("status/dtsa-candidates", "Candidates for DTSAs")),
713                 bf.actions(url),
714               make_table(gen(), caption=("Package", "Bug", "Urgency",               make_table(gen(), caption=("Package", "Bug", "Urgency",
715                                          "Remote"))])                                          "Remote"))])
716    
717      def page_status_release_unstable(self, path, params, url):      def page_status_release_unstable_like(self, path, params, url,
718                                              rel, title):
719            bf = BugFilter(params)
720    
721          def gen():          def gen():
722              old_pkg_name = ''              old_pkg_name = ''
723              for (pkg_name, bug_name, section, urgency) \              for (pkg_name, bug_name, section, urgency, remote) \
724                      in self.db.cursor().execute(                      in self.db.cursor().execute(
725                  """SELECT DISTINCT sp.name, st.bug_name,                  """SELECT DISTINCT sp.name, st.bug_name,
726                  sp.archive, st.urgency                  sp.archive, st.urgency,
727                    (SELECT range_remote FROM nvd_data
728                     WHERE cve_name = st.bug_name)
729                  FROM source_package_status AS st, source_packages AS sp                  FROM source_package_status AS st, source_packages AS sp
730                  WHERE st.vulnerable AND st.urgency <> 'unimportant'                  WHERE st.vulnerable AND st.urgency <> 'unimportant'
731                  AND sp.rowid = st.package AND sp.release = 'sid'                  AND sp.rowid = st.package AND sp.release = ?
732                  AND sp.subrelease = ''                  AND sp.subrelease = ''
733                  ORDER BY sp.name, st.bug_name"""):                  ORDER BY sp.name, st.bug_name""", (rel,)):
734                    if bf.urgencyFiltered(urgency):
735                        continue
736                    if bf.remoteFiltered(remote):
737                        continue
738    
739                  if pkg_name == old_pkg_name:                  if pkg_name == old_pkg_name:
740                      pkg_name = ''                      pkg_name = ''
741                  else:                  else:
# Line 555  this package, but still reference it.""" Line 745  this package, but still reference it."""
745                      else:                      else:
746                          pkg_name = self.make_xref(url, pkg_name)                          pkg_name = self.make_xref(url, pkg_name)
747    
748                    if remote is None:
749                        remote = ''
750                    elif remote:
751                        remote = 'yes'
752                    else:
753                        remote = 'no'
754    
755                  if urgency == 'unknown':                  if urgency == 'unknown':
756                      urgency = ''                      urgency = ''
757                  elif urgency == 'high':                  elif urgency == 'high':
758                      urgency = self.make_red(urgency)                      urgency = self.make_red(urgency)
759    
760                  yield pkg_name, self.make_xref(url, bug_name), urgency                  yield pkg_name, self.make_xref(url, bug_name), urgency, remote
   
   
761          return self.create_page(          return self.create_page(
762              url, 'Vulnerable source packages in the testing suite',              url, title,
763              [P("""Note that the list below is based on source packages.              [P("""Note that the list below is based on source packages.
764              This means that packages are not listed here once a new,              This means that packages are not listed here once a new,
765              fixed source version has been uploaded to the archive, even              fixed source version has been uploaded to the archive, even
766              if there are still some vulnerably binary packages present              if there are still some vulnerably binary packages present
767              in the archive."""),              in the archive."""),
768               make_table(gen(), caption=('Package', 'Bug', 'Urgency'))])               bf.actions(url),
769                 make_table(gen(), caption=('Package', 'Bug', 'Urgency',
770                                            'Remote'))])
771    
772        def page_status_release_unstable(self, path, params, url):
773            return self.page_status_release_unstable_like(
774                path, params, url,
775                title='Vulnerable source packages in the unstable suite',
776                rel='sid')
777    
778        def page_status_release_stable_backports(self, path, params, url):
779            return self.page_status_release_unstable_like(
780                path, params, url,
781                title='Vulnerable source packages among backports for stable',
782                rel='lenny-backports')
783    
784        def page_status_release_oldstable_backports(self, path, params, url):
785            return self.page_status_release_unstable_like(
786                path, params, url,
787                title='Vulnerable source packages among backports for oldstable',
788                rel='etch-backports')
789    
790      def page_status_dtsa_candidates(self, path, params, url):      def page_status_dtsa_candidates(self, path, params, url):
791            bf = BugFilter(params)
792    
793          def gen():          def gen():
794              old_pkg_name = ''              old_pkg_name = ''
795              for (pkg_name, bug_name, archive, urgency, stable_later) \              for (pkg_name, bug_name, archive, urgency, stable_later,
796                     remote) \
797                      in self.db.cursor().execute(                      in self.db.cursor().execute(
798                  """SELECT package, bug, section, urgency,                  """SELECT package, bug, section, urgency,
799                  (SELECT testing.version_id < stable.version_id                  (SELECT testing.version_id < stable.version_id
800                   FROM source_packages AS testing, source_packages AS stable                   FROM source_packages AS testing, source_packages AS stable
801                   WHERE testing.name = testing_status.package                   WHERE testing.name = testing_status.package
802                   AND testing.release = 'etch'                   AND testing.release = 'squeeze'
803                   AND testing.subrelease = ''                   AND testing.subrelease = ''
804                   AND testing.archive = testing_status.section                   AND testing.archive = testing_status.section
805                   AND stable.name = testing_status.package                   AND stable.name = testing_status.package
806                   AND stable.release = 'sarge'                   AND stable.release = 'lenny'
807                   AND stable.subrelease = 'security'                   AND stable.subrelease = 'security'
808                   AND stable.archive = testing_status.section)                   AND stable.archive = testing_status.section),
809                    (SELECT range_remote FROM nvd_data
810                     WHERE cve_name = bug)
811                  FROM testing_status                  FROM testing_status
812                  WHERE (NOT unstable_vulnerable)                  WHERE (NOT unstable_vulnerable)
813                  AND (NOT testing_security_fixed)"""):                  AND (NOT testing_security_fixed)"""):
814                    if bf.urgencyFiltered(urgency):
815                        continue
816                    if bf.remoteFiltered(remote):
817                        continue
818    
819                  if pkg_name == old_pkg_name:                  if pkg_name == old_pkg_name:
820                      pkg_name = ''                      pkg_name = ''
821                      migration = ''                      migration = ''
# Line 603  this package, but still reference it.""" Line 828  this package, but still reference it."""
828                      else:                      else:
829                          pkg_name = self.make_source_package_ref(url, pkg_name)                          pkg_name = self.make_source_package_ref(url, pkg_name)
830    
831                    if remote is None:
832                        remote = ''
833                    elif remote:
834                        remote = 'yes'
835                    else:
836                        remote = 'no'
837    
838                  if urgency == 'unknown':                  if urgency == 'unknown':
839                      urgency = ''                      urgency = ''
840                  elif urgency == 'high':                  elif urgency == 'high':
# Line 614  this package, but still reference it.""" Line 846  this package, but still reference it."""
846                      notes = ''                      notes = ''
847    
848                  yield (pkg_name, migration, self.make_xref(url, bug_name),                  yield (pkg_name, migration, self.make_xref(url, bug_name),
849                         urgency, notes)                         urgency, remote, notes)
850    
851          return self.create_page(          return self.create_page(
852              url, "Candidates for DTSAs",              url, "Candidates for DTSAs",
853              [P("""The table below lists packages which are fixed              [P("""The table below lists packages which are fixed
854  in unstable, but unfixed in testing.  Use the testing migration  in unstable, but unfixed in testing.  Use the testing migration
855  return web_supporttracker to find out why they have not entered  checker to find out why they have not entered testing yet."""),
 return web_supporttesting yet."""),  
856               make_menu(url.scriptRelative,               make_menu(url.scriptRelative,
857                         ("status/release/testing",                         ("status/release/testing",
858                          "List of vulnerable packages in testing")),                          "List of vulnerable packages in testing")),
859                 bf.actions(url),
860               make_table(gen(),               make_table(gen(),
861                          caption=("Package", "Migration", "Bug", "Urgency"))])                          caption=("Package", "Migration", "Bug", "Urgency",
862                                     "Remote"))])
863    
864      def page_status_todo(self, path, params, url):      def page_status_todo(self, path, params, url):
865            hide_check = params.get('hide_check', False)
866            if hide_check:
867                flags = A(url.updateParamsDict({'hide_check' : None}),
868                          'Show "check" TODOs')
869            else:
870                flags = A(url.updateParamsDict({'hide_check' : '1'}),
871                      'Hide "check" TODOs')
872    
873          def gen():          def gen():
874              for (bug, description) in self.db.getTODOs():              for (bug, description) in self.db.getTODOs(hide_check=hide_check):
875                  yield self.make_xref(url, bug), description                  yield self.make_xref(url, bug), description
876          return self.create_page(          return self.create_page(
877              url, "Bugs with TODO items",              url, "Bugs with TODO items",
878              [make_table(gen(),              [P(flags),
879                 make_table(gen(),
880                          caption=("Bug", "Description"))])                          caption=("Bug", "Description"))])
881    
882      def page_status_itp(self, path, params, url):      def page_status_itp(self, path, params, url):
# Line 660  return web_supporttesting yet."""), Line 902  return web_supporttesting yet."""),
902              url, "Unknown packages",              url, "Unknown packages",
903              [P("""Sometimes, a package referenced in a bug report              [P("""Sometimes, a package referenced in a bug report
904  cannot be found in the database.  This can be the result of a spelling  cannot be found in the database.  This can be the result of a spelling
905  return web_supporterror, or a historic entry refers to a  error, or a historic entry refers to a
906  return web_supportpackage which is no longer in the archive."""),  package which is no longer in the archive."""),
907               make_table(gen(), caption=("Package", "Bugs"),               make_table(gen(), caption=("Package", "Bugs"),
908          replacement="No unknown packages are referenced in the database.")])          replacement="No unknown packages are referenced in the database.")])
909    
# Line 699  return web_supportpackage which is no lo Line 941  return web_supportpackage which is no lo
941                  caption=("Bug", "Package", "Version 1", "Version 2"),                  caption=("Bug", "Package", "Version 1", "Version 2"),
942                  replacement="No source package version with missing epochs.")])                  replacement="No source package version with missing epochs.")])
943    
944        def page_data_latently_vulnerable(self, path, params, url):
945            def gen():
946                for pkg, bugs in self.db.cursor().execute(
947                    """SELECT package, string_set(bug_name)
948                    FROM package_notes AS p1
949                    WHERE release <> ''
950                    AND (bug_name LIKE 'CVE-%' OR bug_name LIKE 'TEMP-%')
951                    AND NOT EXISTS (SELECT 1 FROM package_notes AS p2
952                                    WHERE p2.bug_name = p1.bug_name
953                                    AND p2.package = p1.package
954                                    AND release = '')
955                    AND EXISTS (SELECT 1 FROM source_packages
956                               WHERE name = p1.package AND release = 'sid')
957                    GROUP BY package
958                    ORDER BY package"""):
959                    pkg = self.make_source_package_ref(url, pkg)
960                    bugs = bugs.split(',')
961                    yield pkg, self.make_xref_list(url, bugs)
962    
963            def gen_unimportant():
964                for pkg, bugs in self.db.cursor().execute(
965                    """SELECT package, string_set(bug_name)
966                    FROM package_notes AS p1
967                    WHERE release <> ''
968                    AND urgency <> 'unimportant'
969                    AND (bug_name LIKE 'CVE-%' OR bug_name LIKE 'TEMP-%')
970                    AND EXISTS (SELECT 1 FROM package_notes AS p2
971                                    WHERE p2.bug_name = p1.bug_name
972                                    AND p2.package = p1.package
973                                    AND release = '')
974                    AND NOT EXISTS (SELECT 1 FROM package_notes AS p2
975                                    WHERE p2.bug_name = p1.bug_name
976                                    AND p2.package = p1.package
977                                    AND urgency <> 'unimportant'
978                                    AND release = '')
979                    AND EXISTS (SELECT 1 FROM source_packages
980                               WHERE name = p1.package AND release = 'sid')
981                    GROUP BY package
982                    ORDER BY package"""):
983                    pkg = self.make_source_package_ref(url, pkg)
984                    bugs = bugs.split(',')
985                    yield pkg, self.make_xref_list(url, bugs)
986    
987            return self.create_page(
988                url, "Latently vulnerable packages in unstable",
989                [P(
990    """A package is latently vulnerable in unstable if it is vulnerable in
991    any release, and there is no package note for the same vulnerability
992    and package in unstable (and the package is still available in
993    unstable, of course)."""),
994                 make_table(gen(),
995                    caption=("Package", "Bugs"),
996                    replacement="No latently vulnerable packages were found."),
997                 P(
998    """The next table lists issues which are marked unimportant for
999    unstable, but for which release-specific annotations exist which are
1000    not unimportant."""),
1001                 make_table(gen_unimportant(),
1002                    caption=("Package", "Bugs"),
1003                    replacement=
1004        "No packages with unimportant latent vulnerabilities were found."),
1005                ])
1006    
1007      def page_data_releases(self, path, params, url):      def page_data_releases(self, path, params, url):
1008          def gen():          def gen():
1009              for (rel, subrel, archive, sources, archs) \              for (rel, subrel, archive, sources, archs) \
# Line 743  but it makes version-based bug tracking Line 1048  but it makes version-based bug tracking
1048               long as none of the binary packages carries the same name as the               long as none of the binary packages carries the same name as the
1049               source package, most confusion is avoided or can be easily               source package, most confusion is avoided or can be easily
1050               explained.""")])               explained.""")])
1051    
1052        def page_data_fake_names(self, path, params, url):
1053            def gen():
1054                for (bug, description) in self.db.getFakeBugs():
1055                    yield self.make_xref(url, bug), description
1056            return self.create_page(
1057                url, "Automatically generated issue names",
1058                [P("""Some issues have not been assigned CVE names, but are still
1059    tracked by this database.  In this case, the system automatically assigns
1060    a unique name.  These names are not stable and can change when the database
1061    is updated, so they should not be used in external references."""),
1062                 P('''The automatically generated names come in two flavors:
1063    the first kind starts with the string "''', CODE("TEMP-000000-"),
1064                   '''".  This means that no Debian bug has been assigned to this
1065    issue (or a bug has been created and is not recorded in this database).
1066    In the second kind of names, there is a Debian bug for the issue, and the "''',
1067                   CODE("000000"), '''"part of the name is replaced with the
1068    Debian bug number.'''),
1069                 make_table(gen(),
1070                            caption=("Bug", "Description"))])
1071    
1072        def page_debsecan(self, path, params, url):
1073            obj = '/'.join(path)
1074            data = self.db.getDebsecan(obj)
1075            if data:
1076                return BinaryResult(data)
1077            else:
1078                return self.create_page(
1079                    url, "Object not found",
1080                    [P("The requested debsecan object has not been found.")],
1081                    status=404)
1082    
1083      def create_page(self, url, title, body, search_in_page=False, status=200):      def create_page(self, url, title, body, search_in_page=False, status=200):
1084          append = body.append          append = body.append
# Line 774  but it makes version-based bug tracking Line 1109  but it makes version-based bug tracking
1109                            onkeyup="onSearch(this.value)",                            onkeyup="onSearch(this.value)",
1110                            onmousemove="onSearch(this.value)"),                            onmousemove="onSearch(this.value)"),
1111                      INPUT(type='submit', value='Go'),                      INPUT(type='submit', value='Go'),
1112                        ' ',
1113                        A(url.scriptRelative("data/report"), "Reporting problems"),
1114                      method='get',                      method='get',
1115                      action=url.scriptRelative(''))                      action=url.scriptRelative(''))
1116    
# Line 781  but it makes version-based bug tracking Line 1118  but it makes version-based bug tracking
1118          return url.absolute("http://cve.mitre.org/cgi-bin/cvename.cgi",          return url.absolute("http://cve.mitre.org/cgi-bin/cvename.cgi",
1119                              name=name)                              name=name)
1120      def url_nvd(self, url, name):      def url_nvd(self, url, name):
1121          return url.absolute("http://nvd.nist.gov/nvd.cfm",          return url.absolute("http://web.nvd.nist.gov/view/vuln/detail",
1122                              cvename=name)                              vulnId=name)
1123    
1124      def url_dsa(self, url, dsa, re_dsa=re.compile(r'^DSA-(\d+)(?:-\d+)?$')):      def url_dsa(self, url, dsa, re_dsa=re.compile(r'^DSA-(\d+)(?:-\d+)?$')):
1125          match = re_dsa.match(dsa)          match = re_dsa.match(dsa)
# Line 806  but it makes version-based bug tracking Line 1143  but it makes version-based bug tracking
1143          return url.absolute("http://packages.qa.debian.org/common/index.html",          return url.absolute("http://packages.qa.debian.org/common/index.html",
1144                              src=package)                              src=package)
1145      def url_testing_status(self, url, package):      def url_testing_status(self, url, package):
1146          return url.absolute("http://bjorn.haxx.se/debian/testing.pl",          return url.absolute("http://release.debian.org/migration/testing.pl",
1147                              package=package)                              package=package)
1148      def url_source_package(self, url, package, full=False):      def url_source_package(self, url, package, full=False):
1149          if full:          if full:

Legend:
Removed from v.2489  
changed lines
  Added in v.12985

  ViewVC Help
Powered by ViewVC 1.1.5