diff options
Diffstat (limited to 'scripts/cvert-foss')
-rwxr-xr-x | scripts/cvert-foss | 151 |
1 files changed, 151 insertions, 0 deletions
diff --git a/scripts/cvert-foss b/scripts/cvert-foss new file mode 100755 index 0000000..00fbf2c --- /dev/null +++ b/scripts/cvert-foss @@ -0,0 +1,151 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2018 by Cisco Systems, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# + +""" Generate CVE report for the given CVE manifest +""" + +import sys +import textwrap +import argparse +import logging +import logging.config +import cvert + +def report_foss(): + """Generate CVE report""" + + parser = argparse.ArgumentParser( + formatter_class=argparse.RawDescriptionHelpFormatter, + description=textwrap.dedent(""" + Generate CVE report for the given CVE manifest. + """), + epilog=textwrap.dedent(""" + @ run examples: + + # Download (update) NVD feeds in "nvdfeed" directory + # and prepare the report for the "cve-manifest" file + %% %(prog)s --feed-dir nvdfeed --output report-foss.txt cve-manifest + + # Use existed NVD feeds in "nvdfeed" directory + # and prepare the report for the "cve-manifest" file + %% %(prog)s --offline --feed-dir nvdfeed --output report-foss.txt cve-manifest + + # (faster) Restore CVE dump from "cvedump" (must exist) + # and prepare the report for the "cve-manifest" file + %% %(prog)s --restore cvedump --output report-foss.txt cve-manifest + + # Restore CVE dump from "cvedump" (must exist) + # and prepare the extended report for the "cve-manifest" file + %% %(prog)s --restore cvedump --show-description --show-reference --output report-foss.txt cve-manifest + + @ manifest example: + + bash,4.2,CVE-2014-7187 + python,2.7.35, + python,3.5.5,CVE-2017-17522 CVE-2018-1061 + + @ report example output: + + . patched | 10.0 | CVE-2014-7187 | bash | 4.2 + . patched | 7.5 | CVE-2018-1061 | python | 3.5.5 + . patched | 8.8 | CVE-2017-17522 | python | 3.5.5 + unpatched | 10.0 | CVE-2014-6271 | bash | 4.2 + unpatched | 10.0 | CVE-2014-6277 | bash | 4.2 + unpatched | 10.0 | CVE-2014-6278 | bash | 4.2 + unpatched | 10.0 | CVE-2014-7169 | bash | 4.2 + unpatched | 10.0 | CVE-2014-7186 | bash | 4.2 + unpatched | 4.6 | CVE-2012-3410 | bash | 4.2 + unpatched | 8.4 | CVE-2016-7543 | bash | 4.2 + unpatched | 5.0 | CVE-2010-3492 | python | 2.7.35 + unpatched | 5.3 | CVE-2016-1494 | python | 2.7.35 + unpatched | 6.5 | CVE-2017-18207 | python | 3.5.5 + unpatched | 6.5 | CVE-2017-18207 | python | 2.7.35 + unpatched | 7.1 | CVE-2013-7338 | python | 2.7.35 + unpatched | 7.5 | CVE-2018-1060 | python | 3.5.5 + unpatched | 8.8 | CVE-2017-17522 | python | 2.7.35 + """)) + + group = parser.add_mutually_exclusive_group(required=True) + group.add_argument("-f", "--feed-dir", help="feeds directory") + group.add_argument("-d", "--restore", help="load CVE data structures from file", + metavar="FILENAME") + parser.add_argument("--offline", help="do not update from NVD site", + action="store_true") + parser.add_argument("-o", "--output", help="save report to the file") + parser.add_argument("--show-description", help='show "Description" in the report', + action="store_true") + parser.add_argument("--show-reference", help='show "Reference" in the report', + action="store_true") + parser.add_argument("--debug", help="print debug messages", + action="store_true") + + parser.add_argument("cve_manifest", help="file with a list of packages, " + "each line contains three comma separated values: name, " + "version and a space separated list of patched CVEs, " + "e.g.: python,3.5.5,CVE-2017-17522 CVE-2018-1061", + metavar="cve-manifest") + + args = parser.parse_args() + + logging.config.dictConfig(cvert.logconfig(args.debug)) + + cve_manifest = {} + + with open(args.cve_manifest, "r") as fil: + for lin in fil: + lin = lin.rstrip() + + # skip empty lines + if not lin: + continue + + product, version, patched = lin.split(",", maxsplit=3) + + if product in cve_manifest: + cve_manifest[product][version] = patched.split() + else: + cve_manifest[product] = { + version: patched.split() + } + + if args.restore: + cve_struct = cvert.load_cve(args.restore) + elif args.feed_dir: + cve_struct = cvert.update_feeds(args.feed_dir, args.offline) + + if not cve_struct and args.offline: + parser.error("No CVEs found. Try to turn off offline mode or use other file to restore.") + + if args.output: + output = open(args.output, "w") + else: + output = sys.stdout + + report = cvert.generate_report(cve_manifest, cve_struct) + + cvert.print_report(report, + show_description=args.show_description, + show_reference=args.show_reference, + output=output) + + if args.output: + output.close() + + +if __name__ == "__main__": + report_foss() |