summaryrefslogtreecommitdiff
path: root/pym
diff options
context:
space:
mode:
Diffstat (limited to 'pym')
-rwxr-xr-xpym/kernelcheck/kernelcheck.py233
-rw-r--r--pym/kernelcheck/lib/kernellib.py57
2 files changed, 144 insertions, 146 deletions
diff --git a/pym/kernelcheck/kernelcheck.py b/pym/kernelcheck/kernelcheck.py
index ae4f490..1cb359c 100755
--- a/pym/kernelcheck/kernelcheck.py
+++ b/pym/kernelcheck/kernelcheck.py
@@ -1,14 +1,16 @@
#!/usr/bin/env python
-# kernel-check -- Kernel security information
+# kernel-check -- Gentoo Kernel Security
# Copyright 2009-2009 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
from portage.output import blue, bold, colorize, EOutput, darkgreen #FIXME
-#from _emerge.stdout_spinner import stdout_spinner #TODO
+
try:
from _emerge.userquery import userquery
+ from _emerge.stdout_spinner import stdout_spinner
except ImportError:
from _emerge import userquery #FIXME proper checking without except
+ from _emerge import stdout_spinner
import getopt
import portage
@@ -21,16 +23,15 @@ import lib.kernellib as lib
info = EOutput().einfo #FIXME
warn = EOutput().ewarn
error = EOutput().eerror
-#spin = stdout_spinner()
-term = portage.output.get_term_size()
+spin = stdout_spinner()
def main(argv):
'Main function'
try:
- opts, args = getopt.getopt(argv, 'dhnr:s:v',
- ['debug', 'help', 'nocolor', 'report=', 'show=', 'verbose'])
- except getopt.GetoptError:
+ opts, args = getopt.getopt(argv, 'dhnr:sv',
+ ['debug', 'help', 'nocolor', 'report=', 'sync', 'verbose'])
+ except getopt.GetoptError, e:
usage()
return
@@ -45,14 +46,23 @@ def main(argv):
elif opt in ('-r', '--report'):
error('--report not yet implemented')
return
- elif opt in ('-s', '--show'):
- print_bug(arg)
+ elif opt in ('-s', '--sync'):
+ os.system('%s%s' % ('rsync -avz rsync://rbu.sh/gentoo-kernel ',
+ '/usr/portage/metadata/kernel'))
return
elif opt in ('-v', '--verbose'):
lib.VERBOSE = True
+ for arg in argv:
+ if lib.REGEX['argument'].match(arg):
+ if 'cve' in arg.lower():
+ vul = lib.find_cve(arg, lib.DIR['out'])
+ print_bug(vul.bugid)
+ else:
+ print_bug(arg)
+ return
+
information = dict()
- configuration = dict()
print ''
print darkgreen('These are the specifications of your kernel:')
@@ -69,49 +79,27 @@ def main(argv):
error('No kernel information found!')
return
- information['Kernel source'] = kernel.source
- information['Kernel version'] = '%s-%s' % (kernel.version, kernel.revision)
+ arch = portage.settings['ARCH']
+ if not arch:
+ arch = '?' #FIXME
kernel.genpatch = lib.get_genpatch(lib.PORTDIR, kernel)
-
- if kernel.genpatch is not None: #FIXME
- information['Kernel patches'] = '%s %s (%s)' % ('genpatch',
- kernel.genpatch.version,
- repr(kernel.genpatch))
-
- elif kernel.source == 'gentoo':
- warn('No genpatch information found!') #FIXME
-
- arch = portage.settings['ARCH']
- if arch:
- information['Architecture'] = arch
+ if not kernel.genpatch:
+ genpatch = ''
else:
- error('No architecture found!') #FIXME
- return
-
- info(bold('Information:'))
- print_items(information)
+ genpatch = '%s %s (%s)' % ('genpatch', kernel.genpatch.version,
+ repr(kernel.genpatch))
- min_addr = str() #TODO move to kernellib
- try:
- min_addr = open('/proc/sys/vm/mmap_min_addr').read().strip()
- except:
- min_addr = '?'
-
- configuration['Mmap_min_addr'] = min_addr
-
- modules = str() #TODO move to kernellib
- try:
- for line in open('/proc/modules').readlines():
- modules += '%s ' % line.split(' ')[0]
- except:
- modules = '?'
-
- configuration['Loaded modules'] = modules
+ information = {
+ 'Kernel source' : kernel.source,
+ 'Kernel version' : '%s-%s' % (kernel.version, kernel.revision),
+ 'Kernel patches' : genpatch,
+ 'Architecture' : arch
+ }
+ print_items(information, 'Information')
print ''
- info(bold('Configuration:'))
- print_items(configuration)
+ print_items(lib.gather_configuration(), 'Configuration')
print '\nDetermining vulnerabilities... done!' #TODO #spin
print ''
@@ -123,42 +111,8 @@ def main(argv):
print_summary(kernel_eval.affected)
- low = int() #TODO move to kernellib
- medium = int()
- high = int()
- cvss_score = float()
- cve_amount = int()
-
- for item in kernel_eval.affected:
- for cve in item.cves:
- if cve.severity == 'Low':
- low += 1
- if cve.severity == 'Medium':
- medium += 1
- if cve.severity == 'High':
- high += 1
- if len(kernel_eval.affected) is not 0:
- for cve in item.cves:
- cve_amount += 1
- cvss_score += float(cve.score)
-
- cvss_score = cvss_score / cve_amount
-
- severity_eval = str()
-
- if high is not 0:
- severity_eval += '%s high' % high
- if medium is not 0:
- if high is not 0:
- severity_eval += ', '
- severity_eval += '%s medium' % medium
- if low is not 0:
- if high is not 0 or medium is not 0:
- severity_eval += ', '
- severity_eval += '%s low' % low
-
print 'Total: %s vulnerabilities (%s), Average CVSS score: %.1f' % (
- len(kernel_eval.affected), severity_eval, cvss_score)
+ len(kernel_eval.affected), repr(kernel_eval), kernel_eval.avg_cvss)
print ''
@@ -171,15 +125,20 @@ def main(argv):
else:
print 'Not implemented yet ;)'
-def print_items(category):
+def print_items(category, header):
'Indents and prints items'
+ screenwidth = 120
+ if portage.output.get_term_size()[1] < screenwidth:
+ screenwidth = portage.output.get_term_size()[1]
+
+ info(bold('%s%s' % (header, ':')))
for item in category.keys():
for i, string in enumerate(textwrap.wrap('%s' % category[item],
- (term[1] - 23))):
+ (screenwidth - 23))):
if i is 0:
- print ' %s%s : %s' % (darkgreen(item),
- ' ' * (14 - len(item)), string)
+ print '%s%s%s : %s' % (' ' * 6, darkgreen(item),
+ ' ' * (14 - len(item)), string)
else:
print '%s%s' % (' ' * 23, string)
@@ -194,7 +153,6 @@ def print_summary(vullist):
whiteboard += '[' + str(interval) + '] '
if item.cves:
-
for cve in item.cves:
severity = 'BAD'
if cve.severity == 'Low':
@@ -203,32 +161,30 @@ def print_summary(vullist):
severity = 'WARN'
cve_text = str()
- cve_area = str()
if 'AV:L' in cve.vector:
- cve_area += colorize('WARN', 'local')
+ cve_text += colorize('WARN', 'local')
if 'AV:A' in cve.vector or 'AV:N' in cve.vector:
- cve_area += colorize('BAD', 'network')
-
- if 'C:P' in cve.vector or 'C:C' in cve.vector:
- cve_text += ' -confidentiality'
-
- if 'I:P' in cve.vector or 'I:C' in cve.vector:
- cve_text += ' -integrity'
-
- if 'A:P' in cve.vector or 'A:C' in cve.vector:
- cve_text += ' -availability'
+ cve_text += colorize('BAD', 'network')
if ('C:P' in cve.vector or 'C:C' in cve.vector) \
and ('I:P' in cve.vector or 'I:C' in cve.vector) \
and ('A:P' in cve.vector or 'A:C' in cve.vector):
- cve_text = ' -complete'
+ cve_text += '%s%s' % (' ', blue('-complete'))
+ else:
+ if 'C:P' in cve.vector or 'C:C' in cve.vector:
+ cve_text += '%s%s' % (' ', blue('-confidentiality'))
+
+ if 'I:P' in cve.vector or 'I:C' in cve.vector:
+ cve_text += '%s%s' % (' ', blue('-integrity'))
- first_text = textwrap.wrap(cve.desc, term[1] - 44)[0]
- print '[%s %26s] %s CVSS="%s %s%s"' % (darkgreen('bugid'),
+ if 'A:P' in cve.vector or 'A:C' in cve.vector:
+ cve_text += '%s%s' % (' ', blue('-availability'))
+
+ print '[%s %26s] %s CVSS="%s %s"' % (darkgreen('bugid'),
colorize('GOOD', item.bugid), darkgreen(cve.cve),
- colorize(severity, cve.score), cve_area, blue(cve_text))
+ colorize(severity, cve.score), cve_text)
print ''
@@ -240,35 +196,32 @@ def print_bug(bugid):
print_cve(bugid.upper())
return
- whiteboard = str()
- cves = str()
vul = lib.read_cve_file(lib.DIR['out'], bugid)
if vul is None:
error('Could not find bugid: %s' % bugid)
return
- for i, interval in enumerate(vul.affected):
- if i is not 0:
- whiteboard += ' ' * 14
- whiteboard += '[' + str(interval) + ']\n'
+ buginformation = {
+ 'Status' : vul.status.capitalize(),
+ 'Reporter' : vul.reporter,
+ 'Reported' : vul.reported[:-11],
+ 'Affected' : vul.affected,
+ 'Architecture' : vul.arch.capitalize()
+ }
- info('Bugid : %s - %s' % (vul.bugid, vul.status.capitalize()))
- info('Reported : %s - %s' % (vul.reporter, vul.reported[:-5]))
- info('Affected : %s' % whiteboard[:-1])
- #TODO arch = str()
+ print ''
+ print_items(buginformation, '%s%s' % ('Bugid ', bugid))
for cve in vul.cves:
- print ''
print_cve(cve.cve)
def print_cve(cveid):
'Prints information about a cve'
- cve = lib.Cve('cveid')
-
- vul = lib.find_cve(cveid, lib.DIR['out'])
+ cve = lib.Cve(cveid)
+ vul = lib.find_cve(cveid, lib.DIR['out']) #FIXME
if vul is None:
error('Could not find cve: %s' % cveid)
return
@@ -277,47 +230,37 @@ def print_cve(cveid):
if item.cve == cveid:
cve = item
- info('Cve : %s - %s - Bugid %s' % (cve.cve, cve.published, vul.bugid))
- info('Severity : %s %s - %s' % (cve.severity, cve.score, cve.vector))
+ cveinformation = {
+ 'Published' : cve.published,
+ 'Severity' : cve.severity,
+ 'Score' : cve.score,
+ 'Vector' : cve.vector,
+ 'Description' : cve.desc,
+ }
#TODO print cve.refs
- for i, string in enumerate(textwrap.wrap('"%s"' % cve.desc ,
- (term[1] - 15))):
- if i is 0:
- info('Desc : %s' % string)
- else:
- print ' ' * 15 + string
-
- return
-
-
-def print_beta():
- 'Prints a beta warning message'
-
- print('')
- error('%s You are using an early version of kernel-check.' %
- colorize('BAD', 'IMPORTANT'))
- error('Please note that this tool might not operate as expected.')
+ print ''
+ print_items(cveinformation, cve.cve)
def print_information():
'Prints an information message'
info('To print more information about a vulnerability try:')
- info(' $ %s -s [bugid|cve]' % sys.argv[0])
+ info(' $ %s [BUGID|CVE]' % sys.argv[0])
def usage():
'Prints the usage screen'
- print 'Usage: %s [OPTION]...' % sys.argv[0][:-3]
- print 'Kernel security information %s\r\n' % lib.VERSION
- print ' -d, --debug display debugging information'
- print ' -h, --help display help information'
- print ' -n, --nocolor disable colors'
- print ' -r, --report [file] create a security report'
- print ' -s, --show [bugid|cve] display information about a bug or cve'
- print ' -v, --verbose display additional information'
+ print 'Usage: kernel-check [BUGID|CVE] [OPTION]...'
+ print 'Gentoo Kernel Security %s\n' % lib.VERSION
+ print ' -d, --debug display debugging information'
+ print ' -h, --help display help information'
+ print ' -n, --nocolor disable colors'
+ print ' -r, --report [file] create a security report'
+ print ' -s, --sync receive the latest vulnerabilities'
+ print ' -v, --verbose display additional information'
if __name__ == '__main__':
diff --git a/pym/kernelcheck/lib/kernellib.py b/pym/kernelcheck/lib/kernellib.py
index 515511b..6aa3270 100644
--- a/pym/kernelcheck/lib/kernellib.py
+++ b/pym/kernelcheck/lib/kernellib.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python
-# kernel-check -- Kernel security information
+# kernel-check -- Gentoo Kernel Security
# Copyright 2009-2009 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
@@ -24,6 +24,7 @@ ARCHES = [
]
REGEX = {
+ 'argument' : re.compile(r'(CVE-(\d{4})-(\d{4}))|(\d{5,7})'),
'gp_version' : re.compile(r'(?<=K_GENPATCHES_VER\=\").+(?=\")'),
'gp_want' : re.compile(r'(?<=K_WANT_GENPATCHES\=\").+(?=\")'),
'k_version' : re.compile(r'^((?:\d{1,2}\.){0,4}\d{1,2})(-.*)?$'),
@@ -74,11 +75,30 @@ class Evaluation:
arch = int()
affected = list()
unaffected = list()
+ avg_cvss = float()
+ low = int()
+ medium = int()
+ high = int()
def __init__(self):
self.affected = list()
self.unaffected = list()
+ def __repr__(self):
+ severity = str()
+ if self.high is not 0:
+ severity += '%s high' % self.high
+ if self.medium is not 0:
+ if self.high is not 0:
+ severity += ', '
+ severity += '%s medium' % self.medium
+ if self.low is not 0:
+ if self.high is not 0 or self.medium is not 0:
+ severity += ', '
+ severity += '%s low' % self.low
+
+ return severity
+
class Comparison: #TODO Check if deprecated
"""Comparison class
@@ -418,6 +438,8 @@ def eval_cve_files(directory, kernel, arch, spin=None):
if not files:
return None
+ cve_amount = int()
+ cvss_score = int()
evaluation = Evaluation()
for item in files:
@@ -435,9 +457,20 @@ def eval_cve_files(directory, kernel, arch, spin=None):
if is_affected(item.affected, kernel, item):
evaluation.affected.append(item)
+ for cve in item.cves:
+ if cve.severity == 'Low':
+ evaluation.low += 1
+ if cve.severity == 'Medium':
+ evaluation.medium += 1
+ if cve.severity == 'High':
+ evaluation.high += 1
+ cve_amount += 1
+ cvss_score += float(cve.score)
else:
evaluation.unaffected.append(item)
+ evaluation.avg_cvss = cvss_score / cve_amount
+
return evaluation
#TODO Remove item
@@ -614,3 +647,25 @@ def all_version(source):
return versions
+def gather_configuration():
+ ""
+
+ config = dict()
+ mmap_min_addr = str()
+ modules = str()
+
+ try:
+ mmap_min_addr = open('/proc/sys/vm/mmap_min_addr').read().strip()
+ except:
+ mmap_min_addr = '?'
+ config['Mmap_min_addr'] = mmap_min_addr
+
+ try:
+ for line in open('/proc/modules').readlines():
+ modules += '%s ' % line.split(' ')[0]
+ except:
+ modules = '?'
+ config['Loaded modules'] = modules
+
+ return config
+