diff options
Diffstat (limited to 'src/kernelcheck/kernelcheck.py')
-rwxr-xr-x | src/kernelcheck/kernelcheck.py | 274 |
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:]) + |