From aadb29c668ea0e608ebfb7851795e65e405a1e9c Mon Sep 17 00:00:00 2001 From: Jeremy Long Date: Sun, 16 Sep 2012 10:15:42 -0400 Subject: [PATCH] general updates --- pom.xml | 59 ++++++----- .../dependencycheck/data/LuceneUtils.java | 2 +- .../dependencycheck/data/cpe/CPEQuery.java | 7 +- .../reporting/ReportGenerator.java | 10 +- .../dependencycheck/utils/CliParser.java | 63 +++++++++--- .../dependencycheck/utils/Settings.java | 67 ++++++++++--- .../META-INF/dependencycheck.properties | 2 - .../dependencycheck/data/LuceneUtilsTest.java | 24 ++++- .../data/cpe/CPEQueryTest.java | 2 +- .../{ => data/cpe}/xml/CPEHandlerTest.java | 2 +- .../dependencycheck/utils/CliParserTest.java | 5 + .../dependencycheck/utils/SettingsTest.java | 97 +++++++++++++++++++ .../dependencycheck/xml/CPEEntryTest.java | 47 --------- src/test/resources/test.properties | 1 + 14 files changed, 276 insertions(+), 112 deletions(-) rename src/test/java/org/codesecure/dependencycheck/{ => data/cpe}/xml/CPEHandlerTest.java (94%) delete mode 100644 src/test/java/org/codesecure/dependencycheck/xml/CPEEntryTest.java create mode 100644 src/test/resources/test.properties diff --git a/pom.xml b/pom.xml index 74a4c9202..c700fc5be 100644 --- a/pom.xml +++ b/pom.xml @@ -29,6 +29,7 @@ along with DependencyCheck. If not, see . DependencyCheck https://github.com/jeremylong/DependencyCheck.git DependencyCheck is a utility that attempts to detect publically disclosed vulnerabilities contained within project dependencies. It does this by determining if there is a Common Platform Enumeration (CPE) identifier for a given dependency. If found, it will generate a report linking to the associated CVE entries. + 2012 Jeremy Long @@ -49,6 +50,10 @@ along with DependencyCheck. If not, see . https://github.com/jeremylong/DependencyCheck.git scm:git:git@github.com:jeremylong/DependencyCheck.git + + github + https://github.com/jeremylong/DependencyCheck/issues + GNU General Public License version 3 @@ -200,10 +205,6 @@ along with DependencyCheck. If not, see . cve ${project.build.directory}/store/cve - - osvdb - ${project.build.directory}/store/osvdb - cpe ${project.build.directory}/store/cpe @@ -220,7 +221,36 @@ along with DependencyCheck. If not, see . org.apache.maven.plugins maven-project-info-reports-plugin - 2.2 + 2.5.1 + + + + + + index + summary + license + scm + issue-tracking + dependencies + plugin-management + project-team + + + + + + org.codehaus.mojo + versions-maven-plugin + 1.3.1 + + + + dependency-updates-report + plugin-updates-report + + + org.apache.maven.plugins @@ -328,25 +358,6 @@ along with DependencyCheck. If not, see . javadoc provided - - commons-lang - commons-lang - 2.6 - - - commons-lang - commons-lang - 2.6 - javadoc - provided - - - commons-lang - commons-lang - 2.6 - sources - provided - org.apache.commons commons-io diff --git a/src/main/java/org/codesecure/dependencycheck/data/LuceneUtils.java b/src/main/java/org/codesecure/dependencycheck/data/LuceneUtils.java index 25a6a8c7b..93eed5aab 100644 --- a/src/main/java/org/codesecure/dependencycheck/data/LuceneUtils.java +++ b/src/main/java/org/codesecure/dependencycheck/data/LuceneUtils.java @@ -67,7 +67,7 @@ public final class LuceneUtils { case '*': case '?': case ':': - case '\\': + case '\\': //it is supposed to fall through here buf.append('\\'); default: buf.append(c); 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 28a5aa544..4acc36e56 100644 --- a/src/main/java/org/codesecure/dependencycheck/data/cpe/CPEQuery.java +++ b/src/main/java/org/codesecure/dependencycheck/data/cpe/CPEQuery.java @@ -381,7 +381,12 @@ public class CPEQuery { sb.append("^0.2 "); } } else { - LuceneUtils.appendEscapedLuceneQuery(sb, version); + //LuceneUtils.appendEscapedLuceneQuery(sb, version); + //if we have a weighting on something else, reduce the weighting on the version a lot + for (String v : version.split(" ")) { + LuceneUtils.appendEscapedLuceneQuery(sb, v); + sb.append("^0.7 "); + } } sb.append(")"); diff --git a/src/main/java/org/codesecure/dependencycheck/reporting/ReportGenerator.java b/src/main/java/org/codesecure/dependencycheck/reporting/ReportGenerator.java index 3e48524f7..19bb138de 100644 --- a/src/main/java/org/codesecure/dependencycheck/reporting/ReportGenerator.java +++ b/src/main/java/org/codesecure/dependencycheck/reporting/ReportGenerator.java @@ -27,6 +27,8 @@ import java.io.InputStreamReader; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; import org.apache.velocity.app.VelocityEngine; import org.apache.velocity.context.Context; import org.apache.velocity.runtime.RuntimeConstants; @@ -82,9 +84,7 @@ public class ReportGenerator { Context context = manager.createContext(); EasyFactoryConfiguration config = new EasyFactoryConfiguration(); config.addDefaultTools(); - config.toolbox("application") - .tool("esc", "org.apache.velocity.tools.generic.EscapeTool") - .tool("org.apache.velocity.tools.generic.DateTool"); + config.toolbox("application").tool("esc", "org.apache.velocity.tools.generic.EscapeTool").tool("org.apache.velocity.tools.generic.DateTool"); manager.configure(config); @@ -119,12 +119,12 @@ public class ReportGenerator { try { writer.close(); } catch (Exception ex) { - //ignore this error. + Logger.getLogger(ReportGenerator.class.getName()).log(Level.FINEST, null, ex); } try { reader.close(); } catch (Exception ex) { - //ignore this error. + Logger.getLogger(ReportGenerator.class.getName()).log(Level.FINEST, null, ex); } } } diff --git a/src/main/java/org/codesecure/dependencycheck/utils/CliParser.java b/src/main/java/org/codesecure/dependencycheck/utils/CliParser.java index 55300e2c4..776d1c3e4 100644 --- a/src/main/java/org/codesecure/dependencycheck/utils/CliParser.java +++ b/src/main/java/org/codesecure/dependencycheck/utils/CliParser.java @@ -145,26 +145,26 @@ public final class CliParser { @SuppressWarnings("static-access") private Options createCommandLineOptions() { Option help = new Option(ArgumentName.HELP_SHORT, ArgumentName.HELP, false, - "print this message"); + "print this message."); + + Option advancedHelp = new Option(ArgumentName.ADVANCED_HELP_SHORT, ArgumentName.ADVANCED_HELP, false, + "shows additional help regarding properties file."); Option version = new Option(ArgumentName.VERSION_SHORT, ArgumentName.VERSION, - false, "print the version information and exit"); + false, "print the version information."); Option noupdate = new Option(ArgumentName.DISABLE_AUTO_UPDATE_SHORT, ArgumentName.DISABLE_AUTO_UPDATE, false, "disables the automatic updating of the CPE data."); - Option appname = OptionBuilder.withArgName("name").hasArg().withLongOpt(ArgumentName.APPNAME) - .withDescription("the name of the application being scanned").create(ArgumentName.APPNAME_SHORT); + Option appname = OptionBuilder.withArgName("name").hasArg().withLongOpt(ArgumentName.APPNAME).withDescription("the name of the application being scanned.").create(ArgumentName.APPNAME_SHORT); - Option path = OptionBuilder.withArgName("path").hasArg().withLongOpt(ArgumentName.SCAN) - .withDescription("the path to scan - this option can be specified multiple times.") - .create(ArgumentName.SCAN_SHORT); + Option path = OptionBuilder.withArgName("path").hasArg().withLongOpt(ArgumentName.SCAN).withDescription("the path to scan - this option can be specified multiple times.").create(ArgumentName.SCAN_SHORT); - Option load = OptionBuilder.withArgName("file").hasArg().withLongOpt(ArgumentName.CPE) - .withDescription("load the CPE xml file").create(ArgumentName.CPE_SHORT); + Option load = OptionBuilder.withArgName("file").hasArg().withLongOpt(ArgumentName.CPE).withDescription("load the CPE xml file.").create(ArgumentName.CPE_SHORT); - Option out = OptionBuilder.withArgName("folder").hasArg().withLongOpt(ArgumentName.OUT) - .withDescription("the folder to write reports to.").create(ArgumentName.OUT_SHORT); + Option props = OptionBuilder.withArgName("file").hasArg().withLongOpt(ArgumentName.PROP).withDescription("a property file to load.").create(ArgumentName.PROP_SHORT); + + Option out = OptionBuilder.withArgName("folder").hasArg().withLongOpt(ArgumentName.OUT).withDescription("the folder to write reports to.").create(ArgumentName.OUT_SHORT); //TODO add the ability to load a properties file to override the defaults... @@ -179,7 +179,8 @@ public final class CliParser { opts.addOption(version); opts.addOption(help); opts.addOption(noupdate); - + opts.addOption(props); + opts.addOption(advancedHelp); return opts; } @@ -224,12 +225,28 @@ public final class CliParser { */ public void printHelp() { HelpFormatter formatter = new HelpFormatter(); + String nl = System.getProperty("line.separator"); + String advancedHelp = null; + if (line.hasOption(ArgumentName.ADVANCED_HELP)) { + advancedHelp = nl + nl + + "Additionally, the following properties are supported and can be specified either" + + "using the -p argument or by passing them in as system properties." + nl + + nl + " " + Settings.KEYS.PROXY_URL + "\t\t the proxy URL to use when downloading resources." + + nl + " " + Settings.KEYS.PROXY_PORT + "\t\t the proxy port to use when downloading resources." + + nl + " " + Settings.KEYS.CONNECTION_TIMEOUT + "\t the cconnection timeout (in milliseconds) to use" + nl + "\t\t\t when downloading resources."; + } + formatter.printHelp(Settings.getString("application.name", "DependencyCheck"), - "\n" + Settings.getString("application.name", "DependencyCheck") + nl + Settings.getString("application.name", "DependencyCheck") + " can be used to identify if there are any known CVE vulnerabilities in libraries utillized by an application. " + Settings.getString("application.name", "DependencyCheck") - + " will automatically update required data from the Internet, such as the CVE and CPE data files from nvd.nist.gov.\n", - options, "", true); + + " will automatically update required data from the Internet, such as the CVE and CPE data files from nvd.nist.gov." + nl + nl, + options, + "", + true); + if (advancedHelp != null) { + System.out.println(advancedHelp); + } } /** @@ -351,5 +368,21 @@ public final class CliParser { * The short CLI argument name asking for the version. */ public static final String VERSION = "version"; + /** + * The CLI argument name asking for advanced help. + */ + public static final String ADVANCED_HELP_SHORT = "ah"; + /** + * The short CLI argument name asking for advanced help. + */ + public static final String ADVANCED_HELP = "advancedhelp"; + /** + * The short CLI argument name for setting the location of an additional properties file. + */ + public static final String PROP_SHORT = "p"; + /** + * The CLI argument name for setting the location of an additional properties file. + */ + public static final String PROP = "propertyfile"; } } diff --git a/src/main/java/org/codesecure/dependencycheck/utils/Settings.java b/src/main/java/org/codesecure/dependencycheck/utils/Settings.java index c6b3985c2..2c706fb06 100644 --- a/src/main/java/org/codesecure/dependencycheck/utils/Settings.java +++ b/src/main/java/org/codesecure/dependencycheck/utils/Settings.java @@ -18,6 +18,8 @@ package org.codesecure.dependencycheck.utils; * Copyright (c) 2012 Jeremy Long. All Rights Reserved. */ +import java.io.FileInputStream; +import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.util.Properties; @@ -52,10 +54,6 @@ public class Settings { * The properties key for the path where the CCE Lucene Index will be stored. */ 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 = "osvdb"; /** * The properties key for the proxy url. */ @@ -86,6 +84,44 @@ public class Settings { } } + + /** + * Sets a property value. + * @param key the key for the property. + * @param value the value for the property. + */ + public static void setString(String key, String value) { + INSTANCE.props.setProperty(key, value); + } + + /** + * Merges a new properties file into the current properties. This + * method allows for the loading of a user provided properties file.

+ * Note: even if using this method - system properties will be loaded before + * properties loaded from files. + * + * @param filePath the path to the properties file to merge. + * @throws FileNotFoundException is thrown when the filePath points to a non-existent file. + * @throws IOException is thrown when there is an exception loading/merging the properties. + */ + public static void mergeProperties(String filePath) throws FileNotFoundException, IOException { + FileInputStream fis = new FileInputStream(filePath); + mergeProperties(fis); + } + + /** + * Merges a new properties file into the current properties. This + * method allows for the loading of a user provided properties file.

+ * Note: even if using this method - system properties will be loaded before + * properties loaded from files. + * + * @param stream an Input Stream pointing at a properties file to merge. + * @throws IOException is thrown when there is an exception loading/merging the properties + */ + public static void mergeProperties(InputStream stream) throws IOException { + INSTANCE.props.load(stream); + } + /** * 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 @@ -104,15 +140,6 @@ public class Settings { return str; } - /** - * Sets a property value. - * @param key the key for the property. - * @param value the value for the property. - */ - public static void setString(String key, String value) { - INSTANCE.props.setProperty(key, value); - } - /** * 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,7 +154,7 @@ public class Settings { } /** - * Returns a integer value from the properties file. If the value was specified as a + * Returns an int 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. @@ -138,6 +165,18 @@ public class Settings { public static int getInt(String key) { return Integer.parseInt(Settings.getString(key)); } + /** + * Returns a long 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 long getLong(String key) { + return Long.parseLong(Settings.getString(key)); + } /** * Returns a boolean value from the properties file. If the value was specified as a diff --git a/src/main/resources/META-INF/dependencycheck.properties b/src/main/resources/META-INF/dependencycheck.properties index c77202aa4..2076f7d95 100644 --- a/src/main/resources/META-INF/dependencycheck.properties +++ b/src/main/resources/META-INF/dependencycheck.properties @@ -5,5 +5,3 @@ cpe=store/cpe cpe.url=http://static.nvd.nist.gov/feeds/xml/cpe/dictionary/official-cpe-dictionary_v2.2.xml.gz cpe.meta.url=http://static.nvd.nist.gov/feeds/xml/cpe/dictionary/official-cpe-dictionary_v2.2.meta cve=store/cve -osvdb=store/osvdb - diff --git a/src/test/java/org/codesecure/dependencycheck/data/LuceneUtilsTest.java b/src/test/java/org/codesecure/dependencycheck/data/LuceneUtilsTest.java index f8e4bc3af..ea32fa145 100644 --- a/src/test/java/org/codesecure/dependencycheck/data/LuceneUtilsTest.java +++ b/src/test/java/org/codesecure/dependencycheck/data/LuceneUtilsTest.java @@ -48,7 +48,17 @@ public class LuceneUtilsTest { LuceneUtils.appendEscapedLuceneQuery(buf, text); assertEquals(expResult, buf.toString()); } - +/** + * Test of appendEscapedLuceneQuery method, of class LuceneUtils. + */ + @Test + public void testAppendEscapedLuceneQuery_null() { + System.out.println("appendEscapedLuceneQuery"); + StringBuilder buf = new StringBuilder(); + CharSequence text = null; + LuceneUtils.appendEscapedLuceneQuery(buf, text); + assertEquals(0, buf.length()); + } /** * Test of escapeLuceneQuery method, of class LuceneUtils. */ @@ -60,4 +70,16 @@ public class LuceneUtilsTest { String result = LuceneUtils.escapeLuceneQuery(text); assertEquals(expResult, result); } + + /** + * Test of escapeLuceneQuery method, of class LuceneUtils. + */ + @Test + public void testEscapeLuceneQuery_null() { + System.out.println("escapeLuceneQuery"); + CharSequence text = null; + String expResult = null; + String result = LuceneUtils.escapeLuceneQuery(text); + assertEquals(expResult, result); + } } diff --git a/src/test/java/org/codesecure/dependencycheck/data/cpe/CPEQueryTest.java b/src/test/java/org/codesecure/dependencycheck/data/cpe/CPEQueryTest.java index 620976e46..45bea555c 100644 --- a/src/test/java/org/codesecure/dependencycheck/data/cpe/CPEQueryTest.java +++ b/src/test/java/org/codesecure/dependencycheck/data/cpe/CPEQueryTest.java @@ -95,7 +95,7 @@ public class CPEQueryTest extends BaseIndexTestCase { CPEQuery instance = new CPEQuery(); String queryText = instance.buildSearch(vendor, product, version, null, null); - String expResult = " product:( struts 2 core ) vendor:( apache software foundation ) version:(2.1.2)"; + String expResult = " product:( struts 2 core ) vendor:( apache software foundation ) version:(2.1.2^0.7 )"; assertTrue(expResult.equals(queryText)); queryText = instance.buildSearch(vendor, product, version, null, productWeightings); diff --git a/src/test/java/org/codesecure/dependencycheck/xml/CPEHandlerTest.java b/src/test/java/org/codesecure/dependencycheck/data/cpe/xml/CPEHandlerTest.java similarity index 94% rename from src/test/java/org/codesecure/dependencycheck/xml/CPEHandlerTest.java rename to src/test/java/org/codesecure/dependencycheck/data/cpe/xml/CPEHandlerTest.java index e781dcd6b..a35758832 100644 --- a/src/test/java/org/codesecure/dependencycheck/xml/CPEHandlerTest.java +++ b/src/test/java/org/codesecure/dependencycheck/data/cpe/xml/CPEHandlerTest.java @@ -2,7 +2,7 @@ * To change this template, choose Tools | Templates * and open the template in the editor. */ -package org.codesecure.dependencycheck.cpe.xml; +package org.codesecure.dependencycheck.data.cpe.xml; import java.io.File; import junit.framework.TestCase; diff --git a/src/test/java/org/codesecure/dependencycheck/utils/CliParserTest.java b/src/test/java/org/codesecure/dependencycheck/utils/CliParserTest.java index d2c676765..3fe0d6efb 100644 --- a/src/test/java/org/codesecure/dependencycheck/utils/CliParserTest.java +++ b/src/test/java/org/codesecure/dependencycheck/utils/CliParserTest.java @@ -331,6 +331,11 @@ public class CliParserTest extends TestCase { System.setOut(new PrintStream(baos)); CliParser instance = new CliParser(); + String[] args = {"-h"}; + instance.parse(args); + instance.printHelp(); + args[0] = "-ah"; + instance.parse(args); instance.printHelp(); try { baos.flush(); diff --git a/src/test/java/org/codesecure/dependencycheck/utils/SettingsTest.java b/src/test/java/org/codesecure/dependencycheck/utils/SettingsTest.java index ba226a6be..4be2b244a 100644 --- a/src/test/java/org/codesecure/dependencycheck/utils/SettingsTest.java +++ b/src/test/java/org/codesecure/dependencycheck/utils/SettingsTest.java @@ -4,6 +4,10 @@ */ package org.codesecure.dependencycheck.utils; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.URISyntaxException; import junit.framework.TestCase; import org.junit.Test; @@ -38,4 +42,97 @@ public class SettingsTest extends TestCase { String result = Settings.getString(key); assertTrue(result.endsWith(expResult)); } + + /** + * Test of mergeProperties method, of class Settings. + */ + @Test + public void testMergeProperties_String() throws IOException, URISyntaxException { + System.out.println("getString"); + String key = Settings.KEYS.PROXY_PORT; + String expResult = Settings.getString(key); + File f = new File(this.getClass().getClassLoader().getResource("test.properties").toURI()); + //InputStream in = this.getClass().getClassLoader().getResourceAsStream("test.properties"); + Settings.mergeProperties(f.getAbsolutePath()); + String result = Settings.getString(key); + assertTrue("setting didn't change?", (expResult == null && result != null) || !expResult.equals(result)); + } + + /** + * Test of setString method, of class Settings. + */ + @Test + public void testSetString() { + System.out.println("setString"); + String key = "newProperty"; + String value = "someValue"; + Settings.setString(key, value); + String expResults = Settings.getString(key); + assertEquals(expResults, value); + } + + /** + * Test of getString method, of class Settings. + */ + @Test + public void testGetString_String_String() { + System.out.println("getString"); + String key = "key That Doesn't Exist"; + String defaultValue = "blue bunny"; + String expResult = "blue bunny"; + String result = Settings.getString(key); + assertTrue(result == null); + result = Settings.getString(key, defaultValue); + assertEquals(expResult, result); + } + + /** + * Test of getString method, of class Settings. + */ + @Test + public void testGetString_String() { + System.out.println("getString"); + String key = Settings.KEYS.CONNECTION_TIMEOUT; + String result = Settings.getString(key); + assertTrue(result == null); + } + + /** + * Test of getInt method, of class Settings. + */ + @Test + public void testGetInt() { + System.out.println("getInt"); + String key = "SomeNumber"; + int expResult = 85; + Settings.setString(key, "85"); + int result = Settings.getInt(key); + assertEquals(expResult, result); + } + + /** + * Test of getLong method, of class Settings. + */ + @Test + public void testGetLong() { + System.out.println("getLong"); + String key = "SomeNumber"; + long expResult = 300L; + Settings.setString(key, "300"); + long result = Settings.getLong(key); + assertEquals(expResult, result); + } + + /** + * Test of getBoolean method, of class Settings. + */ + @Test + public void testGetBoolean() { + System.out.println("getBoolean"); + String key = "SomeBoolean"; + Settings.setString(key, "false"); + boolean expResult = false; + boolean result = Settings.getBoolean(key); + assertEquals(expResult, result); + } } diff --git a/src/test/java/org/codesecure/dependencycheck/xml/CPEEntryTest.java b/src/test/java/org/codesecure/dependencycheck/xml/CPEEntryTest.java deleted file mode 100644 index 7c47f719b..000000000 --- a/src/test/java/org/codesecure/dependencycheck/xml/CPEEntryTest.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ -package org.codesecure.dependencycheck.cpe.xml; - -import org.codesecure.dependencycheck.data.cpe.Entry; -import junit.framework.TestCase; - -/** - * - * @author Jeremy Long - */ -public class CPEEntryTest extends TestCase { - - public CPEEntryTest(String testName) { - super(testName); - } - - @Override - protected void setUp() throws Exception { - super.setUp(); - } - - @Override - protected void tearDown() throws Exception { - super.tearDown(); - } - - /** - * Test of setName method, of class Entry. - */ - public void testSetName() throws Exception { - System.out.println("setName"); - String name = "cpe:/a:apache:struts:1.1:rc2"; - - Entry instance = new Entry(); - instance.setName(name); - - assertEquals(name,instance.getName()); - assertEquals("apache", instance.getVendor()); - assertEquals("struts", instance.getProduct()); - assertEquals("1.1", instance.getVersion()); - assertEquals("rc2", instance.getRevision()); - - } -} diff --git a/src/test/resources/test.properties b/src/test/resources/test.properties new file mode 100644 index 000000000..dec474f6f --- /dev/null +++ b/src/test/resources/test.properties @@ -0,0 +1 @@ +proxy.port=80 \ No newline at end of file