From ed600f17592ce8ae7b0589333eb5558c9b446dc7 Mon Sep 17 00:00:00 2001 From: Jeremy Long Date: Sat, 8 Sep 2012 01:26:38 -0400 Subject: [PATCH] initial release --- README | 12 +- pom.xml | 56 +++- .../org/codesecure/dependencycheck/App.java | 59 +++- .../dependencycheck/data/cpe/CPEQuery.java | 16 +- .../dependencycheck/data/cpe/Index.java | 94 ++++++- .../data/cpe/xml/Importer.java | 28 +- .../reporting/ReportGenerator.java | 53 ++-- .../reporting/package-info.java | 12 + .../dependencycheck/scanner/Dependency.java | 9 +- .../scanner/EvidenceCollection.java | 2 +- .../dependencycheck/scanner/JarAnalyzer.java | 27 +- .../dependencycheck/scanner/Scanner.java | 2 +- .../dependencycheck/utils/CliParser.java | 151 ++++++---- .../dependencycheck/utils/Settings.java | 64 ++++- src/main/resources/dependencycheck.properties | 13 +- src/main/resources/templates/HtmlReport.vsl | 10 +- src/main/resources/templates/sample.html | 263 ------------------ .../data/BaseIndexTestCase.java | 2 +- .../dependencycheck/utils/CliParserTest.java | 5 +- .../dependencycheck/utils/DownloaderTest.java | 24 +- 20 files changed, 474 insertions(+), 428 deletions(-) create mode 100644 src/main/java/org/codesecure/dependencycheck/reporting/package-info.java delete mode 100644 src/main/resources/templates/sample.html diff --git a/README b/README index 428d08aec..0affa7e8d 100644 --- a/README +++ b/README @@ -1,14 +1,18 @@ About: -DependencyCheck is a simple utility that attempts to determine if there is a Common Product Enumeration (CPE) identifier for a given project dependency. If found, it will generate a report linking to the associated CVE entries. +DependencyCheck is a simple utility that attempts to determine if there is a +Common Product Enumeration (CPE) identifier for a given project dependency. +If found, it will generate a report linking to the associated CVE entries. Usage: Still under development: mvn package site +java -jar dependencycheck-0.1.jar -h + TODO: Add CVE download/indexing and CPE lookup. -Finish report generation. -Fix/finish the CLI. +Finish report generation (xml). +Consider utilizing the OSVDB in addition to CPE/CVE. Author: Jeremy Long (jeremy.long@gmail.com) -Copyright (c) 2012 Jeremy Long. All Rights Reserved. \ No newline at end of file +Copyright (c) 2012 Jeremy Long. All Rights Reserved. diff --git a/pom.xml b/pom.xml index d8a2ec0e7..37ef221d7 100644 --- a/pom.xml +++ b/pom.xml @@ -16,13 +16,14 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with DependencyCheck. If not, see . --> + 4.0.0 org.codesecure DependencyCheck - 1.0-SNAPSHOT + 0.1 jar DependencyCheck @@ -34,6 +35,11 @@ along with DependencyCheck. If not, see . jeremy.long@gmail.com + + scm:git:git@github.com:jeremylong/DependencyCheck.git + scm:git:git@github.com:jeremylong/DependencyCheck.git + scm:git:git@github.com:jeremylong/DependencyCheck.git + GNU General Public License version 3 @@ -44,6 +50,25 @@ along with DependencyCheck. If not, see . UTF-8 + + + src/main/resources + + **/*.properties + + true + + + src/main/resources + + **/*.properties + **/*.gif + **/*.js + + false + + + org.apache.maven.plugins @@ -54,7 +79,9 @@ along with DependencyCheck. If not, see . + org.apache.maven.plugins maven-dependency-plugin + 2.5.1 package @@ -153,15 +180,15 @@ along with DependencyCheck. If not, see . target - index.cpe - ${project.build.directory}/store/cpe + cve + ${project.build.directory}/store/cve - index.osvdb + osvdb ${project.build.directory}/store/osvdb - index.cpe + cpe ${project.build.directory}/store/cpe @@ -392,5 +419,24 @@ along with DependencyCheck. If not, see . javadoc provided + + joda-time + joda-time + 2.1 + + + joda-time + joda-time + 2.1 + javadoc + provided + + + joda-time + joda-time + 2.1 + sources + provided + diff --git a/src/main/java/org/codesecure/dependencycheck/App.java b/src/main/java/org/codesecure/dependencycheck/App.java index 03145e113..eb38744bd 100644 --- a/src/main/java/org/codesecure/dependencycheck/App.java +++ b/src/main/java/org/codesecure/dependencycheck/App.java @@ -1,14 +1,32 @@ package org.codesecure.dependencycheck; +/* + * This file is part of DependencyCheck. + * + * DependencyCheck is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * DependencyCheck 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 DependencyCheck. If not, see http://www.gnu.org/licenses/. + * + * Copyright (c) 2012 Jeremy Long. All Rights Reserved. + */ import java.io.FileNotFoundException; import java.io.IOException; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; -import java.util.prefs.Preferences; import javax.xml.parsers.ParserConfigurationException; import org.apache.commons.cli.ParseException; import org.codesecure.dependencycheck.data.cpe.CPEQuery; +import org.codesecure.dependencycheck.data.cpe.Index; import org.codesecure.dependencycheck.data.cpe.xml.Importer; import org.codesecure.dependencycheck.reporting.ReportGenerator; import org.codesecure.dependencycheck.scanner.Dependency; @@ -34,9 +52,8 @@ import org.xml.sax.SAXException; * * Copyright (c) 2012 Jeremy Long. All Rights Reserved. */ - /** - * + * The command line interface for the DependencyCheck application. * * @author Jeremy Long (jeremy.long@gmail.com) */ @@ -50,7 +67,12 @@ public class App { App app = new App(); app.run(args); } - + + /** + * main CLI entry-point into the application. + * + * @param args the command line arguments + */ public void run(String[] args) { CliParser cli = new CliParser(); try { @@ -62,18 +84,32 @@ public class App { Logger.getLogger(App.class.getName()).log(Level.SEVERE, null, ex); return; } - + if (cli.isGetVersion()) { cli.printVersionInfo(); } else if (cli.isLoadCPE()) { loadCPE(cli.getCpeFile()); } else if (cli.isRunScan()) { + if (cli.isAutoUpdate()) { + Index cpeI = new Index(); + try { + cpeI.updateIndexFromWeb(); + } catch (Exception ex) { + Logger.getLogger(App.class.getName()).log(Level.SEVERE, null, ex); + } + } + runScan(cli.getReportDirectory(), cli.getApplicationName(), cli.getScanFiles()); } else { cli.printHelp(); } - + } + + /** + * Loads the specified CPE.XML file into Lucene Index. + * @param cpePath + */ private void loadCPE(String cpePath) { try { Importer.importXML(cpePath); @@ -85,6 +121,13 @@ public class App { Logger.getLogger(App.class.getName()).log(Level.SEVERE, null, ex); } } + + /** + * Scans the specified directories and writes the dependency reports to the reportDirectory. + * @param reportDirectory the path to the directory where the reports will be written. + * @param applicationName the application name for the report. + * @param files the files/directories to scan. + */ private void runScan(String reportDirectory, String applicationName, String[] files) { try { Scanner scanner = new Scanner(); @@ -106,13 +149,11 @@ public class App { } catch (Exception ex) { Logger.getLogger(App.class.getName()).log(Level.SEVERE, null, ex); } - + } catch (IOException ex) { Logger.getLogger(App.class.getName()).log(Level.SEVERE, null, ex); } catch (org.apache.lucene.queryParser.ParseException ex) { Logger.getLogger(App.class.getName()).log(Level.SEVERE, null, ex); } - } - } diff --git a/src/main/java/org/codesecure/dependencycheck/data/cpe/CPEQuery.java b/src/main/java/org/codesecure/dependencycheck/data/cpe/CPEQuery.java index 56cf41c9c..6e0078763 100644 --- a/src/main/java/org/codesecure/dependencycheck/data/cpe/CPEQuery.java +++ b/src/main/java/org/codesecure/dependencycheck/data/cpe/CPEQuery.java @@ -61,7 +61,7 @@ public class CPEQuery { * utilized within the CPE Names. */ static final String CLEANSE_CHARACTER_RX = "[^A-Za-z0-9 _-]"; - /* A string representation of a regular expression used to remove all but + /* A string representation of a regular expression used to remove all but * alpha characters. */ static final String CLEANSE_NONALPHA_RX = "[^A-Za-z]*"; @@ -191,15 +191,15 @@ public class CPEQuery { do { List entries = searchCPE(vendors, titles, versions, dependency.getTitleEvidence().getWeighting(), dependency.getVendorEvidence().getWeighting()); - - if (entries.size()>0) { + + if (entries.size() > 0) { List verified = verifyEntries(entries, dependency); if (verified.size() > 0) { found = true; dependency.setCPEs(verified); } } - + if (!found) { int round = cnt % 3; if (round == 0) { @@ -320,7 +320,7 @@ public class CPEQuery { */ protected String buildSearch(String vendor, String product, String version, List vendorWeighting, List produdctWeightings) { - + StringBuilder sb = new StringBuilder(vendor.length() + product.length() + version.length() + Fields.PRODUCT.length() + Fields.VERSION.length() + Fields.VENDOR.length() + STRING_BUILDER_BUFFER); @@ -335,7 +335,7 @@ public class CPEQuery { if (!appendWeightedSearch(sb, Fields.VENDOR, vendor.toLowerCase(), vendorWeighting)) { return null; } - + sb.append(Fields.VERSION).append(":("); if (sb.indexOf("^") > 0) { //if we have a weighting on something else, reduce the weighting on the version a lot @@ -369,7 +369,7 @@ public class CPEQuery { sb.append(" ").append(field).append(":( "); String cleanText = cleanseText(searchText); - + if ("".equals(cleanText)) { return false; } @@ -408,7 +408,7 @@ public class CPEQuery { private String cleanseText(String text) { return text.replaceAll(CLEANSE_CHARACTER_RX, " "); } - + /** * Compares two strings after lower casing them and removing the non-alpha * characters. diff --git a/src/main/java/org/codesecure/dependencycheck/data/cpe/Index.java b/src/main/java/org/codesecure/dependencycheck/data/cpe/Index.java index ec1b3d5bf..cbaae8564 100644 --- a/src/main/java/org/codesecure/dependencycheck/data/cpe/Index.java +++ b/src/main/java/org/codesecure/dependencycheck/data/cpe/Index.java @@ -19,10 +19,16 @@ package org.codesecure.dependencycheck.data.cpe; */ import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; import java.io.IOException; +import java.io.OutputStream; +import java.io.OutputStreamWriter; import java.net.URL; import java.util.HashMap; import java.util.Map; +import java.util.Properties; import java.util.logging.Level; import java.util.logging.Logger; import org.apache.lucene.analysis.Analyzer; @@ -38,6 +44,8 @@ import org.apache.lucene.util.Version; import org.codesecure.dependencycheck.utils.Downloader; import org.codesecure.dependencycheck.utils.Settings; import org.codesecure.dependencycheck.data.cpe.xml.Importer; +import org.joda.time.DateTime; +import org.joda.time.Days; /** * The Index class is used to utilize and maintain the CPE Index. @@ -46,6 +54,14 @@ import org.codesecure.dependencycheck.data.cpe.xml.Importer; */ public class Index { + /** + * Te name of the properties file containing the timestamp of the last update. + */ + private static final String UPDATE_PROPERTIES_FILE = "lastupdated.prop"; + /** + * The properties file key for the last updated field. + */ + private static final String LAST_UPDATED = "lastupdated"; /** * The Lucene directory containing the index. */ @@ -124,10 +140,47 @@ public class Index { outputPath = File.createTempFile("cpe", ".xml"); Downloader.fetchFile(url, outputPath); Importer.importXML(outputPath.toString()); + writeLastUpdatedPropertyFile(); } catch (Exception ex) { Logger.getLogger(Index.class.getName()).log(Level.SEVERE, null, ex); } finally { - outputPath.delete(); + boolean deleted = false; + try { + deleted = outputPath.delete(); + } finally { + if (!deleted) { + outputPath.deleteOnExit(); + } + } + } + } + } + + private void writeLastUpdatedPropertyFile() { + DateTime now = new DateTime(); + String dir = Settings.getString(Settings.KEYS.CPE_INDEX); + File cpeProp = new File(dir + File.separatorChar + UPDATE_PROPERTIES_FILE); + Properties prop = new Properties(); + prop.put(this.LAST_UPDATED, String.valueOf(now.getMillis())); + OutputStream os = null; + try { + os = new FileOutputStream(cpeProp); + OutputStreamWriter out = new OutputStreamWriter(os); + prop.store(out, dir); + } catch (FileNotFoundException ex) { + Logger.getLogger(Index.class.getName()).log(Level.SEVERE, null, ex); + } catch (IOException ex) { + Logger.getLogger(Index.class.getName()).log(Level.SEVERE, null, ex); + } finally { + try { + os.flush(); + } catch (IOException ex) { + Logger.getLogger(Index.class.getName()).log(Level.SEVERE, null, ex); + } + try { + os.close(); + } catch (IOException ex) { + Logger.getLogger(Index.class.getName()).log(Level.SEVERE, null, ex); } } } @@ -138,6 +191,43 @@ public class Index { * @return whether or not the CPE Index needs to be updated. */ public boolean updateNeeded() { - return true; + boolean needed = false; + String lastUpdated = null; + String dir = Settings.getString(Settings.KEYS.CPE_INDEX); + File f = new File(dir); + if (!f.exists()) { + needed = true; + } else { + File cpeProp = new File(dir + File.separatorChar + UPDATE_PROPERTIES_FILE); + if (!cpeProp.exists()) { + needed = true; + } else { + Properties prop = new Properties(); + FileInputStream is = null; + try { + is = new FileInputStream(cpeProp); + prop.load(is); + lastUpdated = prop.getProperty(this.LAST_UPDATED); + } catch (FileNotFoundException ex) { + Logger.getLogger(Index.class.getName()).log(Level.SEVERE, null, ex); + } catch (IOException ex) { + Logger.getLogger(Index.class.getName()).log(Level.SEVERE, null, ex); + } + try { + long lastupdate = Long.parseLong(lastUpdated); + DateTime last = new DateTime(lastupdate); + DateTime now = new DateTime(); + Days d = Days.daysBetween(last, now); + int days = d.getDays(); + int freq = Settings.getInt(Settings.KEYS.CPE_DOWNLOAD_FREQUENCY); + if (days >= freq) { + needed = true; + } + } catch (NumberFormatException ex) { + needed = true; + } + } + } + return needed; } } diff --git a/src/main/java/org/codesecure/dependencycheck/data/cpe/xml/Importer.java b/src/main/java/org/codesecure/dependencycheck/data/cpe/xml/Importer.java index d6cc949a3..3cf88f915 100644 --- a/src/main/java/org/codesecure/dependencycheck/data/cpe/xml/Importer.java +++ b/src/main/java/org/codesecure/dependencycheck/data/cpe/xml/Importer.java @@ -39,6 +39,25 @@ public class Importer { private Importer() { } + + /** + * Imports the CPE XML File into the Lucene Index. + * + * @param file containing the path to the CPE XML file. + * @throws ParserConfigurationException is thrown if the parser is misconfigured. + * @throws SAXException is thrown when there is a SAXException. + * @throws IOException is thrown when there is an IOException. + */ + public static void importXML(File file) throws ParserConfigurationException, SAXException, IOException { + SAXParserFactory factory = SAXParserFactory.newInstance(); + SAXParser saxParser = factory.newSAXParser(); + CPEHandler handler = new CPEHandler(); + Indexer indexer = new Indexer(); + indexer.open(); + handler.registerSaveDelegate(indexer); + saxParser.parse(file, handler); + indexer.close(); + } /** * Imports the CPE XML File into the Lucene Index. * @@ -48,14 +67,7 @@ public class Importer { * @throws IOException is thrown when there is an IOException. */ public static void importXML(String path) throws ParserConfigurationException, SAXException, IOException { - SAXParserFactory factory = SAXParserFactory.newInstance(); - SAXParser saxParser = factory.newSAXParser(); - CPEHandler handler = new CPEHandler(); - Indexer indexer = new Indexer(); - indexer.open(); - handler.registerSaveDelegate(indexer); File f = new File(path); - saxParser.parse(f, handler); - indexer.close(); + Importer.importXML(f); } } diff --git a/src/main/java/org/codesecure/dependencycheck/reporting/ReportGenerator.java b/src/main/java/org/codesecure/dependencycheck/reporting/ReportGenerator.java index 09709ce18..3e48524f7 100644 --- a/src/main/java/org/codesecure/dependencycheck/reporting/ReportGenerator.java +++ b/src/main/java/org/codesecure/dependencycheck/reporting/ReportGenerator.java @@ -27,7 +27,6 @@ import java.io.InputStreamReader; import java.util.HashMap; import java.util.List; import java.util.Map; -import org.apache.velocity.VelocityContext; import org.apache.velocity.app.VelocityEngine; import org.apache.velocity.context.Context; import org.apache.velocity.runtime.RuntimeConstants; @@ -42,20 +41,28 @@ import org.codesecure.dependencycheck.scanner.Dependency; */ public class ReportGenerator { - + /** + * Generates the Dependency Reports for the identified dependencies. + * + * @param outputDir the path where the reports should be written. + * @param applicationName the name of the application that was scanned. + * @param dependencies a list of dependencies to include in the report. + * @throws IOException is thrown when the template file does not exist. + * @throws Exception is thrown if there is an error writting out the reports. + */ public void generateReports(String outputDir, String applicationName, List dependencies) throws IOException, Exception { - + Map properties = new HashMap(); - properties.put("dependencies",dependencies); + properties.put("dependencies", dependencies); properties.put("applicationName", applicationName); - + String reportName = applicationName.replaceAll("[^a-zA-Z0-9-_ \\.]+", ""); String filename = outputDir + File.separatorChar + reportName; - generateReport("HtmlReport",filename+".html",properties); - //generateReport("XmlReport",filename+".xml",properties); - + generateReport("HtmlReport", filename + ".html", properties); + //generateReport("XmlReport",filename + ".xml",properties); + } - + /** * much of this code is from http://stackoverflow.com/questions/2931516/loading-velocity-template-inside-a-jar-file * @param templateName the name of the template to load. @@ -64,23 +71,23 @@ public class ReportGenerator { * @throws IOException is thrown when the template file does not exist. * @throws Exception is thrown when an exception occurs. */ - protected void generateReport(String templateName, String outFileName, + protected void generateReport(String templateName, String outFileName, Map properties) throws IOException, Exception { - + VelocityEngine ve = new VelocityEngine(); ve.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath"); ve.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName()); - ToolManager manager = new ToolManager(); + ToolManager manager = new ToolManager(); Context context = manager.createContext(); - EasyFactoryConfiguration config = new EasyFactoryConfiguration(); + EasyFactoryConfiguration config = new EasyFactoryConfiguration(); config.addDefaultTools(); config.toolbox("application") - .tool("esc","org.apache.velocity.tools.generic.EscapeTool") + .tool("esc", "org.apache.velocity.tools.generic.EscapeTool") .tool("org.apache.velocity.tools.generic.DateTool"); - + manager.configure(config); - + ve.init(); final String templatePath = "templates/" + templateName + ".vsl"; @@ -91,19 +98,19 @@ public class ReportGenerator { InputStreamReader reader = new InputStreamReader(input); BufferedWriter writer = null; - + //VelocityContext context = new VelocityContext(); - + //load the data into the context if (properties != null) { for (Map.Entry property : properties.entrySet()) { context.put(property.getKey(), property.getValue()); } - } - + } + try { writer = new BufferedWriter(new FileWriter(new File(outFileName))); - + if (!ve.evaluate(context, writer, templatePath, reader)) { throw new Exception("Failed to convert the template into html."); } @@ -112,12 +119,12 @@ public class ReportGenerator { try { writer.close(); } catch (Exception ex) { - + //ignore this error. } try { reader.close(); } catch (Exception ex) { - + //ignore this error. } } } diff --git a/src/main/java/org/codesecure/dependencycheck/reporting/package-info.java b/src/main/java/org/codesecure/dependencycheck/reporting/package-info.java new file mode 100644 index 000000000..5b539b596 --- /dev/null +++ b/src/main/java/org/codesecure/dependencycheck/reporting/package-info.java @@ -0,0 +1,12 @@ +/** + * + * + * org.codesecure.dependencycheck.reporting + * + * + * Contains classes used to generate reports. + * + * +*/ + +package org.codesecure.dependencycheck.reporting; diff --git a/src/main/java/org/codesecure/dependencycheck/scanner/Dependency.java b/src/main/java/org/codesecure/dependencycheck/scanner/Dependency.java index f8cdd3df2..0045a6ec5 100644 --- a/src/main/java/org/codesecure/dependencycheck/scanner/Dependency.java +++ b/src/main/java/org/codesecure/dependencycheck/scanner/Dependency.java @@ -65,13 +65,16 @@ public class Dependency { */ protected EvidenceCollection versionEvidence = null; + /** + * Constructs a new Dependency object. + */ public Dependency() { vendorEvidence = new EvidenceCollection(); titleEvidence = new EvidenceCollection(); versionEvidence = new EvidenceCollection(); cpes = new ArrayList(); } - + /** * Returns the file name of the JAR. * @@ -180,8 +183,8 @@ public class Dependency { public EvidenceCollection getEvidence() { return EvidenceCollection.mergeUsed(this.titleEvidence, this.vendorEvidence, this.versionEvidence); } - - + + /** * Returns the evidence used to identify this dependency. * diff --git a/src/main/java/org/codesecure/dependencycheck/scanner/EvidenceCollection.java b/src/main/java/org/codesecure/dependencycheck/scanner/EvidenceCollection.java index 13e8ad5e9..6377cdd0a 100644 --- a/src/main/java/org/codesecure/dependencycheck/scanner/EvidenceCollection.java +++ b/src/main/java/org/codesecure/dependencycheck/scanner/EvidenceCollection.java @@ -234,5 +234,5 @@ public class EvidenceCollection implements Iterable { } return sb.toString(); } - + } diff --git a/src/main/java/org/codesecure/dependencycheck/scanner/JarAnalyzer.java b/src/main/java/org/codesecure/dependencycheck/scanner/JarAnalyzer.java index e484aa740..10b4d20eb 100644 --- a/src/main/java/org/codesecure/dependencycheck/scanner/JarAnalyzer.java +++ b/src/main/java/org/codesecure/dependencycheck/scanner/JarAnalyzer.java @@ -51,22 +51,23 @@ public class JarAnalyzer implements Analyzer { private static final String BUNDLE_NAME = "Bundle-Name"; //: Struts 2 Core private static final String BUNDLE_VENDOR = "Bundle-Vendor"; //: Apache Software Foundation - private enum STRING_STATE { + ALPHA, NUMBER, OTHER } + private STRING_STATE determineState(char c) { - if (c>='0' && c<='9' || c=='.') { + if (c >= '0' && c <= '9' || c == '.') { return STRING_STATE.NUMBER; - } else if (c>='a' && c<='z') { + } else if (c >= 'a' && c <= 'z') { return STRING_STATE.ALPHA; } else { return STRING_STATE.OTHER; } } - + /** * Loads a specified JAR file and collects information from the manifest and * checksums to identify the correct CPE information. @@ -82,19 +83,17 @@ public class JarAnalyzer implements Analyzer { String fileName = file.getName(); dependency.setFileName(fileName); dependency.setFilePath(file.getCanonicalPath()); - String fileNameEvidence = fileName.substring(0,fileName.length()-4) - .toLowerCase() - .replace('-', ' ') - .replace('_', ' '); + String fileNameEvidence = fileName.substring(0, fileName.length() - 4) + .toLowerCase().replace('-', ' ').replace('_', ' '); StringBuilder sb = new StringBuilder(fileNameEvidence.length()); STRING_STATE state = determineState(fileNameEvidence.charAt(0)); - - for(int i=0;iImplementation-Version: ${pom.version} */ public void printVersionInfo() { - String version = "DependencyCheck version unknown"; - - URLClassLoader cl = (URLClassLoader) this.getClass().getClassLoader(); - InputStream is = null; - - try { - URL url = cl.findResource("META-INF/MANIFEST.MF"); - is = url.openStream(); - Manifest manifest = new Manifest(is); - Attributes atts = manifest.getMainAttributes(); - version = atts.getValue(Attributes.Name.IMPLEMENTATION_TITLE) - + " version " - + atts.getValue(Attributes.Name.IMPLEMENTATION_VERSION); - } catch (IOException ex) { - Logger.getLogger(CliParser.class.getName()).log(Level.WARNING, null, ex); - } finally { - try { - is.close(); - is = null; - } catch (Throwable ex) { - Logger.getLogger(CliParser.class.getName()).log(Level.FINEST, null, ex); - } - } + String version = String.format("%s version %s", + Settings.getString("application.name", "DependencyCheck"), + Settings.getString("application.version", "Unknown")); System.out.println(version); } + /** + * Checks if the auto update feature has been disabled. If it has been disabled + * via the command line this will return false. + * + * @return if auto-update is allowed. + */ + public boolean isAutoUpdate() { + return (line != null) ? !line.hasOption(ArgumentName.DISABLE_AUTO_UPDATE) : false; + } + /** * A collection of static final strings that represent the possible command * line arguments. */ public static class ArgumentName { - + /** + * The long CLI argument name specifing the directory/file to scan + */ public static final String SCAN = "scan"; - public static final String CPE = "cpe"; - public static final String OUT = "out"; - public static final String APPNAME = "app"; - public static final String VERSION = "version"; - public static final String HELP = "help"; + /** + * The short CLI argument name specifing the directory/file to scan + */ public static final String SCAN_SHORT = "s"; + /** + * The long CLI argument name specifing the path to the CPE.XML file to import + */ + public static final String CPE = "cpe"; + /** + * The short CLI argument name specifing the path to the CPE.XML file to import + */ public static final String CPE_SHORT = "c"; + /** + * The long CLI argument name specifing that the CPE/CVE/etc. data should not be automatically updated. + */ + public static final String DISABLE_AUTO_UPDATE = "noupdate"; + /** + * The short CLI argument name specifing that the CPE/CVE/etc. data should not be automatically updated. + */ + public static final String DISABLE_AUTO_UPDATE_SHORT = "n"; + /** + * The long CLI argument name specifing the directory to write the reports to. + */ + public static final String OUT = "out"; + /** + * The short CLI argument name specifing the directory to write the reports to. + */ public static final String OUT_SHORT = "o"; - public static final String VERSION_SHORT = "v"; - public static final String HELP_SHORT = "h"; + /** + * The long CLI argument name specifing the name of the application to be scanned. + */ + public static final String APPNAME = "app"; + /** + * The short CLI argument name specifing the name of the application to be scanned. + */ public static final String APPNAME_SHORT = "a"; + /** + * The long CLI argument name asking for help. + */ + public static final String HELP = "help"; + /** + * The short CLI argument name asking for help. + */ + public static final String HELP_SHORT = "h"; + /** + * The long CLI argument name asking for the version. + */ + public static final String VERSION_SHORT = "v"; + /** + * The short CLI argument name asking for the version. + */ + public static final String VERSION = "version"; + } } diff --git a/src/main/java/org/codesecure/dependencycheck/utils/Settings.java b/src/main/java/org/codesecure/dependencycheck/utils/Settings.java index 1d828232f..992472ee5 100644 --- a/src/main/java/org/codesecure/dependencycheck/utils/Settings.java +++ b/src/main/java/org/codesecure/dependencycheck/utils/Settings.java @@ -34,6 +34,7 @@ import java.util.logging.Logger; */ public class Settings { + /** * The collection of keys used within the properties file. */ @@ -42,19 +43,23 @@ public class Settings { /** * The properties key for the path where the CPE Lucene Index will be stored. */ - public static final String CPE_INDEX = "index.cpe"; + public static final String CPE_INDEX = "cpe"; /** * The properties key for the URL to the CPE. */ - public static final String CPE_URL = "index.cpe.url"; + public static final String CPE_URL = "cpe.url"; + /** + * The properties key for the URL to the CPE. + */ + public static final String CPE_DOWNLOAD_FREQUENCY = "cpe.downloadfrequency"; /** * The properties key for the path where the CCE Lucene Index will be stored. */ - public static final String CVE_INDEX = "index.cve"; + public static final String CVE_INDEX = "cve"; /** * The properties key for the path where the OSVDB Lucene Index will be stored. */ - public static final String OSVDB_INDEX = "index.osvdb"; + public static final String OSVDB_INDEX = "osvdb"; /** * The properties key prefix for the analyzer assocations. */ @@ -77,6 +82,24 @@ public class Settings { } } + /** + * Returns a value from the properties file. If the value was specified as a + * system property or passed in via the -Dprop=value argument - this method + * will return the value from the system properties before the values in + * the contained configuration file. + * + * @param key the key to lookup within the properties file. + * @param defaultValue the default value for the requested property. + * @return the property from the properties file. + */ + public static String getString(String key, String defaultValue) { + String str = System.getProperty(key, instance.props.getProperty(key)); + if (str==null) { + str = defaultValue; + } + return str; + } + /** * Returns a value from the properties file. If the value was specified as a * system property or passed in via the -Dprop=value argument - this method @@ -127,13 +150,28 @@ public class Settings { } return ret; } -// public static boolean getBoolean(String key) { -// return Boolean.parseBoolean(instance.props.getProperty(key)); -// } -// public static long getLong(String key) { -// return Long.parseLong(instance.props.getProperty(key)); -// } -// public static int getInt(String key) { -// return Integer.parseInt(instance.props.getProperty(key)); -// } + /** + * Returns a integer value from the properties file. If the value was specified as a + * system property or passed in via the -Dprop=value argument - this method + * will return the value from the system properties before the values in + * the contained configuration file. + * + * @param key the key to lookup within the properties file. + * @return the property from the properties file. + */ + public static int getInt(String key) { + return Integer.parseInt(Settings.getString(key)); + } + /** + * Returns a boolean value from the properties file. If the value was specified as a + * system property or passed in via the -Dprop=value argument - this method + * will return the value from the system properties before the values in + * the contained configuration file. + * + * @param key the key to lookup within the properties file. + * @return the property from the properties file. + */ + public static boolean getBoolean(String key) { + return Boolean.parseBoolean(Settings.getString(key)); + } } diff --git a/src/main/resources/dependencycheck.properties b/src/main/resources/dependencycheck.properties index c3bb9aca9..e989860af 100644 --- a/src/main/resources/dependencycheck.properties +++ b/src/main/resources/dependencycheck.properties @@ -1,9 +1,10 @@ -# To change this template, choose Tools | Templates -# and open the template in the editor. +application.name=${pom.name} +application.version=${pom.version} -index.cpe=store/cpe -index.cpe.url=http://static.nvd.nist.gov/feeds/xml/cpe/dictionary/official-cpe-dictionary_v2.2.xml -index.cve=store/cve -index.osvdb=store/osvdb +cpe=store/cpe +cpe.url=http://static.nvd.nist.gov/feeds/xml/cpe/dictionary/official-cpe-dictionary_v2.2.xml +cpe.downloadfrequency=1 +cve=store/cve +osvdb=store/osvdb file.extension.analyzer.association.jar=org.codesecure.dependencycheck.scanner.JarAnalyzer diff --git a/src/main/resources/templates/HtmlReport.vsl b/src/main/resources/templates/HtmlReport.vsl index 752c23485..106bb08e4 100644 --- a/src/main/resources/templates/HtmlReport.vsl +++ b/src/main/resources/templates/HtmlReport.vsl @@ -20,7 +20,6 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved. @version 1 *# - @@ -274,7 +273,9 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved. #set($cnt=0) #foreach($dependency in $dependencies)

$esc.html($dependency.FileName)

-
File Path: $esc.html($dependency.FilePath) +
File Path: $esc.html($dependency.FilePath)
+ MD5: $esc.html($dependency.Md5sum)
+ SHA1: $esc.html($dependency.Sha1sum) #set($cnt=$cnt+1)

Evidence

#end #if($dependency.getCPEs().size()>1) @@ -310,7 +310,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved. #end #if($dependency.getCPEs().size()==0) -

No CPE Identifies were found for this dependency.

+

No CPE Identifiers were found for this dependency.

#end
#end diff --git a/src/main/resources/templates/sample.html b/src/main/resources/templates/sample.html deleted file mode 100644 index 0a2359ddf..000000000 --- a/src/main/resources/templates/sample.html +++ /dev/null @@ -1,263 +0,0 @@ - - - - - - - - - - - -
-

Dependency Report

-

Project: ProjectName

-
Dependencies Scanned: 3
- Dependencies Identified:  -

Dependencies

-

Dependency Name

-
File Name: someFileName/path -

Evidence

- -

Possible CPEs

- -

Identified CPE: cpe://a:/blah3.blah

- -
-
-
- - diff --git a/src/test/java/org/codesecure/dependencycheck/data/BaseIndexTestCase.java b/src/test/java/org/codesecure/dependencycheck/data/BaseIndexTestCase.java index c7a7febed..69fc42eb1 100644 --- a/src/test/java/org/codesecure/dependencycheck/data/BaseIndexTestCase.java +++ b/src/test/java/org/codesecure/dependencycheck/data/BaseIndexTestCase.java @@ -31,7 +31,7 @@ public abstract class BaseIndexTestCase extends TestCase { } protected void ensureIndexExists() throws Exception { - String indexPath = Settings.getString("index.cpe"); + String indexPath = Settings.getString("cpe"); java.io.File f = new File(indexPath); if (!f.exists()) { f.mkdirs(); diff --git a/src/test/java/org/codesecure/dependencycheck/utils/CliParserTest.java b/src/test/java/org/codesecure/dependencycheck/utils/CliParserTest.java index 7c91431d2..d2c676765 100644 --- a/src/test/java/org/codesecure/dependencycheck/utils/CliParserTest.java +++ b/src/test/java/org/codesecure/dependencycheck/utils/CliParserTest.java @@ -336,9 +336,8 @@ public class CliParserTest extends TestCase { baos.flush(); String text = (new String(baos.toByteArray())); String[] lines = text.split(System.getProperty("line.separator")); - assertEquals("usage: DependencyCheck [-a ] [-c | -s ] [-h] [-o", lines[0]); - assertEquals(" ] [-v]", lines[1]); - assertEquals(8, lines.length); + assertTrue(lines[0].startsWith("usage: ")); + assertTrue((lines.length>2)); } catch (IOException ex) { System.setOut(out); fail("CliParser.printVersionInfo did not write anything to system.out."); diff --git a/src/test/java/org/codesecure/dependencycheck/utils/DownloaderTest.java b/src/test/java/org/codesecure/dependencycheck/utils/DownloaderTest.java index c02caa864..4ed3910f8 100644 --- a/src/test/java/org/codesecure/dependencycheck/utils/DownloaderTest.java +++ b/src/test/java/org/codesecure/dependencycheck/utils/DownloaderTest.java @@ -36,15 +36,17 @@ public class DownloaderTest { public void tearDown() { } - /** - * Test of fetchFile method, of class Downloader. - * @throws Exception thrown when an excpetion occurs. - */ - @Test - public void testFetchFile_URL_String() throws Exception { - System.out.println("fetchFile"); - URL url = new URL(Settings.getString(Settings.KEYS.CPE_URL)); - String outputPath = "target\\downloaded_cpe.xml"; - Downloader.fetchFile(url, outputPath); - } + +//This test is being removed because it is a bit too slow. +// /** +// * Test of fetchFile method, of class Downloader. +// * @throws Exception thrown when an excpetion occurs. +// */ +// @Test +// public void testFetchFile_URL_String() throws Exception { +// System.out.println("fetchFile"); +// URL url = new URL(Settings.getString(Settings.KEYS.CPE_URL)); +// String outputPath = "target\\downloaded_cpe.xml"; +// Downloader.fetchFile(url, outputPath); +// } }