summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorBjoern Tropf <asym@gentoo.org>2009-10-31 12:52:36 +0100
committerBjoern Tropf <asym@gentoo.org>2009-10-31 12:52:36 +0100
commit63d063d03127573225e1c43d0d9e03e5c7884d21 (patch)
treef1eb27680c808e5e69f520a545d1f1a64d7e8fe6 /tools
parentCode cleanup (diff)
downloadkernel-check-63d063d03127573225e1c43d0d9e03e5c7884d21.tar.gz
kernel-check-63d063d03127573225e1c43d0d9e03e5c7884d21.tar.bz2
kernel-check-63d063d03127573225e1c43d0d9e03e5c7884d21.zip
Large restructuration
Diffstat (limited to 'tools')
-rwxr-xr-xtools/cron.py405
-rwxr-xr-xtools/findcommit.sh62
-rwxr-xr-xtools/testsuite.py212
3 files changed, 679 insertions, 0 deletions
diff --git a/tools/cron.py b/tools/cron.py
new file mode 100755
index 0000000..01e04af
--- /dev/null
+++ b/tools/cron.py
@@ -0,0 +1,405 @@
+#!/usr/bin/env python
+# kernel-check -- Kernel security information
+# Copyright 2009-2009 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+from contextlib import closing
+import xml.etree.cElementTree as et
+import cStringIO
+import datetime
+import logging
+import mmap
+import os
+import portage
+import re
+import sys
+import time
+import urllib
+
+
+class CronError(Exception):
+ def __init__(self, value):
+ self.value = value
+
+NOCVE = 'GENERIC-MAP-NOMATCH'
+NOCVEDESC = 'This GENERIC identifier is not specific to any vulnerability. '\
+ 'GENERIC-MAP-NOMATCH is used by products, databases, and ' \
+ 'services to specify when a particular vulnerability element ' \
+ 'does not map to a corresponding CVE entry.'
+DELAY = 0.2
+SKIP = True
+MINYEAR = 2002
+MAXYEAR = 2020
+NVDURL = 'http://nvd.nist.gov/'
+BZURL = 'https://bugs.gentoo.org/'
+STATE = ['NEW', 'ASSIGNED', 'REOPENED', 'RESOLVED', 'VERIFIED', 'CLOSED']
+RESOLUTION = ['FIXED', 'LATER', 'TEST-REQUEST', 'UPSTREAM', '---']
+BUGORDER = ['bugid', 'reporter', 'reported', 'status', 'arch', 'affected']
+CVEORDER = ['cve', 'published', 'desc', 'severity', 'vector', 'score', 'refs']
+FILEPATH = os.path.dirname(os.path.realpath(__file__))
+PORTDIR = portage.settings['PORTDIR']
+LOGFILE = None #os.path.join(FILEPATH, 'cron.log')
+DIR = {
+ 'tmp' : os.path.join(FILEPATH, 'tmp'),
+ 'out' : os.path.join(PORTDIR, 'metadata', 'kernel'),
+ 'bug' : os.path.join(FILEPATH, 'tmp', 'bug'),
+ 'nvd' : os.path.join(FILEPATH, 'tmp', 'nvd')
+}
+REGEX = {
+ 'bugzilla' : re.compile(r'(?<=bug.cgi\?id=)\d*'),
+ 'grp_all' : re.compile(r'(?<=\()[ (]*CVE-(\d{4})' \
+ r'([-,(){}|, \d]+)(?=\))'),
+ 'm_nomatch' : re.compile(r'.*GENERIC-MAP-NOMATCH.*'),
+ 'grp_split' : re.compile(r'(?<=\D)(\d{4})(?=\D|$)'),
+ 'wb_match' : re.compile(r'\s*\[\s*([^ +<=>]+)\s*([' \
+ r'<=>]{1,2})\s*([^ <=>\]]+' \
+ r')\s*(?:([<=>]{1,2})\s*([' \
+ r'^ \]]+))?\s*\]\s*(.*)'),
+ 'wb_version' : re.compile(r'^(?:\d{1,2}\.){0,3}\d{1,2}' \
+ r'(?:[-_](?:r|rc)?\d{1,2})*$')
+}
+CVES = dict()
+logging.basicConfig(format='[%(asctime)s] %(levelname)-6s : %(message)s',
+ datefmt='%H:%M:%S', filename=LOGFILE, level=logging.DEBUG)
+
+
+def main(argv):
+ 'Main function'
+
+ logging.info('Running cron...')
+
+ current_year = datetime.datetime.now().year
+ if current_year < MINYEAR or current_year > MAXYEAR:
+ current_year = MAXYEAR
+
+ for directory in DIR:
+ if not os.path.isdir(DIR[directory]):
+ os.makedirs(DIR[directory])
+
+ logging.info('Receiving the latest xml file from the nvd')
+
+ receive_file(DIR['nvd'], [NVDURL, 'download/'],'nvdcve-recent.xml')
+
+ if not SKIP:
+ logging.info('Receiving earlier xml files from the nvd')
+
+ for year in xrange(MINYEAR, current_year + 1):
+ receive_file(DIR['nvd'], [NVDURL, 'download/'],
+ 'nvdcve-%s.xml' % str(year))
+
+ logging.info('Receiving the kernel vulnerability list from bugzilla')
+
+ url = [BZURL, 'buglist.cgi?query_format=advanced&component=Kernel']
+
+ for item in STATE:
+ url.append('&bug_status=' + item)
+ for item in RESOLUTION:
+ url.append('&resolution=' + item)
+ url.append('#')
+
+ receive_file(DIR['tmp'], url, 'bugzilla.xml')
+
+ filename = os.path.join(DIR['tmp'], 'bugzilla.xml')
+ with open(filename, 'r+') as buglist_file:
+ memory_map = mmap.mmap(buglist_file.fileno(), 0)
+ buglist = REGEX['bugzilla'].findall(memory_map.read(-1))
+
+ logging.info('Found %i kernel vulnerabilities' % len(buglist))
+
+ logging.info('Creating the nvd dictionary')
+ nvd_dict = parse_nvd_dict(DIR['nvd'])
+
+ logging.info('Creating the xml files')
+
+ created_files = 0
+ for item in buglist:
+ try:
+ receive_file(DIR['bug'], [BZURL, 'show_bug.cgi?ctype=xml&id='],
+ item)
+
+ vul = parse_bugzilla_dict(DIR['bug'], item)
+
+ for cve in vul['cvelist']:
+ if cve == NOCVE:
+ vul['cves'] = [NOCVE]
+ break; #TODO
+ else:
+ try:
+ vul['cves'].append(nvd_dict[cve])
+ except KeyError:
+ raise CronError('No Nvd entry: ' + cve)
+
+ write_cve_file(DIR['out'], vul)
+ created_files += 1
+ time.sleep(DELAY)
+
+ except CronError, e:
+ logging.error('[%s] %s' % (item, e.value))
+
+ logging.info('Created %i xml files' % created_files)
+
+
+def receive_file(directory, url, xml_file):
+ 'Generic download function'
+
+ filename = os.path.join(directory, xml_file)
+ url.append(xml_file)
+
+ try:
+ with closing(cStringIO.StringIO()) as data:
+ with closing(urllib.urlopen(''.join(url))) as resource:
+ data.write(resource.read())
+
+ with open(filename, 'w') as output:
+ output.write(data.getvalue())
+
+ except IOError:
+ logging.error('File %s - Download failed!' % filename)
+
+ logging.debug('File %s - %sKB received' %
+ (filename, os.path.getsize(filename)/1024))
+
+
+def parse_nvd_dict(directory):
+ 'Returns a dictionary from the National Vulnerability Database'
+
+ nvd = dict()
+
+ for nvdfile in os.listdir(directory):
+ filename = os.path.join(directory, nvdfile)
+ try:
+ with open(filename, 'r+') as xml_data:
+ memory_map = mmap.mmap(xml_data.fileno(), 0)
+
+ except SyntaxError:
+ continue
+
+ root = et.parse(memory_map).getroot()
+ namespace = root.tag[:-3]
+
+ for tree in root:
+ cve = {
+ 'cve' : tree.get('name'),
+ 'published' : tree.get('published'),
+ 'severity' : tree.get('severity'),
+ 'vector' : tree.get('CVSS_vector'),
+ 'score' : tree.get('CVSS_score')
+ }
+
+ desc = tree.find('%sdesc/%sdescript/' % (namespace, namespace))
+ if desc is not None:
+ cve['desc'] = desc.text
+
+ reftree = tree.find(namespace + 'refs')
+ reftree.tag = reftree.tag.replace(namespace, '')
+ for elem in reftree.findall('.//*'):
+ elem.tag = elem.tag.replace(namespace, '')
+
+ bugref = et.SubElement(reftree, 'ref')
+ bugref.set('source', 'GENTOO')
+ bugref.set('url', '%sshow_bug.cgi?id=%s' % (BZURL, cve['cve']))
+ bugref.text = 'Gentoo %s' % cve['cve']
+
+ cve['refs'] = reftree
+
+ nvd[cve['cve']] = cve
+
+ return nvd
+
+def parse_bugzilla_dict(directory, bugid):
+ 'Returns a vulnerability class containing information about a bug'
+
+ filename = os.path.join(directory, bugid)
+
+ try:
+ with open(filename, 'r+') as xml_data:
+ memory_map = mmap.mmap(xml_data.fileno(), 0)
+ root = et.parse(memory_map).getroot()[0]
+
+ except IOError:
+ return
+
+ string = str()
+
+ try:
+ string = root.find('short_desc').text
+ except AttributeError:
+ CronError('No Cve')
+
+ try:
+ cvelist = list()
+ string = string.replace('CAN', 'CVE')
+
+ if string in REGEX['m_nomatch'].findall(string):
+ cvelist = [NOCVE]
+
+ for (year, split_cves) in REGEX['grp_all'].findall(string):
+ for cve in REGEX['grp_split'].findall(split_cves):
+ cvelist.append('CVE-%s-%s' % (year, cve))
+
+ vul = {
+ 'bugid' : bugid,
+ 'cvelist' : cvelist,
+ 'cves' : list(),
+ 'arch' : root.find('rep_platform').text.lower(),
+ 'reporter' : root.find('reporter').text.lower(),
+ 'reported' : root.find('creation_ts').text,
+ 'status' : root.find('bug_status').text.lower(),
+ }
+
+ for item in vul['cvelist']:
+ if item != NOCVE:
+ if item not in CVES:
+ CVES[item] = vul.bugid
+ else:
+ raise CronError('Duplicate: ' + CVES[item])
+
+ except AttributeError:
+ pass
+
+ try:
+ wb = root.find('status_whiteboard').text;
+ vul['affected'] = interval_from_whiteboard(wb)
+
+ if vul['affected'] == None:
+ raise CronError('Invalid whiteboard: ' + wb)
+
+ except AttributeError:
+ raise CronError('Empty whiteboard')
+
+ return vul
+
+
+def interval_from_whiteboard(whiteboard):
+ 'Returns a list of intervals within a whiteboard string'
+
+ upper_inc = None
+ upper = None
+ lower_inc = None
+ lower = None
+
+ affected = list()
+
+ while len(whiteboard.strip()) > 0:
+ match = REGEX['wb_match'].match(whiteboard)
+ if not match:
+ return None
+
+ name = match.group(1)
+ comp1 = match.group(2)
+ vers1 = match.group(3)
+ comp2 = match.group(4)
+ vers2 = match.group(5)
+ whiteboard = match.group(6)
+
+ if comp1 == '=' or comp1 == '==':
+ lower_inc = True
+ upper_inc = True
+ lower = vers1
+ upper = vers1
+
+ if not REGEX['wb_version'].match(vers1):
+ return None
+ else:
+ for (char, version) in ((comp1, vers1), (comp2, vers2)):
+
+ if char == '<':
+ upper_inc = False
+ upper = version
+ elif char == '<=' or char == '=<':
+ upper_inc = True
+ upper = version
+ elif char == '>':
+ lower_inc = False
+ lower = version
+ elif char == '>=' or char == '=>':
+ lower_inc = True
+ lower = version
+ elif char:
+ return None
+
+ if version and not REGEX['wb_version'].match(version):
+ return None
+
+ interval = {
+ 'name' : name,
+ 'lower' : lower,
+ 'upper' : upper,
+ 'lower_inc' : lower_inc,
+ 'upper_inc' : upper_inc
+ }
+
+ affected.append(interval)
+
+ return affected
+
+
+def write_cve_file(directory, vul):
+ 'Write a bug file containing all important information for kernel-check'
+
+ filename = os.path.join(directory, vul['bugid'] + '.xml')
+
+ root = et.Element('vulnerability')
+ bugroot = et.SubElement(root, 'bug')
+
+ for element in BUGORDER:
+ if element == 'affected':
+ affectedroot = et.SubElement(bugroot, 'affected')
+ for item in vul['affected']:
+ intnode = et.Element('interval')
+ intnode.set('source', item['name'])
+
+ affectedroot.append(intnode)
+
+ for i in ('lower', 'upper'):
+ if item[i]:
+ node = et.SubElement(intnode, i)
+ node.text = item[i]
+ node.set('inclusive',
+ str(item[i + '_inc']).lower())
+ else:
+ node = et.SubElement(bugroot, element)
+ node.text = vul[element]
+
+ for cve in vul['cves']:
+ cveroot = et.SubElement(root, 'cve')
+ if cve == NOCVE:
+ node = et.SubElement(cveroot, 'cve')
+ node.text = NOCVE
+ node = et.SubElement(cveroot, 'desc')
+ node.text = NOCVEDESC
+ else:
+ for element in CVEORDER:
+ if element == 'refs':
+ cveroot.append(cve[element])
+ else:
+ node = et.SubElement(cveroot, element)
+ node.text = cve[element]
+
+ with open(filename, 'w') as xmlout:
+ __indent__(root)
+ doc = et.ElementTree(root)
+ doc.write(xmlout, encoding='utf-8')
+
+
+def __indent__(node, level=0):
+ 'Indents xml layout for printing'
+
+ i = '\n' + level * ' ' * 4
+ if len(node):
+ if not node.text or not node.text.strip():
+ node.text = i + ' ' * 4
+ if not node.tail or not node.tail.strip():
+ node.tail = i
+ for node in node:
+ __indent__(node, level + 1)
+ if not node.tail or not node.tail.strip():
+ node.tail = i
+ else:
+ if level and (not node.tail or not node.tail.strip()):
+ node.tail = i
+
+
+if __name__ == '__main__':
+ main(sys.argv[1:])
+
diff --git a/tools/findcommit.sh b/tools/findcommit.sh
new file mode 100755
index 0000000..770078b
--- /dev/null
+++ b/tools/findcommit.sh
@@ -0,0 +1,62 @@
+#!/bin/sh
+# kernel-check -- Kernel security information
+# Copyright 2009-2009 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+TEXT=".*$@.*"
+GITPATH="./"
+
+KNOWNCOMMITS=""
+LASTFIXEDBRANCH=""
+WHITEBOARD=""
+
+GOOD=$'\e[32;01m'
+BAD=$'\e[31;01m'
+BRACKET=$'\e[34;01m'
+NORMAL=$'\e[0m'
+
+GITPATH="--git-dir=$GITPATH.git --work-tree=$GITPATH"
+BRANCHES="`git $GITPATH branch -a | grep linux` origin/master"
+for B in $BRANCHES ; do
+ COMMITS="`git $GITPATH rev-list --pretty=oneline "$B" |
+ grep "$TEXT" | cut -d " " -f 1`"
+ for C in $COMMITS ; do
+ if [ "${KNOWNCOMMITS/$C/}" == "$KNOWNCOMMITS" ] ; then
+ TAG="`git $GITPATH describe --contains --all "$C"`"
+ DESC="`git $GITPATH --no-pager log -1 --pretty=short "$C"`"
+ DESC="`echo "$DESC" | tr -s "\n" `"
+ DESC="${TAG/tags\//\n${GOOD}label${NORMAL} }\n${DESC}"
+ DESC="${DESC/commit/${GOOD}commit${NORMAL}}"
+ DESC="${DESC/Author:/${GOOD}author${NORMAL}}"
+ DESC="${DESC/ /${GOOD}title${NORMAL} ${BRACKET}}${NORMAL}\n"
+ echo -e "$DESC"
+
+ VERSION="${TAG/tags\/v/}"
+ VERSION="${VERSION/~*/}"
+ VERSION="${VERSION/^*/}"
+
+ if [ "$B" != "origin/master" ] ; then
+ THISBRANCH="${B/remotes\/origin\/linux-/}"
+ THISBRANCH="${THISBRANCH/.y/}"
+ REVISION="${THISBRANCH/*./}"
+ MAJORMINOR="${THISBRANCH/.${REVISION}/}"
+ let REVISION=REVISION+1
+ NEXTBRANCH="${MAJORMINOR}.${REVISION}"
+ fi
+ if [ -z "$LASTFIXEDBRANCH" ] ; then
+ WHITEBOARD="$WHITEBOARD [linux <${VERSION}]"
+ else
+ if [ "${LASTFIXEDBRANCH}" == "${VERSION/-rc*/}" ] ; then
+ WHITEBOARD="${WHITEBOARD} ${BAD}[linux >=" \
+ "${LASTFIXEDBRANCH} <${VERSION}]${NORMAL}"
+ else
+ WHITEBOARD="${WHITEBOARD} [linux >=" \
+ "${LASTFIXEDBRANCH} <${VERSION}]"
+ fi
+ fi
+ LASTFIXEDBRANCH=$NEXTBRANCH
+ KNOWNCOMMITS="$KNOWNCOMMITS $C"
+ fi
+ done
+done
+echo -e "${GOOD}Whiteboard${NORMAL}\n${WHITEBOARD:1}\n"
diff --git a/tools/testsuite.py b/tools/testsuite.py
new file mode 100755
index 0000000..1a9287c
--- /dev/null
+++ b/tools/testsuite.py
@@ -0,0 +1,212 @@
+#!/usr/bin/env python
+
+import unittest
+import sys
+import kernellib as lib
+import guidexml
+
+"""
+import matplotlib.pyplot as pyplot
+
+
+def draw_graph():
+ 'Draws a graph x=kernel releases, y=amount of vulnerabilities'
+
+LINUX26_RELEASES = [
+'0', '1', '2', '3', '4', '5', '6', '7', '8', '8.1', '9', '10', '11', '11.1',
+'11.2', '11.3', '11.4', '11.5', '11.6', '11.7', '11.8', '11.9', '11.10',
+'11.11', '11.12', '12', '12.1', '12.2', '12.3', '12.4', '12.5', '12.6',
+'13', '13.1', '13.2', '13.3', '13.4', '13.5', '14', '14.1', '14.2', '14.3',
+'14.4', '14.5', '14.6', '14.7', '15', '15.1', '15.2', '15.3', '15.4', '15.5',
+'15.6', '15.7', '16', '16.1', '16.2', '16.3', '16.4', '16.5', '16.6', '16.7',
+'16.8', '16.9', '16.10', '16.11', '16.12', '16.13', '16.14', '16.15', '16.16',
+'16.17', '16.18', '16.19', '16.20', '16.21', '16.22', '16.23', '16.24',
+'16.25', '16.26', '16.27', '16.28', '16.29', '16.30', '16.31', '16.32',
+'16.33', '16.34', '16.35', '16.36', '16.37', '16.38', '16.39', '16.40',
+'16.41', '16.42', '16.43', '16.44', '16.45', '16.46', '16.47', '16.48',
+'16.49', '16.50', '16.51', '16.52', '16.53', '16.54', '16.55', '16.56',
+'16.57', '16.58', '16.59', '16.60', '16.61', '16.62', '17', '17.1', '17.2',
+'17.3', '17.4', '17.5', '17.6', '17.7', '17.8', '17.9', '17.10', '17.11',
+'17.12', '17.13', '17.14', '18', '18.1', '18.2', '18.3', '18.4', '18.5',
+'18.6', '18.7', '18.8', '19', '19.1', '19.2', '19.3', '19.4', '19.5', '19.6',
+'19.7', '20', '20.1', '20.2', '20.3', '20.4', '20.5', '20.6', '20.7', '20.8',
+'20.9', '20.10', '20.11', '20.12', '20.13', '20.14', '20.15', '20.16', '20.17',
+'20.18', '20.19', '20.20', '20.21', '21', '21.1', '21.2', '21.3', '21.4',
+'21.5', '21.6', '21.7', '22', '22.1', '22.2', '22.3', '22.4', '22.5', '22.6',
+'22.7', '22.8', '22.9', '22.10', '22.11', '22.12', '22.13', '22.14', '22.15',
+'22.16', '22.17', '22.18', '22.19', '23', '23.1', '23.2', '23.3', '23.4',
+'23.5', '23.6', '23.7', '23.8', '23.9', '23.10', '23.11', '23.12', '23.13',
+'23.14', '23.15', '23.16', '23.17', '24', '24.1', '24.2', '24.3', '24.4',
+'24.5', '24.6', '24.7', '25', '25.1', '25.2', '25.3', '25.4', '25.5', '25.6',
+'25.7', '25.8', '25.9', '25.10', '25.11', '25.12', '25.13', '25.14', '25.15',
+'25.16', '25.17', '25.18', '25.19', '25.20', '26', '26.1', '26.2', '26.3',
+'26.4', '26.5', '26.6', '26.7', '26.8', '27', '27.1', '27.2', '27.3', '27.4',
+'27.5', '27.6', '27.7', '27.8', '27.9', '27.10', '27.11', '27.12', '27.13',
+'27.14', '27.15', '27.16', '27.17', '27.18', '27.19', '27.20', '27.21',
+'27.22', '27.23', '27.24', '27.25', '27.26', '27.27', '27.28', '28', '28.1',
+'28.2', '28.3', '28.4', '28.5', '28.6', '28.7', '28.8', '28.9', '28.10', '29',
+'29.1', '29.2', '29.3', '29.4', '29.5', '29.6', '30', '30.1', '30.2', '30.3',
+'30.4', '30.5'
+]
+
+vul, line, value = [], [], []
+
+for item in LINUX26_RELEASES:
+ kernel = lib.Kernel('gentoo-sources')
+ kernel.revision = ''
+ kernel.version = '2.6.' + item
+ best = lib.best_version(kernel.source)
+ schedule = lib.parse_cve_files('out', kernel, best, 'all') #FIXME
+ vul.append(len(schedule.canfix))
+ if '.' not in item:
+ line.append(len(schedule.canfix))
+ value.append(len(vul) - 1)
+
+pyplot.plot(vul, color='#7A5ADA', linewidth=1)
+for i in range(0, len(line)):
+ pyplot.bar(value[i], line[i], color='#7A5ADA', edgecolor='#FFFFFF')
+
+pyplot.axis('tight')
+pyplot.ylabel('Number of vulnerabilities')
+pyplot.xlabel('Kernel release')
+pyplot.show()
+
+
+def write_guidexml():
+ 'Testcases for guidexml'
+
+doc = guidexml.Document('mydocument', '2.0', 'Sehr nuetzliches infos', 'en',
+ '/doc/en/bla')
+
+doc.addAuthor('creator', 'asyme', 'asymmail@googlemail.de')
+doc.addAuthor('creator', 'rbu')
+
+chap = guidexml.Chapter('1 chapter')
+sect = guidexml.Section('1 section')
+
+taguri = guidexml.uri("http://google.de")
+tagpara = guidexml.paragraph("hello world, Visit: %s.das ist ein sehr langer' \
+ 'text mit mehr als MAXLENGTH Zeichen." %
+ repr(taguri))
+
+doc.append(chap)
+chap.append(sect)
+sect.append(tagpara)
+
+doc.create('/', 'file')
+
+
+def test_kernel_version():
+ 'Test if kernel releases are parsed correctly'
+
+ kernelcases = {
+ '2.6.29.1' :
+ {'source' : 'vanilla',
+ 'revision' : 'r0',
+ 'version' : '2.6.29.1'},
+ '2.6.18-xen-r11' :
+ {'source' : 'xen',
+ 'revision' : 'r11',
+ 'version' : '2.6.18'},
+ '2.6.27-gentoo-r2' :
+ {'source' : 'gentoo',
+ 'revision' : 'r2',
+ 'version' : '2.6.27'},
+ '2.6.28-hardened-r77' :
+ {'source' : 'hardened',
+ 'revision' : 'r77',
+ 'version' : '2.6.28'},
+ '2.6.28-r7' :
+ {'source' : 'vanilla',
+ 'revision' : 'r7',
+ 'version' : '2.6.28'},
+ '2.6.28-rc8' :
+ {'source' : 'vanilla',
+ 'revision' : 'r0',
+ 'version' : '2.6.28_rc8'},
+ '2.6.28-rc8-git6' :
+ {'source' : 'git',
+ 'revision' : 'r6',
+ 'version' : '2.6.28_rc8'},
+ '2' :
+ {'source' : 'vanilla',
+ 'revision' : 'r0',
+ 'version' : '2'},
+ '2.6.28-hardened-r7777' :
+ {'source' : 'hardened',
+ 'revision' : 'r0',
+ 'version' : '2.6.28'},
+ '2.6.2833-hardened-r7' :
+ None,
+
+}
+
+ suite = unittest.TestSuite()
+
+ for name, dict in kernelcases.iteritems():
+ newtest = KernelVersionTestCase(name, dict)
+ suite.addTest(newtest)
+
+ unittest.TextTestRunner(verbosity=2).run(suite)
+
+
+class KernelVersionTestCase(unittest.TestCase):
+
+ def __init__(self, name, dict):
+ unittest.TestCase.__init__(self, 'testFunction')
+ self.name = name
+ self.dict = dict
+
+ def testFunction(self):
+ rvalue = lib.extract_version_from(self.name)
+ self.assertEqual(self.dict, rvalue)
+"""
+
+
+def test_interval():
+ 'Test if a kernel release is affected'
+
+ kernelcase = ['gentoo', '2.6.30', 'r4', '2.6.30-5']
+ intervalcases = {
+ '[linux >=2.6.27 <=2.6.30] [gp <2.6.30.3]' : False,
+ '[linux >=2.6.27 <=2.6.30] [gp <2.6.30.6]' : True,
+ '[linux >=2.6.28 <=2.6.31] [gp <=2.6.30.5]' : True,
+ '[linux >=2.6.26 <2.6.28] [linux >2.6.29 <=2.6.30]' : True,
+
+ }
+
+ suite = unittest.TestSuite()
+
+ kernel = lib.Kernel(kernelcase[0])
+ kernel.version = kernelcase[1]
+ kernel.revision = kernelcase[2]
+ kernel_gp = lib.Genpatch(kernelcase[3])
+
+ for wb, affected in intervalcases.iteritems():
+ interval_list = lib.interval_from_whiteboard(wb)
+
+ newtest = IntervalTestCase(interval_list, kernel, kernel_gp, affected)
+ suite.addTest(newtest)
+
+ unittest.TextTestRunner(verbosity=2).run(suite)
+
+
+class IntervalTestCase(unittest.TestCase):
+
+ def __init__(self, interval_list, kernel, kernel_gp, affected):
+ unittest.TestCase.__init__(self, 'testFunction')
+ self.interval_list = interval_list
+ self.kernel = kernel
+ self.kernel_gp = kernel_gp
+ self.item = lib.Vulnerability('000000')
+ self.affected = affected
+
+ def testFunction(self):
+ rvalue = lib.is_affected(self.interval_list, self.kernel,
+ self.kernel_gp, self.item)
+ self.assertEqual(self.affected, rvalue)
+
+
+if __name__ == '__main__':
+ test_interval()
+