Merge remote-tracking branch 'upstream/master'

Former-commit-id: b066078bf0df0365d850ea71e2434a5376b9cd16
This commit is contained in:
Will Stranathan
2014-02-26 20:45:30 -05:00
21 changed files with 507 additions and 183 deletions

View File

@@ -741,47 +741,57 @@ public class DependencyCheckTask extends Task {
validateConfiguration();
populateSettings();
final Engine engine = new Engine();
for (Resource resource : path) {
final FileProvider provider = resource.as(FileProvider.class);
if (provider != null) {
final File file = provider.getFile();
if (file != null && file.exists()) {
engine.scan(file);
}
}
}
Engine engine = null;
try {
engine.analyzeDependencies();
DatabaseProperties prop = null;
CveDB cve = null;
try {
cve = new CveDB();
cve.open();
prop = cve.getDatabaseProperties();
} catch (DatabaseException ex) {
Logger.getLogger(DependencyCheckTask.class.getName()).log(Level.FINE, "Unable to retrieve DB Properties", ex);
} finally {
if (cve != null) {
cve.close();
engine = new Engine();
for (Resource resource : path) {
final FileProvider provider = resource.as(FileProvider.class);
if (provider != null) {
final File file = provider.getFile();
if (file != null && file.exists()) {
engine.scan(file);
}
}
}
final ReportGenerator reporter = new ReportGenerator(applicationName, engine.getDependencies(), engine.getAnalyzers(), prop);
reporter.generateReports(reportOutputDirectory, reportFormat);
try {
engine.analyzeDependencies();
DatabaseProperties prop = null;
CveDB cve = null;
try {
cve = new CveDB();
cve.open();
prop = cve.getDatabaseProperties();
} catch (DatabaseException ex) {
Logger.getLogger(DependencyCheckTask.class.getName()).log(Level.FINE, "Unable to retrieve DB Properties", ex);
} finally {
if (cve != null) {
cve.close();
}
}
final ReportGenerator reporter = new ReportGenerator(applicationName, engine.getDependencies(), engine.getAnalyzers(), prop);
reporter.generateReports(reportOutputDirectory, reportFormat);
if (this.failBuildOnCVSS <= 10) {
checkForFailure(engine.getDependencies());
if (this.failBuildOnCVSS <= 10) {
checkForFailure(engine.getDependencies());
}
if (this.showSummary) {
showSummary(engine.getDependencies());
}
} catch (IOException ex) {
Logger.getLogger(DependencyCheckTask.class.getName()).log(Level.FINE, "Unable to generate dependency-check report", ex);
throw new BuildException("Unable to generate dependency-check report", ex);
} catch (Exception ex) {
Logger.getLogger(DependencyCheckTask.class.getName()).log(Level.FINE, "An exception occurred; unable to continue task", ex);
throw new BuildException("An exception occurred; unable to continue task", ex);
}
if (this.showSummary) {
showSummary(engine.getDependencies());
} catch (DatabaseException ex) {
Logger.getLogger(DependencyCheckTask.class.getName()).log(Level.SEVERE, "Unable to connect to the dependency-check database; analysis has stopped");
Logger.getLogger(DependencyCheckTask.class.getName()).log(Level.FINE, "", ex);
} finally {
if (engine != null) {
engine.cleanup();
}
} catch (IOException ex) {
Logger.getLogger(DependencyCheckTask.class.getName()).log(Level.FINE, "Unable to generate dependency-check report", ex);
throw new BuildException("Unable to generate dependency-check report", ex);
} catch (Exception ex) {
Logger.getLogger(DependencyCheckTask.class.getName()).log(Level.FINE, "An exception occurred; unable to continue task", ex);
throw new BuildException("An exception occurred; unable to continue task", ex);
}
}

View File

@@ -98,36 +98,46 @@ public class App {
* @param files the files/directories to scan
*/
private void runScan(String reportDirectory, String outputFormat, String applicationName, String[] files, String extraExtensions) {
final Engine scanner = new Engine();
for (String file : files) {
scanner.scan(file);
}
scanner.analyzeDependencies();
final List<Dependency> dependencies = scanner.getDependencies();
DatabaseProperties prop = null;
CveDB cve = null;
Engine scanner = null;
try {
cve = new CveDB();
cve.open();
prop = cve.getDatabaseProperties();
} catch (DatabaseException ex) {
Logger.getLogger(App.class.getName()).log(Level.FINE, "Unable to retrieve DB Properties", ex);
} finally {
if (cve != null) {
cve.close();
scanner = new Engine();
for (String file : files) {
scanner.scan(file);
}
scanner.analyzeDependencies();
final List<Dependency> dependencies = scanner.getDependencies();
DatabaseProperties prop = null;
CveDB cve = null;
try {
cve = new CveDB();
cve.open();
prop = cve.getDatabaseProperties();
} catch (DatabaseException ex) {
Logger.getLogger(App.class.getName()).log(Level.FINE, "Unable to retrieve DB Properties", ex);
} finally {
if (cve != null) {
cve.close();
}
}
final ReportGenerator report = new ReportGenerator(applicationName, dependencies, scanner.getAnalyzers(), prop);
try {
report.generateReports(reportDirectory, outputFormat);
} catch (IOException ex) {
Logger.getLogger(App.class.getName()).log(Level.SEVERE, "There was an IO error while attempting to generate the report.");
Logger.getLogger(App.class.getName()).log(Level.FINE, null, ex);
} catch (Exception ex) {
Logger.getLogger(App.class.getName()).log(Level.SEVERE, "There was an error while attempting to generate the report.");
Logger.getLogger(App.class.getName()).log(Level.FINE, null, ex);
}
} catch (DatabaseException ex) {
Logger.getLogger(App.class.getName()).log(Level.SEVERE, "Unable to connect to the dependency-check database; analysis has stopped");
Logger.getLogger(App.class.getName()).log(Level.FINE, "", ex);
} finally {
if (scanner != null) {
scanner.cleanup();
}
}
final ReportGenerator report = new ReportGenerator(applicationName, dependencies, scanner.getAnalyzers(), prop);
try {
report.generateReports(reportDirectory, outputFormat);
} catch (IOException ex) {
Logger.getLogger(App.class.getName()).log(Level.SEVERE, "There was an IO error while attempting to generate the report.");
Logger.getLogger(App.class.getName()).log(Level.INFO, null, ex);
} catch (Exception ex) {
Logger.getLogger(App.class.getName()).log(Level.SEVERE, "There was an error while attempting to generate the report.");
Logger.getLogger(App.class.getName()).log(Level.INFO, null, ex);
}
}

View File

@@ -32,6 +32,7 @@ import org.owasp.dependencycheck.analyzer.AnalyzerService;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.data.cpe.CpeMemoryIndex;
import org.owasp.dependencycheck.data.cpe.IndexException;
import org.owasp.dependencycheck.data.nvdcve.ConnectionFactory;
import org.owasp.dependencycheck.data.nvdcve.CveDB;
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
import org.owasp.dependencycheck.data.update.CachedWebDataSource;
@@ -67,11 +68,14 @@ public class Engine {
/**
* Creates a new Engine.
*
* @throws DatabaseException thrown if there is an error connecting to the database
*/
public Engine() {
public Engine() throws DatabaseException {
this.extensions = new HashSet<String>();
this.dependencies = new ArrayList<Dependency>();
this.analyzers = new EnumMap<AnalysisPhase, List<Analyzer>>(AnalysisPhase.class);
ConnectionFactory.initialize();
boolean autoUpdate = true;
try {
@@ -85,6 +89,13 @@ public class Engine {
loadAnalyzers();
}
/**
* Properly cleans up resources allocated during analysis.
*/
public void cleanup() {
ConnectionFactory.cleanup();
}
/**
* Loads the analyzers specified in the configuration file (or system properties).
*/
@@ -291,7 +302,7 @@ public class Engine {
} catch (Exception ex) {
final String msg = String.format("Exception occurred initializing %s.", a.getName());
Logger.getLogger(Engine.class.getName()).log(Level.SEVERE, msg);
Logger.getLogger(Engine.class.getName()).log(Level.INFO, null, ex);
Logger.getLogger(Engine.class.getName()).log(Level.FINE, null, ex);
try {
a.close();
} catch (Exception ex1) {
@@ -326,7 +337,7 @@ public class Engine {
Logger.getLogger(Engine.class.getName()).log(Level.FINE, "", ex);
} catch (Throwable ex) {
final String axMsg = String.format("An unexpected error occurred during analysis of '%s'", d.getActualFilePath());
final AnalysisException ax = new AnalysisException(axMsg, ex);
//final AnalysisException ax = new AnalysisException(axMsg, ex);
Logger.getLogger(Engine.class.getName()).log(Level.WARNING, axMsg);
Logger.getLogger(Engine.class.getName()).log(Level.FINE, "", ex);
}

View File

@@ -95,9 +95,9 @@ public class ArchiveAnalyzer extends AbstractAnalyzer implements Analyzer {
private static final Set<String> EXTENSIONS = newHashSet("tar", "gz", "tgz");
static {
String additionalZipExt = Settings.getString(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS);
final String additionalZipExt = Settings.getString(Settings.KEYS.ADDITIONAL_ZIP_EXTENSIONS);
if (additionalZipExt != null) {
HashSet ext = new HashSet<String>(Arrays.asList(additionalZipExt));
final HashSet ext = new HashSet<String>(Arrays.asList(additionalZipExt));
ZIPPABLES.addAll(ext);
}
EXTENSIONS.addAll(ZIPPABLES);
@@ -263,7 +263,7 @@ public class ArchiveAnalyzer extends AbstractAnalyzer implements Analyzer {
try {
fis = new FileInputStream(archive);
} catch (FileNotFoundException ex) {
Logger.getLogger(ArchiveAnalyzer.class.getName()).log(Level.INFO, null, ex);
Logger.getLogger(ArchiveAnalyzer.class.getName()).log(Level.FINE, null, ex);
throw new AnalysisException("Archive file was not found.", ex);
}
final String archiveExt = org.owasp.dependencycheck.utils.FileUtils.getFileExtension(archive.getName()).toLowerCase();

View File

@@ -17,7 +17,6 @@
*/
package org.owasp.dependencycheck.analyzer;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
@@ -33,6 +32,7 @@ import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.dependency.Confidence;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.dependency.Evidence;
@@ -172,7 +172,7 @@ public class AssemblyAnalyzer extends AbstractAnalyzer {
grokAssemblyExe = tempFile;
// Set the temp file to get deleted when we're done
grokAssemblyExe.deleteOnExit();
LOG.log(Level.INFO, "Extracted GrokAssembly.exe to {0}", grokAssemblyExe.getPath());
LOG.log(Level.FINE, "Extracted GrokAssembly.exe to {0}", grokAssemblyExe.getPath());
} catch (IOException ioe) {
LOG.log(Level.WARNING, "Could not extract GrokAssembly.exe: {0}", ioe.getMessage());
throw new AnalysisException("Could not extract GrokAssembly.exe", ioe);
@@ -201,13 +201,15 @@ public class AssemblyAnalyzer extends AbstractAnalyzer {
final XPath xpath = XPathFactory.newInstance().newXPath();
final String error = xpath.evaluate("/assembly/error", doc);
if (p.exitValue() != 1 || error == null || "".equals(error)) {
LOG.warning("GrokAssembly.exe is not working properly");
LOG.warning("An error occured with the .NET AssemblyAnalyzer, please see the log for more details.");
LOG.fine("GrokAssembly.exe is not working properly");
grokAssemblyExe = null;
throw new AnalysisException("Could not execute GrokAssembly");
throw new AnalysisException("Could not execute .NET AssemblyAnalyzer");
}
} catch (Exception e) {
LOG.warning("Could not execute GrokAssembly " + e.getMessage());
throw new AnalysisException("Could not execute GrokAssembly", e);
LOG.warning("An error occured with the .NET AssemblyAnalyzer, please see the log for more details.");
LOG.fine("Could not execute GrokAssembly " + e.getMessage());
throw new AnalysisException("An error occured with the .NET AssemblyAnalyzer", e);
}
builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();

View File

@@ -261,7 +261,7 @@ public class JarAnalyzer extends AbstractAnalyzer implements Analyzer {
jar = new JarFile(dependency.getActualFilePath());
} catch (IOException ex) {
final String msg = String.format("Unable to read JarFile '%s'.", dependency.getActualFilePath());
final AnalysisException ax = new AnalysisException(msg, ex);
//final AnalysisException ax = new AnalysisException(msg, ex);
Logger.getLogger(JarAnalyzer.class.getName()).log(Level.WARNING, msg);
Logger.getLogger(JarAnalyzer.class.getName()).log(Level.FINE, null, ex);
return false;
@@ -271,9 +271,9 @@ public class JarAnalyzer extends AbstractAnalyzer implements Analyzer {
pomEntries = retrievePomListing(jar);
} catch (IOException ex) {
final String msg = String.format("Unable to read Jar file entries in '%s'.", dependency.getActualFilePath());
final AnalysisException ax = new AnalysisException(msg, ex);
//final AnalysisException ax = new AnalysisException(msg, ex);
Logger.getLogger(JarAnalyzer.class.getName()).log(Level.WARNING, msg);
Logger.getLogger(JarAnalyzer.class.getName()).log(Level.INFO, msg, ex);
Logger.getLogger(JarAnalyzer.class.getName()).log(Level.FINE, msg, ex);
return false;
}
if (pomEntries.isEmpty()) {
@@ -314,7 +314,7 @@ public class JarAnalyzer extends AbstractAnalyzer implements Analyzer {
} catch (AnalysisException ex) {
final String msg = String.format("An error occured while analyzing '%s'.", dependency.getActualFilePath());
Logger.getLogger(JarAnalyzer.class.getName()).log(Level.WARNING, msg);
Logger.getLogger(JarAnalyzer.class.getName()).log(Level.INFO, "", ex);
Logger.getLogger(JarAnalyzer.class.getName()).log(Level.FINE, "", ex);
}
}
return foundSomething;
@@ -768,7 +768,7 @@ public class JarAnalyzer extends AbstractAnalyzer implements Analyzer {
} else {
versionEvidence.addEvidence(source, key, value, Confidence.MEDIUM);
}
} else if (key.equals("build-id")) {
} else if ("build-id".equals(key)) {
int pos = value.indexOf('(');
if (pos >= 0) {
value = value.substring(0, pos - 1);

View File

@@ -0,0 +1,12 @@
/**
* <html>
* <head>
* <title>org.owasp.dependencycheck.analyzer.exception</title>
* </head>
* <body>
* <p>
* A collection of exception classes used within the analyzers.</p>
* </body>
* </html>
*/
package org.owasp.dependencycheck.analyzer.exception;

View File

@@ -18,10 +18,9 @@
package org.owasp.dependencycheck.data.cpe;
import java.io.IOException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.lucene.analysis.Analyzer;
@@ -45,6 +44,8 @@ import org.owasp.dependencycheck.data.lucene.FieldAnalyzer;
import org.owasp.dependencycheck.data.lucene.LuceneUtils;
import org.owasp.dependencycheck.data.lucene.SearchFieldAnalyzer;
import org.owasp.dependencycheck.data.nvdcve.CveDB;
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
import org.owasp.dependencycheck.utils.Pair;
/**
* An in memory lucene index that contains the vendor/product combinations from the CPE (application) identifiers within
@@ -210,7 +211,7 @@ public final class CpeMemoryIndex {
}
/**
* Builds the lucene index based off of the data within the CveDB.
* Builds the CPE Lucene Index based off of the data within the CveDB.
*
* @param cve the data base containing the CPE data
* @throws IndexException thrown if there is an issue creating the index
@@ -222,15 +223,12 @@ public final class CpeMemoryIndex {
analyzer = createIndexingAnalyzer();
final IndexWriterConfig conf = new IndexWriterConfig(LuceneUtils.CURRENT_VERSION, analyzer);
indexWriter = new IndexWriter(index, conf);
final ResultSet rs = cve.getVendorProductList();
if (rs == null) {
throw new IndexException("No data exists");
}
try {
while (rs.next()) {
saveEntry(rs.getString(1), rs.getString(2), indexWriter);
final Set<Pair<String, String>> data = cve.getVendorProductList();
for (Pair<String, String> pair : data) {
saveEntry(pair.getLeft(), pair.getRight(), indexWriter);
}
} catch (SQLException ex) {
} catch (DatabaseException ex) {
Logger.getLogger(CpeMemoryIndex.class.getName()).log(Level.FINE, null, ex);
throw new IndexException("Error reading CPE data", ex);
}

View File

@@ -67,7 +67,7 @@ public final class UrlTokenizingFilter extends AbstractTokenizingFilter {
final List<String> data = UrlStringUtils.extractImportantUrlData(part);
tokens.addAll(data);
} catch (MalformedURLException ex) {
Logger.getLogger(UrlTokenizingFilter.class.getName()).log(Level.INFO, "error parsing " + part, ex);
Logger.getLogger(UrlTokenizingFilter.class.getName()).log(Level.FINE, "error parsing " + part, ex);
tokens.add(part);
}
} else {

View File

@@ -24,6 +24,7 @@ import java.io.InputStream;
import java.io.InputStreamReader;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
@@ -50,6 +51,22 @@ public final class ConnectionFactory {
* Resource location for SQL file used to create the database schema.
*/
public static final String DB_STRUCTURE_RESOURCE = "data/initialize.sql";
/**
* The database driver used to connect to the database.
*/
private static Driver driver = null;
/**
* The database connection string.
*/
private static String connectionString = null;
/**
* The username to connect to the database.
*/
private static String userName = null;
/**
* The password for the database.
*/
private static String password = null;
/**
* Private constructor for this factory class; no instance is ever needed.
@@ -58,64 +75,134 @@ public final class ConnectionFactory {
}
/**
* Constructs a new database connection object per the database configuration. This will load the appropriate
* database driver, via the DriverManager, if configured.
* Initializes the connection factory. Ensuring that the appropriate drivers are loaded and that a connection can be
* made successfully.
*
* @return a database connection object
* @throws DatabaseException thrown if there is an exception loading the database connection
* @throws DatabaseException thrown if we are unable to connect to the database
*/
public static Connection getConnection() throws DatabaseException {
public static synchronized void initialize() throws DatabaseException {
//this only needs to be called once.
if (connectionString != null) {
return;
}
//load the driver if necessary
final String driverName = Settings.getString(Settings.KEYS.DB_DRIVER_NAME, "");
if (!driverName.isEmpty()) { //likely need to load the correct driver
Logger.getLogger(CveDB.class.getName()).log(Level.FINE, "Loading driver: {0}", driverName);
final String driverPath = Settings.getString(Settings.KEYS.DB_DRIVER_PATH, "");
try {
if (!driverPath.isEmpty()) {
Logger.getLogger(CveDB.class.getName()).log(Level.FINE, "Loading driver from: {0}", driverPath);
driver = DriverLoader.load(driverName, driverPath);
} else {
driver = DriverLoader.load(driverName);
}
} catch (DriverLoadException ex) {
Logger.getLogger(ConnectionFactory.class.getName()).log(Level.FINE, "Unable to load database driver", ex);
throw new DatabaseException("Unable to load database driver");
}
}
userName = Settings.getString(Settings.KEYS.DB_USER, "dcuser");
//yes, yes - hard-coded password - only if there isn't one in the properties file.
password = Settings.getString(Settings.KEYS.DB_PASSWORD, "DC-Pass1337!");
try {
connectionString = getConnectionString();
} catch (IOException ex) {
Logger.getLogger(ConnectionFactory.class.getName()).log(Level.FINE,
"Unable to retrieve the database connection string", ex);
throw new DatabaseException("Unable to retrieve the database connection string");
}
boolean shouldCreateSchema = false;
try {
if (connectionString.startsWith("jdbc:h2:file:")) { //H2
shouldCreateSchema = !dbSchemaExists();
Logger.getLogger(CveDB.class.getName()).log(Level.FINE, "Need to create DB Structure: {0}", shouldCreateSchema);
}
} catch (IOException ioex) {
Logger.getLogger(ConnectionFactory.class.getName()).log(Level.FINE, "Unable to verify database exists", ioex);
throw new DatabaseException("Unable to verify database exists");
}
Logger.getLogger(CveDB.class.getName()).log(Level.FINE, "Loading database connection");
Logger.getLogger(CveDB.class.getName()).log(Level.FINE, "Connection String: {0}", connectionString);
Logger.getLogger(CveDB.class.getName()).log(Level.FINE, "Database User: {0}", userName);
Connection conn = null;
try {
Logger.getLogger(CveDB.class.getName()).log(Level.FINE, "Loading database connection");
final String connStr = getConnectionString();
final String user = Settings.getString(Settings.KEYS.DB_USER, "dcuser");
//yes, yes - hard-coded password - only if there isn't one in the properties file.
final String pass = Settings.getString(Settings.KEYS.DB_PASSWORD, "DC-Pass1337!");
Logger.getLogger(CveDB.class.getName()).log(Level.FINE, "Connection String: {0}", connStr);
Logger.getLogger(CveDB.class.getName()).log(Level.FINE, "Database User: {0}", user);
boolean createTables = false;
if (connStr.startsWith("jdbc:h2:file:")) { //H2
createTables = needToCreateDatabaseStructure();
Logger.getLogger(CveDB.class.getName()).log(Level.FINE, "Need to create DB Structure: {0}", createTables);
}
final String driverName = Settings.getString(Settings.KEYS.DB_DRIVER_NAME, "");
if (!driverName.isEmpty()) { //likely need to load the correct driver
Logger.getLogger(CveDB.class.getName()).log(Level.FINE, "Loading driver: {0}", driverName);
final String driverPath = Settings.getString(Settings.KEYS.DB_DRIVER_PATH, "");
if (!driverPath.isEmpty()) { //ugh, driver is not on classpath?
Logger.getLogger(CveDB.class.getName()).log(Level.FINE, "Loading driver from: {0}", driverPath);
DriverLoader.load(driverName, driverPath);
} else {
DriverLoader.load(driverName);
conn = DriverManager.getConnection(connectionString, userName, password);
} catch (SQLException ex) {
if (ex.getMessage().contains("java.net.UnknownHostException") && connectionString.contains("AUTO_SERVER=TRUE;")) {
connectionString = connectionString.replace("AUTO_SERVER=TRUE;", "");
try {
conn = DriverManager.getConnection(connectionString, userName, password);
Settings.setString(Settings.KEYS.DB_CONNECTION_STRING, connectionString);
Logger.getLogger(ConnectionFactory.class.getName()).log(Level.FINE,
"Unable to start the database in server mode; reverting to single user mode");
} catch (SQLException sqlex) {
Logger.getLogger(ConnectionFactory.class.getName()).log(Level.FINE, "Unable to connect to the database", ex);
throw new DatabaseException("Unable to connect to the database");
}
} else {
Logger.getLogger(ConnectionFactory.class.getName()).log(Level.FINE, "Unable to connect to the database", ex);
throw new DatabaseException("Unable to connect to the database");
}
//JDBC4 drivers don't need this call.
//Class.forName("org.h2.Driver");
conn = DriverManager.getConnection(connStr, user, pass);
if (createTables) {
if (shouldCreateSchema) {
try {
createTables(conn);
} catch (DatabaseException ex) {
Logger.getLogger(ConnectionFactory.class.getName()).log(Level.FINE, null, ex);
} catch (DatabaseException dex) {
Logger.getLogger(ConnectionFactory.class.getName()).log(Level.FINE, null, dex);
throw new DatabaseException("Unable to create the database structure");
}
} else {
try {
ensureSchemaVersion(conn);
} catch (DatabaseException ex) {
Logger.getLogger(ConnectionFactory.class.getName()).log(Level.FINE, null, ex);
} catch (DatabaseException dex) {
Logger.getLogger(ConnectionFactory.class.getName()).log(Level.FINE, null, dex);
throw new DatabaseException("Database schema does not match this version of dependency-check");
}
}
} catch (IOException ex) {
Logger.getLogger(ConnectionFactory.class.getName()).log(Level.FINE, null, ex);
throw new DatabaseException("Unable to load database");
} catch (DriverLoadException ex) {
Logger.getLogger(ConnectionFactory.class.getName()).log(Level.FINE, null, ex);
throw new DatabaseException("Unable to load database driver");
} finally {
if (conn != null) {
try {
conn.close();
} catch (SQLException ex) {
Logger.getLogger(ConnectionFactory.class.getName()).log(Level.FINE, "An error occured closing the connection", ex);
}
}
}
}
/**
* Cleans up resources and unloads any registered database drivers. This needs to be called to ensure the driver is
* unregistered prior to the finalize method being called as during shutdown the class loader used to load the
* driver may be unloaded prior to the driver being de-registered.
*/
public static synchronized void cleanup() {
if (driver != null) {
try {
DriverManager.deregisterDriver(driver);
} catch (SQLException ex) {
Logger.getLogger(ConnectionFactory.class.getName()).log(Level.FINE, "An error occured unloading the databse driver", ex);
}
driver = null;
}
connectionString = null;
userName = null;
password = null;
}
/**
* Constructs a new database connection object per the database configuration.
*
* @return a database connection object
* @throws DatabaseException thrown if there is an exception loading the database connection
*/
public static Connection getConnection() throws DatabaseException {
initialize();
Connection conn = null;
try {
conn = DriverManager.getConnection(connectionString, userName, password);
} catch (SQLException ex) {
Logger.getLogger(ConnectionFactory.class.getName()).log(Level.FINE, null, ex);
throw new DatabaseException("Unable to connect to the database");
@@ -164,11 +251,11 @@ public final class ConnectionFactory {
* @return true if the H2 database file does not exist; otherwise false
* @throws IOException thrown if the data directory does not exist and cannot be created
*/
private static boolean needToCreateDatabaseStructure() throws IOException {
private static boolean dbSchemaExists() throws IOException {
final File dir = getDataDirectory();
final String name = String.format("cve.%s.h2.db", DB_SCHEMA_VERSION);
final File file = new File(dir, name);
return !file.exists();
return file.exists();
}
/**

View File

@@ -38,6 +38,7 @@ import org.owasp.dependencycheck.dependency.VulnerableSoftware;
import org.owasp.dependencycheck.utils.DBUtils;
import org.owasp.dependencycheck.utils.DependencyVersion;
import org.owasp.dependencycheck.utils.DependencyVersionUtil;
import org.owasp.dependencycheck.utils.Pair;
/**
* The database holding information about the NVD CVE data.
@@ -295,19 +296,27 @@ public class CveDB {
/**
* Returns the entire list of vendor/product combinations.
*
* @return the entire list of vendor/product combinations.
* @return the entire list of vendor/product combinations
* @throws DatabaseException thrown when there is an error retrieving the data from the DB
*/
public ResultSet getVendorProductList() {
public Set<Pair<String, String>> getVendorProductList() throws DatabaseException {
HashSet data = new HashSet<Pair<String, String>>();
ResultSet rs = null;
PreparedStatement ps = null;
try {
final PreparedStatement ps = getConnection().prepareStatement(SELECT_VENDOR_PRODUCT_LIST);
ps = getConnection().prepareStatement(SELECT_VENDOR_PRODUCT_LIST);
rs = ps.executeQuery();
while (rs.next()) {
data.add(new Pair(rs.getString(1), rs.getString(2)));
}
} catch (SQLException ex) {
final String msg = "An unexpected SQL Exception occurred; please see the verbose log for more details.";
Logger.getLogger(CveDB.class.getName()).log(Level.SEVERE, msg);
Logger.getLogger(CveDB.class.getName()).log(Level.FINE, null, ex);
} // can't close the statement in the PS as the resultset is returned, closing PS would close the resultset
return rs;
throw new DatabaseException(msg, ex);
} finally {
DBUtils.closeResultSet(rs);
DBUtils.closeStatement(ps);
}
return data;
}
/**

View File

@@ -47,11 +47,12 @@ public final class DriverLoader {
* Loads the specified class using the system class loader and registers the driver with the driver manager.
*
* @param className the fully qualified name of the desired class
* @return the loaded Driver
* @throws DriverLoadException thrown if the driver cannot be loaded
*/
public static void load(String className) throws DriverLoadException {
public static Driver load(String className) throws DriverLoadException {
final ClassLoader loader = DriverLoader.class.getClassLoader(); //ClassLoader.getSystemClassLoader();
load(className, loader);
return load(className, loader);
}
/**
@@ -64,9 +65,10 @@ public final class DriverLoader {
* @param className the fully qualified name of the desired class
* @param pathToDriver the path to the JAR file containing the driver; note, this can be a semi-colon separated list
* of paths
* @return the loaded Driver
* @throws DriverLoadException thrown if the driver cannot be loaded
*/
public static void load(String className, String pathToDriver) throws DriverLoadException {
public static Driver load(String className, String pathToDriver) throws DriverLoadException {
final URLClassLoader parent = (URLClassLoader) ClassLoader.getSystemClassLoader();
final ArrayList<URL> urls = new ArrayList<URL>();
final String[] paths = pathToDriver.split(File.pathSeparator);
@@ -103,7 +105,7 @@ public final class DriverLoader {
}
});
load(className, loader);
return load(className, loader);
}
/**
@@ -111,15 +113,18 @@ public final class DriverLoader {
*
* @param className the fully qualified name of the desired class
* @param loader the class loader to use when loading the driver
* @return the loaded Driver
* @throws DriverLoadException thrown if the driver cannot be loaded
*/
private static void load(String className, ClassLoader loader) throws DriverLoadException {
private static Driver load(String className, ClassLoader loader) throws DriverLoadException {
try {
final Class c = Class.forName(className, true, loader);
//final Class c = loader.loadClass(className);
final Driver driver = (Driver) c.newInstance();
final Driver shim = new DriverShim(driver);
//using the DriverShim to get around the fact that the DriverManager won't register a driver not in the base class path
DriverManager.registerDriver(new DriverShim(driver));
DriverManager.registerDriver(shim);
return shim;
} catch (ClassNotFoundException ex) {
final String msg = String.format("Unable to load database driver '%s'", className);
Logger.getLogger(DriverLoader.class.getName()).log(Level.FINE, msg, ex);

View File

@@ -360,7 +360,7 @@ public class EvidenceCollection implements Iterable<Evidence> {
final List<String> data = UrlStringUtils.extractImportantUrlData(part);
sb.append(' ').append(StringUtils.join(data, ' '));
} catch (MalformedURLException ex) {
Logger.getLogger(EvidenceCollection.class.getName()).log(Level.INFO, "error parsing " + part, ex);
Logger.getLogger(EvidenceCollection.class.getName()).log(Level.FINE, "error parsing " + part, ex);
sb.append(' ').append(part);
}
} else {

View File

@@ -160,7 +160,7 @@ public final class FileUtils {
try {
fis = new FileInputStream(archive);
} catch (FileNotFoundException ex) {
Logger.getLogger(FileUtils.class.getName()).log(Level.INFO, null, ex);
Logger.getLogger(FileUtils.class.getName()).log(Level.FINE, null, ex);
throw new ExtractionException("Archive file was not found.", ex);
}
zis = new ZipInputStream(new BufferedInputStream(fis));

View File

@@ -0,0 +1,124 @@
/*
* This file is part of dependency-check-core.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright (c) 2014 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.utils;
/**
* A generic pair of elements.
*
* @author Jeremy Long <jeremy.long@owasp.org>
*/
public class Pair<K, V> {
/**
* Constructs a new empty pair.
*/
public Pair() {
}
/**
* Constructs a new Pair with the given left and right values.
*
* @param left the value for the left pair
* @param right the value for the right pair
*/
public Pair(K left, V right) {
this.left = left;
this.right = right;
}
/**
* The left element of the pair.
*/
private K left = null;
/**
* Get the value of left
*
* @return the value of left
*/
public K getLeft() {
return left;
}
/**
* Set the value of left
*
* @param left new value of left
*/
public void setLeft(K left) {
this.left = left;
}
/**
* The right element of the pair.
*/
private V right = null;
/**
* Get the value of right
*
* @return the value of right
*/
public V getRight() {
return right;
}
/**
* Set the value of right
*
* @param right new value of right
*/
public void setRight(V right) {
this.right = right;
}
/**
* Generates the hash code using the hash codes from the contained objects.
*
* @return the hash code of the Pair
*/
@Override
public int hashCode() {
int hash = 3;
hash = 53 * hash + (this.left != null ? this.left.hashCode() : 0);
hash = 53 * hash + (this.right != null ? this.right.hashCode() : 0);
return hash;
}
/**
* Determines the equality of this and the provided object.
*
* @param obj the {@link Object} to check for equality to this
* @return true if this and the provided {@link Object} are equal; otherwise false
*/
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Pair<?, ?> other = (Pair<?, ?>) obj;
if (this.left != other.left && (this.left == null || !this.left.equals(other.left))) {
return false;
}
if (this.right != other.right && (this.right == null || !this.right.equals(other.right))) {
return false;
}
return true;
}
}

View File

@@ -10,3 +10,4 @@ org.owasp.dependencycheck.analyzer.NvdCveAnalyzer
org.owasp.dependencycheck.analyzer.VulnerabilitySuppressionAnalyzer
org.owasp.dependencycheck.analyzer.NexusAnalyzer
org.owasp.dependencycheck.analyzer.NuspecAnalyzer
org.owasp.dependencycheck.analyzer.AssemblyAnalyzer

View File

@@ -69,5 +69,6 @@ public class EngineIntegrationTest {
ReportGenerator rg = new ReportGenerator("DependencyCheck",
instance.getDependencies(), instance.getAnalyzers(), dbProp);
rg.generateReports("./target/", "ALL");
instance.cleanup();
}
}

View File

@@ -160,6 +160,8 @@ public class ArchiveAnalyzerTest extends BaseIndexTestCase {
instance.analyze(dependency, engine);
int ending_size = engine.getDependencies().size();
engine.cleanup();
assertTrue(initial_size < ending_size);
} finally {
@@ -186,6 +188,7 @@ public class ArchiveAnalyzerTest extends BaseIndexTestCase {
int initial_size = engine.getDependencies().size();
instance.analyze(dependency, engine);
int ending_size = engine.getDependencies().size();
engine.cleanup();
assertTrue(initial_size < ending_size);
@@ -214,7 +217,7 @@ public class ArchiveAnalyzerTest extends BaseIndexTestCase {
engine.scan(file);
engine.analyzeDependencies();
int ending_size = engine.getDependencies().size();
engine.cleanup();
assertTrue(initial_size < ending_size);
} finally {
@@ -261,7 +264,7 @@ public class ArchiveAnalyzerTest extends BaseIndexTestCase {
engine.scan(file);
engine.analyzeDependencies();
int ending_size = engine.getDependencies().size();
engine.cleanup();
assertTrue(initial_size < ending_size);
} finally {
@@ -292,6 +295,7 @@ public class ArchiveAnalyzerTest extends BaseIndexTestCase {
// }
// assertTrue(failed);
int ending_size = engine.getDependencies().size();
engine.cleanup();
assertEquals(initial_size, ending_size);
} finally {
instance.close();

View File

@@ -59,7 +59,14 @@ public class DriverLoaderTest {
@Test
public void testLoad_String() throws Exception {
String className = "org.h2.Driver";
DriverLoader.load(className);
Driver d = null;
try {
d = DriverLoader.load(className);
} finally {
if (d != null) {
DriverManager.deregisterDriver(d);
}
}
}
/**
@@ -68,7 +75,7 @@ public class DriverLoaderTest {
@Test(expected = DriverLoadException.class)
public void testLoad_String_ex() throws Exception {
String className = "bad.Driver";
DriverLoader.load(className);
Driver d = DriverLoader.load(className);
}
/**
@@ -82,9 +89,16 @@ public class DriverLoaderTest {
File driver = new File(testClassPath, "../../src/test/resources/mysql-connector-java-5.1.27-bin.jar");
assertTrue("MySQL Driver JAR file not found in src/test/resources?", driver.isFile());
DriverLoader.load(className, driver.getAbsolutePath());
Driver d = DriverManager.getDriver("jdbc:mysql://localhost:3306/dependencycheck");
assertNotNull(d);
Driver d = null;
try {
d = DriverLoader.load(className, driver.getAbsolutePath());
d = DriverManager.getDriver("jdbc:mysql://localhost:3306/dependencycheck");
assertNotNull(d);
} finally {
if (d != null) {
DriverManager.deregisterDriver(d);
}
}
}
/**
@@ -99,7 +113,14 @@ public class DriverLoaderTest {
final File dir2 = new File(testClassPath, "../../src/test/resources/");
final String paths = String.format("%s" + File.pathSeparator + "%s", dir1.getAbsolutePath(), dir2.getAbsolutePath());
DriverLoader.load(className, paths);
Driver d = null;
try {
d = DriverLoader.load(className, paths);
} finally {
if (d != null) {
DriverManager.deregisterDriver(d);
}
}
}
/**
@@ -113,7 +134,7 @@ public class DriverLoaderTest {
File driver = new File(testClassPath, "../../src/test/resources/mysql-connector-java-5.1.27-bin.jar");
assertTrue("MySQL Driver JAR file not found in src/test/resources?", driver.isFile());
DriverLoader.load(className, driver.getAbsolutePath());
Driver d = DriverLoader.load(className, driver.getAbsolutePath());
}
/**
@@ -125,6 +146,6 @@ public class DriverLoaderTest {
//we know this is in target/test-classes
File testClassPath = (new File(this.getClass().getClassLoader().getResource("org.mortbay.jetty.jar").getPath())).getParentFile();
File driver = new File(testClassPath, "../../src/test/bad/mysql-connector-java-5.1.27-bin.jar");
DriverLoader.load(className, driver.getAbsolutePath());
Driver d = DriverLoader.load(className, driver.getAbsolutePath());
}
}

View File

@@ -150,6 +150,8 @@ public class ReportGeneratorTest {
ReportGenerator generator = new ReportGenerator("Test Report", engine.getDependencies(), engine.getAnalyzers(), dbProp);
generator.generateReport(templateName, writeTo);
engine.cleanup();
InputStream xsdStream = ReportGenerator.class.getClassLoader().getResourceAsStream("schema/DependencyCheck.xsd");
StreamSource xsdSource = new StreamSource(xsdStream);
StreamSource xmlSource = new StreamSource(new File(writeTo));

View File

@@ -280,30 +280,37 @@ public class DependencyCheckMojo extends AbstractMojo implements MavenMultiPageR
*
* @return the Engine used to scan the dependencies.
*/
private Engine executeDependencyCheck() {
private Engine executeDependencyCheck() throws DatabaseException {
final InputStream in = DependencyCheckMojo.class.getClassLoader().getResourceAsStream(LOG_PROPERTIES_FILE);
LogUtils.prepareLogger(in, logFile);
populateSettings();
final Engine engine = new Engine();
final Set<Artifact> artifacts = project.getArtifacts();
for (Artifact a : artifacts) {
if (skipTestScope && Artifact.SCOPE_TEST.equals(a.getScope())) {
continue;
}
Engine engine = null;
try {
engine = new Engine();
final Set<Artifact> artifacts = project.getArtifacts();
for (Artifact a : artifacts) {
if (skipTestScope && Artifact.SCOPE_TEST.equals(a.getScope())) {
continue;
}
if (skipProvidedScope && Artifact.SCOPE_PROVIDED.equals(a.getScope())) {
continue;
}
if (skipProvidedScope && Artifact.SCOPE_PROVIDED.equals(a.getScope())) {
continue;
}
if (skipRuntimeScope && !Artifact.SCOPE_RUNTIME.equals(a.getScope())) {
continue;
}
if (skipRuntimeScope && !Artifact.SCOPE_RUNTIME.equals(a.getScope())) {
continue;
}
engine.scan(a.getFile().getAbsolutePath());
engine.scan(a.getFile().getAbsolutePath());
}
engine.analyzeDependencies();
} finally {
if (engine != null) {
engine.cleanup();
}
}
engine.analyzeDependencies();
return engine;
}
@@ -794,13 +801,23 @@ public class DependencyCheckMojo extends AbstractMojo implements MavenMultiPageR
* @throws MojoFailureException thrown if a CVSS score is found that is higher then the configured level
*/
public void execute() throws MojoExecutionException, MojoFailureException {
final Engine engine = executeDependencyCheck();
generateExternalReports(engine);
if (this.showSummary) {
showSummary(engine.getDependencies());
}
if (this.failBuildOnCVSS <= 10) {
checkForFailure(engine.getDependencies());
Engine engine = null;
try {
engine = executeDependencyCheck();
generateExternalReports(engine);
if (this.showSummary) {
showSummary(engine.getDependencies());
}
if (this.failBuildOnCVSS <= 10) {
checkForFailure(engine.getDependencies());
}
} catch (DatabaseException ex) {
Logger.getLogger(DependencyCheckMojo.class.getName()).log(Level.SEVERE, "Unable to connect to the dependency-check database; analysis has stopped");
Logger.getLogger(DependencyCheckMojo.class.getName()).log(Level.FINE, "", ex);
} finally {
if (engine != null) {
engine.cleanup();
}
}
}
@@ -825,8 +842,18 @@ public class DependencyCheckMojo extends AbstractMojo implements MavenMultiPageR
* @throws MavenReportException if a maven report exception occurs
*/
public void generate(Sink sink, SinkFactory sinkFactory, Locale locale) throws MavenReportException {
final Engine engine = executeDependencyCheck();
generateMavenSiteReport(engine, sink);
Engine engine = null;
try {
engine = executeDependencyCheck();
generateMavenSiteReport(engine, sink);
} catch (DatabaseException ex) {
Logger.getLogger(DependencyCheckMojo.class.getName()).log(Level.SEVERE, "Unable to connect to the dependency-check database; analysis has stopped");
Logger.getLogger(DependencyCheckMojo.class.getName()).log(Level.FINE, "", ex);
} finally {
if (engine != null) {
engine.cleanup();
}
}
}
// <editor-fold defaultstate="collapsed" desc="required setter/getter methods">