diff options
author | Bjoern Tropf <asymmail@googlemail.com> | 2009-08-22 11:17:03 +0200 |
---|---|---|
committer | Bjoern Tropf <asymmail@googlemail.com> | 2009-08-22 11:17:03 +0200 |
commit | bc703b78be5a3931af7ba3ac47c2002a23b940ad (patch) | |
tree | 65378792cdcec6ea6a7c219bd4669b67a2c7ab48 | |
parent | Break lines after 79 characters (diff) | |
download | kernel-check-bc703b78be5a3931af7ba3ac47c2002a23b940ad.tar.gz kernel-check-bc703b78be5a3931af7ba3ac47c2002a23b940ad.tar.bz2 kernel-check-bc703b78be5a3931af7ba3ac47c2002a23b940ad.zip |
Implement show bugid
Rework output
Add beta message
Remove sys.exit()
Add debug arg (-d, --debug)
Fix one exception
-rw-r--r-- | TODO | 40 | ||||
-rwxr-xr-x | collector.py | 4 | ||||
-rwxr-xr-x | kernel-check.py | 178 | ||||
-rwxr-xr-x | kernellib.py | 22 |
4 files changed, 178 insertions, 66 deletions
@@ -1,19 +1,29 @@ -Todo -==== -- Fix all inline TODO/FIXME markers -- Find a solution for <ref source url/> -- Use telling function- and variable names -- Rework interval class and all interval functions (expand?) -- Rework cves.refs -- Use exeptions instead of debug() +Implementation +============== +- Implement Report +- Handle "best kernel not found" - Add further error handling -- [kernel +<version] -> [+kernel <version] -- Ignore vserver whiteboard -- Find a way to insert arch into bugzilla - Implement find_cve() (return bugid) -- Write a proper documentation -- Implement DTD + +Cleanup and Rework +================== - Remove unused code and find better ways - Check lookaround of 'grp_all' -- Handle "best kernel not found" -- Implement Show and Report +- Rework interval class and all interval functions (expand?) +- Rework cves.refs and find a solution for <ref source url/> + +Dokumentation +============= +- Use telling function- and variable names +- Write a proper documentation +- Implement DTD + +Whiteboard changes +================== +- Move arch into whiteboard e.g. {x86, amd64} +- [kernel +<version] -> [+kernel <version] +- Ignore vserver whiteboard + +Summary changes +=============== +- Explicitly mention the CVSS score e.g. (CVSS-5.6) diff --git a/collector.py b/collector.py index d817024..8aed337 100755 --- a/collector.py +++ b/collector.py @@ -19,6 +19,7 @@ def main(argv): ['delay=', 'force', 'help', 'skip', 'verbose']) except getopt.GetoptError: usage() + return for opt, arg in opts: if opt in ('-d', '--delay'): @@ -28,6 +29,7 @@ def main(argv): lib.FORCE = True elif opt in ('-h', '--help'): usage() + return elif opt in ('-s', '--skip'): lib.SKIP = True elif opt in ('-v', '--verbose'): @@ -103,6 +105,7 @@ def main(argv): print '\nCreated %i xml files!' % created_files + def usage(): 'Prints the usage screen' @@ -113,7 +116,6 @@ def usage(): print ' -h, --help display help information' print ' -s, --skip skip update of prior nvd files' print ' -v, --verbose display debugging information' - sys.exit() if __name__ == '__main__': diff --git a/kernel-check.py b/kernel-check.py index 62b519d..e5a0c70 100755 --- a/kernel-check.py +++ b/kernel-check.py @@ -10,32 +10,35 @@ import os import 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' - 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() - try: - opts, args = getopt.getopt(argv, 'hnr:s:v', - ['help', 'nocolor', 'report=', 'show=', 'verbose']) + 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 ('-h', '--help'): + 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'): - error('--show not yet implemented') + print_bug(arg) return elif opt in ('-v', '--verbose'): lib.VERBOSE = True @@ -53,9 +56,9 @@ def main(argv): error('No kernel information found!') sys.exit() - info('Kernel version: %s' % (color('GOOD', '%s-%s' % + info('Kernel version : %s' % (color('GOOD', '%s-%s' % (kernel.version, kernel.revision)))) - info('Kernel sources: %s' % color('GOOD', kernel.source)) + info('Kernel source : %s' % color('GOOD', kernel.source)) best = lib.best_version(kernel.source) if not best: @@ -66,16 +69,16 @@ def main(argv): genpatch = lib.get_genpatch(lib.read_genpatch_file(lib.FOLDER['out']), kernel) if genpatch is not None: - info('Integrated genpatch: %s' % color('GOOD', '%s %s' % + info('Gen(too)patch : %s' % color('GOOD', '%s %s' % (genpatch.version, repr(genpatch)))) - elif lib.VERBOSE: - info('No genpatch information found.') + elif kernel.source == 'gentoo': + warn('No genpatch information found!') arch = portage.settings['ARCH'] if arch: - info('System architecture: %s' % color('GOOD', arch)) + info('Architecture : %s' % color('GOOD', arch)) else: - error('No system architecture found!') + error('No architecture found!') sys.exit() print '\n>>> Reading all kernel vulnerabilities' @@ -89,38 +92,31 @@ def main(argv): info('%s do not affect this system.' % color('GOOD', str(schedule.fixed))) - if len(schedule.canfix): - error('%s can be fixed by upgrading.' % - color('BAD', str(len(schedule.canfix)))) - else: - info('No vulnerability can be fixed by upgrading.') - if len(schedule.notfix): warn('%s have not been fixed yet.' % color('WARN', str(len(schedule.notfix)))) + if lib.VERBOSE: + print_summary(schedule.notfix) + else: info('No vulnerabilities have not been fixed yet.') + if len(schedule.canfix): + error('%s can be fixed by upgrading.' % + color('BAD', str(len(schedule.canfix)))) + else: + info('No vulnerability can be fixed by upgrading.') + else: error('No vulnerability files found!') sys.exit() if len(schedule.canfix): - print '\nThese could be fixed by upgrading:' - for item in schedule.canfix: - print '\n Bugid %s:' % item.bugid - for cve in item.cves: - print ' %s - %s\n "%s..."' % (cve.cve, - cve.severity, cve.desc[:term[1]-14]) - print '' - info('To print more information about a vulnerability try:') - info('') - info(' $ %s -s [bugid]' % sys.argv[0]) - info('') + print_summary(schedule.canfix) info('It is recommended to upgrade your kernel to %s.' % color('GOOD', best.version + '-' + best.revision)) else: - info('') + print "" if kernel == best: info('Your kernel is up to date!') else: @@ -128,18 +124,118 @@ def main(argv): color('GOOD', best.version + '-' + best.revision)) info('does not improve your security!') + if len(schedule.canfix) or (len(schedule.notfix) and lib.VERBOSE): + info('') + info('To print more information about a vulnerability try:') + info('') + info(' $ %s -s [bugid|cve]' % sys.argv[0]) + info('') + + print_beta() + + +def print_summary(vullist): + 'Prints the vulnerability summary' + + severity = str() + + for item in vullist: + print '\nBugid %s' % item.bugid + for cve in item.cves: + if cve.severity == 'Low': + severity = 'GOOD' + elif cve.severity == 'Medium': + severity = 'WARN' + else: + severity = 'BAD' + + print '%s - %s\n"%s..."' % (cve.cve, + color(severity, cve.severity + ' (' + cve.score + ')'), + cve.desc[:term[1]-6]) + print '' + + +def print_bug(bugid): + 'Prints information about a particular bugid' + + if 'CVE' in bugid.upper(): + #print_cve(bugid) + #TODO find_cve + return + + whiteboard = str() + cves = str() + vul = lib.read_cve_file(lib.FOLDER['out'], bugid) + + if vul == 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 : ' + vul.bugid + ' - ' + vul.status.capitalize()) + info('Reported : ' + vul.reporter + ' - ' + vul.reported[:-5]) + info('Affected : ' + whiteboard[:-1]) + #TODO arch = str() + + for cve in vul.cves: + print '' + print_cve(cve) + +def print_cve(cve): + 'Prints information about a cve' + + info('Cve : ' + cve.cve + ' - ' + cve.published) + info('Severity : ' + cve.severity + ' ' + cve.score + ' - ' + cve.vector) + info('Desc : ' + break_line('"' + cve.desc + '"', 14)[14:]) + #TODO print cve.refs + + return + +def break_line(string, indent): + 'Breaks the line at the last whitespace' + + ret = str() + last_space = 0 + p_last_space = 0; + + for i, char in enumerate(string): + if char == ' ': + last_space = i; + + if i % (term[1] - indent) is 0 and i is not 0: + ret += (' ' * indent) + string[p_last_space:last_space] + '\n' + p_last_space = last_space + + if i == len(string) - 1: #FIXME why does 'is' not work? + ret += (' ' * indent) + string[p_last_space:len(string)] + + return ret + + +def print_beta(): + print '' + error('%s You are using a very early version of kernel-check!' % + color('BAD', 'IMPORTANT')) + error('Please note that this tool might not operate as expected.') + error('Moreover the given information are most likely incorrect.') + def usage(): 'Prints the usage screen' print 'Usage: %s [OPTION]...' % sys.argv[0][:-3] print 'Kernel security information %s\r\n' % lib.VERSION - print ' -h, --help display help information' - print ' -n, --nocolor disable colors' - print ' -r, --report [file] create a security report' - print ' -s, --show [bugid] display information about a bug' - print ' -v, --verbose display debugging information' - sys.exit() + 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 debugging information' if __name__ == '__main__': diff --git a/kernellib.py b/kernellib.py index d201ac8..921a37a 100755 --- a/kernellib.py +++ b/kernellib.py @@ -58,10 +58,11 @@ KERNEL_TYPES = [ 'vserver', 'win4lin', 'wolk-dev', 'wolk', 'xbox', 'xen', 'xfs' ] -VERSION = '0.5.5' +VERSION = '0.5.6' NOCVE = 'GENERIC-MAP-NOMATCH' CVES = dict() PORTDIR = portage.settings['PORTDIR'] +DEBUG = False VERBOSE = False FORCE = False SKIP = False @@ -74,13 +75,11 @@ FOLDER = { 'nvd' : os.path.join(FILEPATH, 'tmp', 'nvd') } - #TODO Deprecated logging.basicConfig(format='%(levelname)-6s[%(asctime)s] : %(message)s', datefmt='%H:%M:%S', level=logging.DEBUG) - #TODO Deprecated def debug(msg): - if VERBOSE: + if DEBUG: logging.debug(msg) @@ -629,7 +628,9 @@ def parse_cve_files(directory, kernel, best, arch): for item in os.listdir(directory): try: - files.append(read_cve_file(directory, item[:-4])) + cve_file = read_cve_file(directory, item[:-4]) + if cve_file is not None: + files.append(cve_file) except: #FIXME specify pass @@ -673,10 +674,13 @@ def read_cve_file(directory, bugid): affected = list() filename = os.path.join(directory, bugid + '.xml') - - with open(filename, 'r+') as xml_data: - memory_map = mmap.mmap(xml_data.fileno(), 0) - root = et.parse(memory_map).getroot() + + try: + with open(filename, 'r+') as xml_data: + memory_map = mmap.mmap(xml_data.fileno(), 0) + root = et.parse(memory_map).getroot() + except IOError: + return None bugroot = root.find('bug') |