From bc703b78be5a3931af7ba3ac47c2002a23b940ad Mon Sep 17 00:00:00 2001 From: Bjoern Tropf Date: Sat, 22 Aug 2009 11:17:03 +0200 Subject: Implement show bugid Rework output Add beta message Remove sys.exit() Add debug arg (-d, --debug) Fix one exception --- TODO | 40 ++++++++----- collector.py | 4 +- kernel-check.py | 178 +++++++++++++++++++++++++++++++++++++++++++------------- kernellib.py | 22 ++++--- 4 files changed, 178 insertions(+), 66 deletions(-) diff --git a/TODO b/TODO index cb65cfe..cc6e67e 100644 --- a/TODO +++ b/TODO @@ -1,19 +1,29 @@ -Todo -==== -- Fix all inline TODO/FIXME markers -- Find a solution for -- 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 + [+kernel + +Dokumentation +============= +- Use telling function- and variable names +- Write a proper documentation +- Implement DTD + +Whiteboard changes +================== +- Move arch into whiteboard e.g. {x86, amd64} +- [kernel + [+kernel >> 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') -- cgit v1.2.3-65-gdbad