From 8813652f0d50b961f9242c6eb8b116cfaa12a7a1 Mon Sep 17 00:00:00 2001 From: Steve Springett Date: Wed, 22 May 2013 01:11:02 -0700 Subject: [PATCH 1/4] Forcing the class loading of the H2 JDBC driver. Former-commit-id: d6c11d56afc04d115bbf1d0962072c70cb205dd8 --- .../java/org/owasp/dependencycheck/data/nvdcve/CveDB.java | 3 ++- .../org/owasp/dependencycheck/data/nvdcve/NvdCveAnalyzer.java | 2 +- .../dependencycheck/data/nvdcve/xml/DatabaseUpdater.java | 4 +++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/owasp/dependencycheck/data/nvdcve/CveDB.java b/src/main/java/org/owasp/dependencycheck/data/nvdcve/CveDB.java index f9e60b659..c7c064da5 100644 --- a/src/main/java/org/owasp/dependencycheck/data/nvdcve/CveDB.java +++ b/src/main/java/org/owasp/dependencycheck/data/nvdcve/CveDB.java @@ -182,13 +182,14 @@ public class CveDB { * @throws SQLException thrown if there is a SQL Exception * @throws DatabaseException thrown if there is an error initializing a new database */ - public void open() throws IOException, SQLException, DatabaseException { + public void open() throws IOException, SQLException, DatabaseException, ClassNotFoundException { final String fileName = CveDB.getDataDirectory().getCanonicalPath() + File.separator + "cve"; final File f = new File(fileName); final boolean createTables = !f.exists(); final String connStr = "jdbc:h2:file:" + fileName; + Class.forName("org.h2.Driver"); conn = DriverManager.getConnection(connStr, "sa", ""); if (createTables) { createTables(); diff --git a/src/main/java/org/owasp/dependencycheck/data/nvdcve/NvdCveAnalyzer.java b/src/main/java/org/owasp/dependencycheck/data/nvdcve/NvdCveAnalyzer.java index 30cfb6180..964ed751e 100644 --- a/src/main/java/org/owasp/dependencycheck/data/nvdcve/NvdCveAnalyzer.java +++ b/src/main/java/org/owasp/dependencycheck/data/nvdcve/NvdCveAnalyzer.java @@ -54,7 +54,7 @@ public class NvdCveAnalyzer implements Analyzer { * @throws IOException thrown when there is an IO Exception * @throws DatabaseException thrown when there is a database exceptions */ - public void open() throws SQLException, IOException, DatabaseException { + public void open() throws SQLException, IOException, DatabaseException, ClassNotFoundException { cveDB = new CveDB(); cveDB.open(); } diff --git a/src/main/java/org/owasp/dependencycheck/data/nvdcve/xml/DatabaseUpdater.java b/src/main/java/org/owasp/dependencycheck/data/nvdcve/xml/DatabaseUpdater.java index bc5abcbf4..d74c0f614 100644 --- a/src/main/java/org/owasp/dependencycheck/data/nvdcve/xml/DatabaseUpdater.java +++ b/src/main/java/org/owasp/dependencycheck/data/nvdcve/xml/DatabaseUpdater.java @@ -137,6 +137,8 @@ public class DatabaseUpdater implements CachedWebDataSource { throw new UpdateException(ex); } catch (DatabaseException ex) { throw new UpdateException(ex); + } catch (ClassNotFoundException ex) { + throw new UpdateException(ex); } finally { try { if (outputPath != null && outputPath.exists()) { @@ -181,7 +183,7 @@ public class DatabaseUpdater implements CachedWebDataSource { * @throws DatabaseException is thrown if there is a database exception */ private void importXML(File file, File oldVersion) - throws ParserConfigurationException, SAXException, IOException, SQLException, DatabaseException { + throws ParserConfigurationException, SAXException, IOException, SQLException, DatabaseException, ClassNotFoundException { CveDB cveDB = null; Index cpeIndex = null; From adfc913a0edfe35925cf88f0f4a64ca88b016202 Mon Sep 17 00:00:00 2001 From: Steve Springett Date: Fri, 24 May 2013 16:00:10 -0700 Subject: [PATCH 2/4] Fixed Velocity logging issues in server environment. Former-commit-id: 429105274ee0c2e78c3398e3c019feaaa056866d --- .../reporting/ReportGenerator.java | 1 + .../reporting/VelocityLoggerRedirect.java | 93 +++++++++++++++++++ 2 files changed, 94 insertions(+) create mode 100644 src/main/java/org/owasp/dependencycheck/reporting/VelocityLoggerRedirect.java diff --git a/src/main/java/org/owasp/dependencycheck/reporting/ReportGenerator.java b/src/main/java/org/owasp/dependencycheck/reporting/ReportGenerator.java index 544a97eca..144437c56 100644 --- a/src/main/java/org/owasp/dependencycheck/reporting/ReportGenerator.java +++ b/src/main/java/org/owasp/dependencycheck/reporting/ReportGenerator.java @@ -100,6 +100,7 @@ public class ReportGenerator { */ private VelocityEngine createVelocityEngine() { final VelocityEngine ve = new VelocityEngine(); + ve.setProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM_CLASS, VelocityLoggerRedirect.class.getName()); ve.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath"); ve.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName()); return ve; diff --git a/src/main/java/org/owasp/dependencycheck/reporting/VelocityLoggerRedirect.java b/src/main/java/org/owasp/dependencycheck/reporting/VelocityLoggerRedirect.java new file mode 100644 index 000000000..9bd5bff14 --- /dev/null +++ b/src/main/java/org/owasp/dependencycheck/reporting/VelocityLoggerRedirect.java @@ -0,0 +1,93 @@ +/* + * This file is part of Dependency-Check. + * + * Dependency-Check 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. + * + * Dependency-Check 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 + * Dependency-Check. If not, see http://www.gnu.org/licenses/. + * + * Copyright (c) 2012 Jeremy Long. All Rights Reserved. + */ +package org.owasp.dependencycheck.reporting; + +import org.apache.velocity.app.Velocity; +import org.apache.velocity.runtime.RuntimeServices; +import org.apache.velocity.runtime.log.LogChute; + +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * DependencyCheck uses {@link java.util.logging.Logger} as a logging framework, + * and Apache Velocity uses a custom logging implementation that outputs to a + * file named velocity.log by default. This class is an implementation of a + * custom Velocity logger that redirects all velocity logging to the Java Logger + * class. + *

+ * This class was written to address permission issues when using DependencyCheck + * in a server environment (such as the Jenkins plugin). In some circumstances, + * Velocity would attempt to create velocity.log in an un-writable directory. + * + * @author Steve Springett (steve.springett@owasp.org) + */ +public class VelocityLoggerRedirect implements LogChute { + + /** + * This will be invoked once by the LogManager + */ + public void init(RuntimeServices rsvc) { + // do nothing + } + + /** + * Given a Velocity log level and message, this method will + * call the appropriate Logger level and log the specified values. + */ + public void log(int level, String message) { + Logger.getLogger(Velocity.class.getName()).log(getLevel(level), message); + } + + /** + * Given a Velocity log level, message and Throwable, this method will + * call the appropriate Logger level and log the specified values. + */ + public void log(int level, String message, Throwable t) { + Logger.getLogger(Velocity.class.getName()).log(getLevel(level), message, t); + } + + /** + * Will always return true. The property file will decide what level to log. + */ + public boolean isLevelEnabled(int level) { + return true; + } + + /** + * Maps Velocity log levels to {@link Logger} values. + */ + private Level getLevel(int velocityLevel) { + switch (velocityLevel) { + case TRACE_ID: + return Level.ALL; + case DEBUG_ID: + return Level.FINE; + case INFO_ID: + return Level.INFO; + case WARN_ID: + return Level.WARNING; + case ERROR_ID: + return Level.SEVERE; + default: + return Level.INFO; + } + } + +} From 9a7fbe44eb73f5ac9787a2280a904450685364d5 Mon Sep 17 00:00:00 2001 From: Steve Springett Date: Fri, 24 May 2013 23:53:24 -0700 Subject: [PATCH 3/4] Adding more control over data directory path Former-commit-id: 966544bd738646ba57be087f413f686ecdfcee9c --- .../owasp/dependencycheck/data/cpe/Index.java | 6 ++--- .../dependencycheck/data/nvdcve/CveDB.java | 6 ++--- .../dependencycheck/utils/FileUtils.java | 23 +++++++++++++++++++ .../data/cpe/BaseIndexTestCase.java | 7 ++---- .../data/nvdcve/BaseDBTestCase.java | 6 ++--- 5 files changed, 31 insertions(+), 17 deletions(-) diff --git a/src/main/java/org/owasp/dependencycheck/data/cpe/Index.java b/src/main/java/org/owasp/dependencycheck/data/cpe/Index.java index 1040cc68b..b3c3d9254 100644 --- a/src/main/java/org/owasp/dependencycheck/data/cpe/Index.java +++ b/src/main/java/org/owasp/dependencycheck/data/cpe/Index.java @@ -20,7 +20,6 @@ package org.owasp.dependencycheck.data.cpe; import java.io.File; import java.io.IOException; -import java.net.URLDecoder; import java.util.HashMap; import java.util.Map; import org.apache.lucene.analysis.Analyzer; @@ -37,6 +36,7 @@ import org.apache.lucene.store.Directory; import org.apache.lucene.store.FSDirectory; import org.apache.lucene.util.Version; import org.owasp.dependencycheck.data.lucene.AbstractIndex; +import org.owasp.dependencycheck.utils.FileUtils; import org.owasp.dependencycheck.utils.Settings; import org.owasp.dependencycheck.data.lucene.FieldAnalyzer; import org.owasp.dependencycheck.data.lucene.SearchFieldAnalyzer; @@ -70,9 +70,7 @@ public class Index extends AbstractIndex { */ public File getDataDirectory() throws IOException { final String fileName = Settings.getString(Settings.KEYS.CPE_INDEX); - final String filePath = Index.class.getProtectionDomain().getCodeSource().getLocation().getPath(); - final String decodedPath = URLDecoder.decode(filePath, "UTF-8"); - File exePath = new File(decodedPath); + File exePath = FileUtils.getDataDirectory(fileName, Index.class); if (exePath.getName().toLowerCase().endsWith(".jar")) { exePath = exePath.getParentFile(); } else { diff --git a/src/main/java/org/owasp/dependencycheck/data/nvdcve/CveDB.java b/src/main/java/org/owasp/dependencycheck/data/nvdcve/CveDB.java index c7c064da5..d6e91fcb2 100644 --- a/src/main/java/org/owasp/dependencycheck/data/nvdcve/CveDB.java +++ b/src/main/java/org/owasp/dependencycheck/data/nvdcve/CveDB.java @@ -21,7 +21,6 @@ package org.owasp.dependencycheck.data.nvdcve; import java.io.File; import java.io.IOException; import java.io.UnsupportedEncodingException; -import java.net.URLDecoder; import java.sql.CallableStatement; import java.sql.Connection; import java.sql.DriverManager; @@ -37,6 +36,7 @@ import org.owasp.dependencycheck.data.cwe.CweDB; import org.owasp.dependencycheck.dependency.Reference; import org.owasp.dependencycheck.dependency.Vulnerability; import org.owasp.dependencycheck.dependency.VulnerableSoftware; +import org.owasp.dependencycheck.utils.FileUtils; import org.owasp.dependencycheck.utils.Settings; /** @@ -408,9 +408,7 @@ public class CveDB { */ public static File getDataDirectory() throws IOException { final String fileName = Settings.getString(Settings.KEYS.CVE_INDEX); - final String filePath = CveDB.class.getProtectionDomain().getCodeSource().getLocation().getPath(); - final String decodedPath = URLDecoder.decode(filePath, "UTF-8"); - File exePath = new File(decodedPath); + File exePath = FileUtils.getDataDirectory(fileName, CveDB.class); if (exePath.getName().toLowerCase().endsWith(".jar")) { exePath = exePath.getParentFile(); diff --git a/src/main/java/org/owasp/dependencycheck/utils/FileUtils.java b/src/main/java/org/owasp/dependencycheck/utils/FileUtils.java index 0d48eb8d1..9cc82b4a2 100644 --- a/src/main/java/org/owasp/dependencycheck/utils/FileUtils.java +++ b/src/main/java/org/owasp/dependencycheck/utils/FileUtils.java @@ -21,6 +21,7 @@ package org.owasp.dependencycheck.utils; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; +import java.net.URLDecoder; /** * A collection of utilities for processing information about files. @@ -67,4 +68,26 @@ public final class FileUtils { throw new FileNotFoundException("Failed to delete file: " + file); } } + + /** + * Returns the data directory. If a path was specified in dependencycheck.properties + * or was specified using the Settings object, and the path exists, that path will be + * returned as a File object. If it does not exist, then a File object will be created + * based on the file location of the JAR containing the specified class. + * + * @param configuredFilePath the configured relative or absolute path + * @param clazz the class whos path will be resolved + * @return a File object + * @throws IOException is thrown if the path could not be decoded + */ + public static File getDataDirectory(String configuredFilePath, Class clazz) throws IOException { + File file = new File(configuredFilePath); + if (file.exists() && file.isDirectory() && file.canWrite()) { + return file; + } else { + String filePath = clazz.getProtectionDomain().getCodeSource().getLocation().getPath(); + return new File(URLDecoder.decode(filePath, "UTF-8")); + } + } + } diff --git a/src/test/java/org/owasp/dependencycheck/data/cpe/BaseIndexTestCase.java b/src/test/java/org/owasp/dependencycheck/data/cpe/BaseIndexTestCase.java index ba61280c6..475d1287b 100644 --- a/src/test/java/org/owasp/dependencycheck/data/cpe/BaseIndexTestCase.java +++ b/src/test/java/org/owasp/dependencycheck/data/cpe/BaseIndexTestCase.java @@ -18,20 +18,19 @@ */ package org.owasp.dependencycheck.data.cpe; -import org.owasp.dependencycheck.data.cpe.Index; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; -import java.net.URLDecoder; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; +import org.owasp.dependencycheck.utils.FileUtils; import org.owasp.dependencycheck.utils.Settings; /** @@ -59,9 +58,7 @@ public abstract class BaseIndexTestCase { protected static File getDataDirectory() throws IOException { String fileName = Settings.getString(Settings.KEYS.CPE_INDEX); - String filePath = Index.class.getProtectionDomain().getCodeSource().getLocation().getPath(); - String decodedPath = URLDecoder.decode(filePath, "UTF-8"); - File exePath = new File(decodedPath); + File exePath = FileUtils.getDataDirectory(fileName, Index.class); if (exePath.getName().toLowerCase().endsWith(".jar")) { exePath = exePath.getParentFile(); } else { diff --git a/src/test/java/org/owasp/dependencycheck/data/nvdcve/BaseDBTestCase.java b/src/test/java/org/owasp/dependencycheck/data/nvdcve/BaseDBTestCase.java index d0cc33c84..f80681551 100644 --- a/src/test/java/org/owasp/dependencycheck/data/nvdcve/BaseDBTestCase.java +++ b/src/test/java/org/owasp/dependencycheck/data/nvdcve/BaseDBTestCase.java @@ -25,10 +25,10 @@ import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; -import java.net.URLDecoder; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import junit.framework.TestCase; +import org.owasp.dependencycheck.utils.FileUtils; import org.owasp.dependencycheck.utils.Settings; /** @@ -49,9 +49,7 @@ public abstract class BaseDBTestCase extends TestCase { protected static File getDataDirectory() throws IOException { String fileName = Settings.getString(Settings.KEYS.CVE_INDEX); - String filePath = Index.class.getProtectionDomain().getCodeSource().getLocation().getPath(); - String decodedPath = URLDecoder.decode(filePath, "UTF-8"); - File exePath = new File(decodedPath); + File exePath = FileUtils.getDataDirectory(fileName, Index.class); if (exePath.getName().toLowerCase().endsWith(".jar")) { exePath = exePath.getParentFile(); } else { From dbc862ad39129253a39b5813f3ed09302a65b8e4 Mon Sep 17 00:00:00 2001 From: Steve Springett Date: Mon, 27 May 2013 00:10:08 -0700 Subject: [PATCH 4/4] Adding more control over data directory path Former-commit-id: 263475fc5b3aae04f2530ea78a0456deb18686fe --- .../org/owasp/dependencycheck/data/cpe/Index.java | 9 +-------- .../owasp/dependencycheck/data/nvdcve/CveDB.java | 11 +---------- .../org/owasp/dependencycheck/utils/FileUtils.java | 14 +++++++++++--- .../data/cpe/BaseIndexTestCase.java | 10 +--------- .../data/nvdcve/BaseDBTestCase.java | 10 +--------- 5 files changed, 15 insertions(+), 39 deletions(-) diff --git a/src/main/java/org/owasp/dependencycheck/data/cpe/Index.java b/src/main/java/org/owasp/dependencycheck/data/cpe/Index.java index b3c3d9254..20b9b1c69 100644 --- a/src/main/java/org/owasp/dependencycheck/data/cpe/Index.java +++ b/src/main/java/org/owasp/dependencycheck/data/cpe/Index.java @@ -70,14 +70,7 @@ public class Index extends AbstractIndex { */ public File getDataDirectory() throws IOException { final String fileName = Settings.getString(Settings.KEYS.CPE_INDEX); - File exePath = FileUtils.getDataDirectory(fileName, Index.class); - if (exePath.getName().toLowerCase().endsWith(".jar")) { - exePath = exePath.getParentFile(); - } else { - exePath = new File("."); - } - File path = new File(exePath.getCanonicalFile() + File.separator + fileName); - path = new File(path.getCanonicalPath()); + File path = FileUtils.getDataDirectory(fileName, Index.class); if (!path.exists()) { if (!path.mkdirs()) { throw new IOException("Unable to create CPE Data directory"); diff --git a/src/main/java/org/owasp/dependencycheck/data/nvdcve/CveDB.java b/src/main/java/org/owasp/dependencycheck/data/nvdcve/CveDB.java index d6e91fcb2..cd517f91c 100644 --- a/src/main/java/org/owasp/dependencycheck/data/nvdcve/CveDB.java +++ b/src/main/java/org/owasp/dependencycheck/data/nvdcve/CveDB.java @@ -408,16 +408,7 @@ public class CveDB { */ public static File getDataDirectory() throws IOException { final String fileName = Settings.getString(Settings.KEYS.CVE_INDEX); - File exePath = FileUtils.getDataDirectory(fileName, CveDB.class); - - if (exePath.getName().toLowerCase().endsWith(".jar")) { - exePath = exePath.getParentFile(); - } else { - exePath = new File("."); - } - File path = new File(exePath.getCanonicalFile() + File.separator + fileName); - path = new File(path.getCanonicalPath()); - + File path = FileUtils.getDataDirectory(fileName, CveDB.class); if (!path.exists()) { if (!path.mkdirs()) { throw new IOException("Unable to create NVD CVE Data directory"); diff --git a/src/main/java/org/owasp/dependencycheck/utils/FileUtils.java b/src/main/java/org/owasp/dependencycheck/utils/FileUtils.java index 9cc82b4a2..1949b8d83 100644 --- a/src/main/java/org/owasp/dependencycheck/utils/FileUtils.java +++ b/src/main/java/org/owasp/dependencycheck/utils/FileUtils.java @@ -83,10 +83,18 @@ public final class FileUtils { public static File getDataDirectory(String configuredFilePath, Class clazz) throws IOException { File file = new File(configuredFilePath); if (file.exists() && file.isDirectory() && file.canWrite()) { - return file; + return new File(file.getCanonicalPath()); } else { - String filePath = clazz.getProtectionDomain().getCodeSource().getLocation().getPath(); - return new File(URLDecoder.decode(filePath, "UTF-8")); + final String filePath = clazz.getProtectionDomain().getCodeSource().getLocation().getPath(); + final String decodedPath = URLDecoder.decode(filePath, "UTF-8"); + File exePath = new File(decodedPath); + if (exePath.getName().toLowerCase().endsWith(".jar")) { + exePath = exePath.getParentFile(); + } else { + exePath = new File("."); + } + File path = new File(exePath.getCanonicalFile() + File.separator + configuredFilePath); + return new File(path.getCanonicalPath()); } } diff --git a/src/test/java/org/owasp/dependencycheck/data/cpe/BaseIndexTestCase.java b/src/test/java/org/owasp/dependencycheck/data/cpe/BaseIndexTestCase.java index 475d1287b..a61e11ebd 100644 --- a/src/test/java/org/owasp/dependencycheck/data/cpe/BaseIndexTestCase.java +++ b/src/test/java/org/owasp/dependencycheck/data/cpe/BaseIndexTestCase.java @@ -58,15 +58,7 @@ public abstract class BaseIndexTestCase { protected static File getDataDirectory() throws IOException { String fileName = Settings.getString(Settings.KEYS.CPE_INDEX); - File exePath = FileUtils.getDataDirectory(fileName, Index.class); - if (exePath.getName().toLowerCase().endsWith(".jar")) { - exePath = exePath.getParentFile(); - } else { - exePath = new File("."); - } - File path = new File(exePath.getCanonicalFile() + File.separator + fileName); - path = new File(path.getCanonicalPath()); - return path; + return FileUtils.getDataDirectory(fileName, Index.class); } public static void ensureIndexExists() throws Exception { diff --git a/src/test/java/org/owasp/dependencycheck/data/nvdcve/BaseDBTestCase.java b/src/test/java/org/owasp/dependencycheck/data/nvdcve/BaseDBTestCase.java index f80681551..2c579de86 100644 --- a/src/test/java/org/owasp/dependencycheck/data/nvdcve/BaseDBTestCase.java +++ b/src/test/java/org/owasp/dependencycheck/data/nvdcve/BaseDBTestCase.java @@ -49,15 +49,7 @@ public abstract class BaseDBTestCase extends TestCase { protected static File getDataDirectory() throws IOException { String fileName = Settings.getString(Settings.KEYS.CVE_INDEX); - File exePath = FileUtils.getDataDirectory(fileName, Index.class); - if (exePath.getName().toLowerCase().endsWith(".jar")) { - exePath = exePath.getParentFile(); - } else { - exePath = new File("."); - } - File path = new File(exePath.getCanonicalFile() + File.separator + fileName); - path = new File(path.getCanonicalPath()); - return path; + return FileUtils.getDataDirectory(fileName, Index.class); } public static void ensureDBExists() throws Exception {