summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernelcheck/kernelcheck.py')
-rwxr-xr-xsrc/kernelcheck/kernelcheck.py274
1 files changed, 274 insertions, 0 deletions
diff --git a/src/kernelcheck/kernelcheck.py b/src/kernelcheck/kernelcheck.py
new file mode 100755
index 0000000..1587b98
--- /dev/null
+++ b/src/kernelcheck/kernelcheck.py
@@ -0,0 +1,274 @@
+#!/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
+
+import getopt
+import portage
+import sys
+import textwrap
+import os
+
+import lib.kernellib as lib
+
+info = portage.output.EOutput().einfo
+warn = portage.output.EOutput().ewarn
+error = portage.output.EOutput().eerror
+color = portage.output.colorize
+term = portage.output.get_term_size()
+
+def main(argv):
+ 'Main function'
+
+ try:
+ opts, args = getopt.getopt(argv, 'dhnr:s:v',
+ ['debug', 'help', 'nocolor', 'report=', 'show=', 'verbose'])
+ except getopt.GetoptError:
+ usage()
+ return
+
+ for opt, arg in opts:
+ if opt in ('-d', '--debug'):
+ lib.DEBUG = True
+ elif opt in ('-h', '--help'):
+ usage()
+ return
+ elif opt in ('-n', '--nocolor'):
+ portage.output.nocolor()
+ elif opt in ('-r', '--report'):
+ error('--report not yet implemented')
+ return
+ elif opt in ('-s', '--show'):
+ print_bug(arg)
+ return
+ elif opt in ('-v', '--verbose'):
+ lib.VERBOSE = True
+
+ print '>>> Gathering system information'
+
+ uname = os.uname()
+ if uname[0] != 'Linux':
+ error('This tool currently only works for Linux kernels.')
+ error('Apparantly you are using "%s".' % uname[0])
+ sys.exit()
+
+ kernel = lib.extract_version(uname[2])
+ if kernel is None:
+ error('No kernel information found!')
+ return
+
+ info('Kernel version : %s' % (color('GOOD', '%s-%s' %
+ (kernel.version, kernel.revision))))
+ info('Kernel source : %s' % color('GOOD', kernel.source))
+
+ kernel.genpatch = lib.get_genpatch(lib.PORTDIR, kernel)
+
+ if kernel.genpatch is not None:
+ info('Gen(too)patch : %s' % color('GOOD', '%s %s' %
+ (kernel.genpatch.version, repr(kernel.genpatch))))
+ elif kernel.source == 'gentoo':
+ warn('No genpatch information found!')
+
+ arch = portage.settings['ARCH']
+ if arch:
+ info('Architecture : %s' % color('GOOD', arch))
+ else:
+ error('No architecture found!')
+ return
+
+ print '\n>>> Reading all kernel vulnerabilities'
+
+ """
+ supported = list()
+ for item in lib.SUPPORTED:
+ best = (lib.all_version(item))
+ if best and best is not None:
+ for i in best:
+ if item == 'gentoo':
+ i.genpatch = lib.get_genpatch(lib.read_genpatch_file(
+ lib.DIR['out']), i)
+ supported.append(i)
+ """
+
+ kernel_eval = lib.eval_cve_files(lib.DIR['out'], kernel, arch)
+ if not kernel_eval:
+ error('No kernel vulnerability files found!')
+ return
+
+ info('%s vulnerabilities read.' %
+ color('GOOD', str(kernel_eval.read)))
+ info('%s apply to this architecture.' %
+ color('GOOD', str(kernel_eval.arch)))
+ info('%s do not affect this kernel.' %
+ color('GOOD', str(len(kernel_eval.unaffected))))
+
+ if (len(kernel_eval.affected) is 0):
+ info('Your kernel is not affected by any known vulnerabilites!')
+ return
+
+ error('%s affect this kernel: ' %
+ color('BAD', str(len(kernel_eval.affected))))
+ print_summary(kernel_eval.affected)
+
+ """
+ info('You have the following choices: ')
+ print ''
+
+ info('[1] Recommended')
+ info('Keep your current kernel: %s' % color('BRACKET',
+ 'sys-kernel/%s-sources-%s-%s' % (
+ kernel.source, kernel.version, kernel.revision)))
+ print ''
+
+ choice = 1
+ for item in supported:
+ supported_eval = lib.eval_cve_files(lib.DIR['out'], item, arch)
+
+ if not supported_eval or kernel == item:
+ continue
+
+ else:
+ comparison = lib.compare_evaluation(kernel_eval, supported_eval)
+
+ if comparison is not None:
+ choice += 1;
+ score = 0
+ for fix in comparison.fixed:
+ for cve in fix.cves:
+ score += float(cve.score)
+
+ for new in comparison.new:
+ for cve in new.cves:
+ score -= float(cve.score)
+
+ info('[%s] Recommended: (Score %s)' % (str(choice), score))
+ info('Upgrade to this kernel: %s' % color('BRACKET',
+ 'sys-kernel/%s-sources-%s-%s' % (
+ item.source, item.version, item.revision)))
+ info('which fixes %s of %s vulnerabilities and introduces %s' \
+ ' new' % (color('GOOD', str(len(comparison.fixed))),
+ color('BAD', str(len(kernel_eval.affected))),
+ color('BAD', str(len(comparison.new)))))
+ print ''
+ """
+
+ print_information()
+ print_beta()
+
+
+def print_summary(vullist):
+ 'Prints the vulnerability summary'
+
+ for item in vullist:
+
+ whiteboard = str()
+ for interval in item.affected:
+ whiteboard += '[' + str(interval) + '] '
+
+ if item.cves:
+ print ''
+
+ for cve in item.cves:
+ severity = 'BAD'
+ if cve.severity == 'Low':
+ severity = 'GOOD'
+ elif cve.severity == 'Medium':
+ severity = 'WARN'
+
+ print '\nBugid %s %-32s %s %s\n"%s..."' % (item.bugid,
+ color(severity, cve.severity + ' (' + cve.score + ')'),
+ cve.cve, whiteboard, cve.desc[:term[1]-6])
+
+ print '\n'
+
+
+def print_bug(bugid):
+ 'Prints information about a particular bugid'
+
+ if 'cve' in bugid.lower():
+ 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'
+
+ 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()
+
+ 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'])
+ if vul is None:
+ error('Could not find cve: %s' % cveid)
+ return
+ else:
+ for item in vul.cves:
+ 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))
+ #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.' %
+ color('BAD', 'IMPORTANT'))
+ error('Please note that this tool might not operate as expected.')
+
+
+def print_information():
+ 'Prints an information message'
+
+ info('To print more information about a vulnerability try:')
+ info(' $ %s -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'
+
+
+if __name__ == '__main__':
+ main(sys.argv[1:])
+