mirror of
https://github.com/ysoftdevs/DependencyCheck.git
synced 2026-01-14 07:43:40 +01:00
Merge branch 'master' into swift_support
This commit is contained in:
18
.github/issue_template.md
vendored
Normal file
18
.github/issue_template.md
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
### Reporting Bugs/Errors
|
||||
When reporting errors, 99% of the time log file output is required. Please post the log file as a [gist](https://gist.github.com/) and provide a link in the new issue.
|
||||
|
||||
### Reporting False Positives
|
||||
When reporting a false positive please include:
|
||||
- The location of the dependency (Maven GAV, URL to download the dependency, etc.)
|
||||
- The CPE that is believed to be false positive
|
||||
- Please report the CPE not the CVE
|
||||
|
||||
#### Example
|
||||
False positive on library foo.jar - reported as cpe:/a:apache:tomcat:7.0
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>org.sample</groupId>
|
||||
<artifactId>foo</artifactId>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
```
|
||||
@@ -20,7 +20,7 @@ Copyright (c) 2013 - Jeremy Long. All Rights Reserved.
|
||||
<parent>
|
||||
<groupId>org.owasp</groupId>
|
||||
<artifactId>dependency-check-parent</artifactId>
|
||||
<version>1.4.1-SNAPSHOT</version>
|
||||
<version>1.4.3-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>dependency-check-ant</artifactId>
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
package org.owasp.dependencycheck.taskdefs;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import org.apache.tools.ant.BuildException;
|
||||
import org.apache.tools.ant.Project;
|
||||
@@ -32,9 +31,12 @@ import org.owasp.dependencycheck.Engine;
|
||||
import org.owasp.dependencycheck.data.nvdcve.CveDB;
|
||||
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
|
||||
import org.owasp.dependencycheck.data.nvdcve.DatabaseProperties;
|
||||
import org.owasp.dependencycheck.data.update.exception.UpdateException;
|
||||
import org.owasp.dependencycheck.dependency.Dependency;
|
||||
import org.owasp.dependencycheck.dependency.Identifier;
|
||||
import org.owasp.dependencycheck.dependency.Vulnerability;
|
||||
import org.owasp.dependencycheck.exception.ExceptionCollection;
|
||||
import org.owasp.dependencycheck.exception.ReportException;
|
||||
import org.owasp.dependencycheck.reporting.ReportGenerator;
|
||||
import org.owasp.dependencycheck.reporting.ReportGenerator.Format;
|
||||
import org.owasp.dependencycheck.utils.Settings;
|
||||
@@ -806,52 +808,67 @@ public class Check extends Update {
|
||||
engine = new Engine(Check.class.getClassLoader());
|
||||
if (isUpdateOnly()) {
|
||||
log("Deprecated 'UpdateOnly' property set; please use the UpdateTask instead", Project.MSG_WARN);
|
||||
engine.doUpdates();
|
||||
} else {
|
||||
try {
|
||||
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.doUpdates();
|
||||
} catch (UpdateException ex) {
|
||||
if (this.isFailOnError()) {
|
||||
throw new BuildException(ex);
|
||||
}
|
||||
log(ex.getMessage(), Project.MSG_ERR);
|
||||
}
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
engine.analyzeDependencies();
|
||||
DatabaseProperties prop = null;
|
||||
CveDB cve = null;
|
||||
try {
|
||||
cve = new CveDB();
|
||||
cve.open();
|
||||
prop = cve.getDatabaseProperties();
|
||||
} catch (DatabaseException ex) {
|
||||
log("Unable to retrieve DB Properties", ex, Project.MSG_DEBUG);
|
||||
} finally {
|
||||
if (cve != null) {
|
||||
cve.close();
|
||||
}
|
||||
} catch (ExceptionCollection ex) {
|
||||
if (this.isFailOnError()) {
|
||||
throw new BuildException(ex);
|
||||
}
|
||||
final ReportGenerator reporter = new ReportGenerator(getProjectName(), engine.getDependencies(), engine.getAnalyzers(), prop);
|
||||
reporter.generateReports(reportOutputDirectory, reportFormat);
|
||||
}
|
||||
DatabaseProperties prop = null;
|
||||
CveDB cve = null;
|
||||
try {
|
||||
cve = new CveDB();
|
||||
cve.open();
|
||||
prop = cve.getDatabaseProperties();
|
||||
} catch (DatabaseException ex) {
|
||||
log("Unable to retrieve DB Properties", ex, Project.MSG_DEBUG);
|
||||
} finally {
|
||||
if (cve != null) {
|
||||
cve.close();
|
||||
}
|
||||
}
|
||||
final ReportGenerator reporter = new ReportGenerator(getProjectName(), engine.getDependencies(), engine.getAnalyzers(), prop);
|
||||
reporter.generateReports(reportOutputDirectory, reportFormat);
|
||||
|
||||
if (this.failBuildOnCVSS <= 10) {
|
||||
checkForFailure(engine.getDependencies());
|
||||
}
|
||||
if (this.showSummary) {
|
||||
showSummary(engine.getDependencies());
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
log("Unable to generate dependency-check report", ex, Project.MSG_DEBUG);
|
||||
throw new BuildException("Unable to generate dependency-check report", ex);
|
||||
} catch (Exception ex) {
|
||||
log("An exception occurred; unable to continue task", ex, Project.MSG_DEBUG);
|
||||
throw new BuildException("An exception occurred; unable to continue task", ex);
|
||||
if (this.failBuildOnCVSS <= 10) {
|
||||
checkForFailure(engine.getDependencies());
|
||||
}
|
||||
if (this.showSummary) {
|
||||
showSummary(engine.getDependencies());
|
||||
}
|
||||
}
|
||||
} catch (DatabaseException ex) {
|
||||
log("Unable to connect to the dependency-check database; analysis has stopped", ex, Project.MSG_ERR);
|
||||
final String msg = "Unable to connect to the dependency-check database; analysis has stopped";
|
||||
if (this.isFailOnError()) {
|
||||
throw new BuildException(msg, ex);
|
||||
}
|
||||
log(msg, ex, Project.MSG_ERR);
|
||||
} catch (ReportException ex) {
|
||||
final String msg = "Unable to generate the dependency-check report";
|
||||
if (this.isFailOnError()) {
|
||||
throw new BuildException(msg, ex);
|
||||
}
|
||||
log(msg, ex, Project.MSG_ERR);
|
||||
} finally {
|
||||
Settings.cleanup(true);
|
||||
if (engine != null) {
|
||||
|
||||
@@ -71,6 +71,30 @@ public class Purge extends Task {
|
||||
this.dataDirectory = dataDirectory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if dependency-check should fail the build if an exception
|
||||
* occurs.
|
||||
*/
|
||||
private boolean failOnError = true;
|
||||
|
||||
/**
|
||||
* Get the value of failOnError.
|
||||
*
|
||||
* @return the value of failOnError
|
||||
*/
|
||||
public boolean isFailOnError() {
|
||||
return failOnError;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of failOnError.
|
||||
*
|
||||
* @param failOnError new value of failOnError
|
||||
*/
|
||||
public void setFailOnError(boolean failOnError) {
|
||||
this.failOnError = failOnError;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() throws BuildException {
|
||||
populateSettings();
|
||||
@@ -81,30 +105,49 @@ public class Purge extends Task {
|
||||
if (db.delete()) {
|
||||
log("Database file purged; local copy of the NVD has been removed", Project.MSG_INFO);
|
||||
} else {
|
||||
log(String.format("Unable to delete '%s'; please delete the file manually", db.getAbsolutePath()), Project.MSG_ERR);
|
||||
final String msg = String.format("Unable to delete '%s'; please delete the file manually", db.getAbsolutePath());
|
||||
if (this.failOnError) {
|
||||
throw new BuildException(msg);
|
||||
}
|
||||
log(msg, Project.MSG_ERR);
|
||||
}
|
||||
} else {
|
||||
log(String.format("Unable to purge database; the database file does not exists: %s", db.getAbsolutePath()), Project.MSG_ERR);
|
||||
final String msg = String.format("Unable to purge database; the database file does not exists: %s", db.getAbsolutePath());
|
||||
if (this.failOnError) {
|
||||
throw new BuildException(msg);
|
||||
}
|
||||
log(msg, Project.MSG_ERR);
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
log("Unable to delete the database", Project.MSG_ERR);
|
||||
final String msg = "Unable to delete the database";
|
||||
if (this.failOnError) {
|
||||
throw new BuildException(msg);
|
||||
}
|
||||
log(msg, Project.MSG_ERR);
|
||||
} finally {
|
||||
Settings.cleanup(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes the properties supplied and updates the dependency-check settings. Additionally, this sets the system properties
|
||||
* required to change the proxy server, port, and connection timeout.
|
||||
* Takes the properties supplied and updates the dependency-check settings.
|
||||
* Additionally, this sets the system properties required to change the
|
||||
* proxy server, port, and connection timeout.
|
||||
*
|
||||
* @throws BuildException thrown if the properties file cannot be read.
|
||||
*/
|
||||
protected void populateSettings() {
|
||||
protected void populateSettings() throws BuildException {
|
||||
Settings.initialize();
|
||||
InputStream taskProperties = null;
|
||||
try {
|
||||
taskProperties = this.getClass().getClassLoader().getResourceAsStream(PROPERTIES_FILE);
|
||||
Settings.mergeProperties(taskProperties);
|
||||
} catch (IOException ex) {
|
||||
log("Unable to load the dependency-check ant task.properties file.", ex, Project.MSG_WARN);
|
||||
final String msg = "Unable to load the dependency-check ant task.properties file.";
|
||||
if (this.failOnError) {
|
||||
throw new BuildException(msg, ex);
|
||||
}
|
||||
log(msg, ex, Project.MSG_WARN);
|
||||
} finally {
|
||||
if (taskProperties != null) {
|
||||
try {
|
||||
|
||||
@@ -18,14 +18,17 @@
|
||||
package org.owasp.dependencycheck.taskdefs;
|
||||
|
||||
import org.apache.tools.ant.BuildException;
|
||||
import org.apache.tools.ant.Project;
|
||||
import org.owasp.dependencycheck.Engine;
|
||||
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
|
||||
import org.owasp.dependencycheck.data.update.exception.UpdateException;
|
||||
import org.owasp.dependencycheck.utils.Settings;
|
||||
import org.slf4j.impl.StaticLoggerBinder;
|
||||
|
||||
/**
|
||||
* An Ant task definition to execute dependency-check update. This will download the latest data from the National Vulnerability
|
||||
* Database (NVD) and store a copy in the local database.
|
||||
* An Ant task definition to execute dependency-check update. This will download
|
||||
* the latest data from the National Vulnerability Database (NVD) and store a
|
||||
* copy in the local database.
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@@ -381,10 +384,11 @@ public class Update extends Purge {
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the update by initializing the settings, downloads the NVD XML data, and then processes the data storing it in the
|
||||
* local database.
|
||||
* Executes the update by initializing the settings, downloads the NVD XML
|
||||
* data, and then processes the data storing it in the local database.
|
||||
*
|
||||
* @throws BuildException thrown if a connection to the local database cannot be made.
|
||||
* @throws BuildException thrown if a connection to the local database
|
||||
* cannot be made.
|
||||
*/
|
||||
@Override
|
||||
public void execute() throws BuildException {
|
||||
@@ -392,9 +396,20 @@ public class Update extends Purge {
|
||||
Engine engine = null;
|
||||
try {
|
||||
engine = new Engine(Update.class.getClassLoader());
|
||||
engine.doUpdates();
|
||||
try {
|
||||
engine.doUpdates();
|
||||
} catch (UpdateException ex) {
|
||||
if (this.isFailOnError()) {
|
||||
throw new BuildException(ex);
|
||||
}
|
||||
log(ex.getMessage(), Project.MSG_ERR);
|
||||
}
|
||||
} catch (DatabaseException ex) {
|
||||
throw new BuildException("Unable to connect to the dependency-check database; unable to update the NVD data", ex);
|
||||
final String msg = "Unable to connect to the dependency-check database; unable to update the NVD data";
|
||||
if (this.isFailOnError()) {
|
||||
throw new BuildException(msg, ex);
|
||||
}
|
||||
log(msg, Project.MSG_ERR);
|
||||
} finally {
|
||||
Settings.cleanup(true);
|
||||
if (engine != null) {
|
||||
@@ -404,8 +419,9 @@ public class Update extends Purge {
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes the properties supplied and updates the dependency-check settings. Additionally, this sets the system properties
|
||||
* required to change the proxy server, port, and connection timeout.
|
||||
* Takes the properties supplied and updates the dependency-check settings.
|
||||
* Additionally, this sets the system properties required to change the
|
||||
* proxy server, port, and connection timeout.
|
||||
*
|
||||
* @throws BuildException thrown when an invalid setting is configured.
|
||||
*/
|
||||
|
||||
@@ -14,6 +14,7 @@ Configuration: dependency-check-purge Task
|
||||
--------------------
|
||||
The following properties can be set on the dependency-check-purge task.
|
||||
|
||||
Property | Description | Default Value
|
||||
----------------------|----------------------------------------------------------------|------------------
|
||||
dataDirectory | Data directory that is used to store the local copy of the NVD | data
|
||||
Property | Description | Default Value
|
||||
----------------------|------------------------------------------------------------------------|------------------
|
||||
dataDirectory | Data directory that is used to store the local copy of the NVD | data
|
||||
failOnError | Whether the build should fail if there is an error executing the purge | true
|
||||
|
||||
@@ -24,6 +24,7 @@ proxyPort | The Proxy Port. |
|
||||
proxyUsername | Defines the proxy user name. |
|
||||
proxyPassword | Defines the proxy password. |
|
||||
connectionTimeout | The URL Connection Timeout. |
|
||||
failOnError | Whether the build should fail if there is an error executing the update | true
|
||||
|
||||
Advanced Configuration
|
||||
====================
|
||||
|
||||
@@ -34,6 +34,7 @@ Property | Description
|
||||
autoUpdate | Sets whether auto-updating of the NVD CVE/CPE data is enabled. It is not recommended that this be turned to false. | true
|
||||
cveValidForHours | Sets the number of hours to wait before checking for new updates from the NVD | 4
|
||||
failBuildOnCVSS | Specifies if the build should be failed if a CVSS score above a specified level is identified. The default is 11 which means since the CVSS scores are 0-10, by default the build will never fail. | 11
|
||||
failOnError | Whether the build should fail if there is an error executing the dependency-check analysis | true
|
||||
projectName | The name of the project being scanned. | Dependency-Check
|
||||
reportFormat | The report format to be generated (HTML, XML, VULN, ALL). This configuration option has no affect if using this within the Site plugin unless the externalReport is set to true. | HTML
|
||||
reportOutputDirectory | The location to write the report(s). Note, this is not used if generating the report as part of a `mvn site` build | 'target'
|
||||
|
||||
@@ -20,7 +20,7 @@ Copyright (c) 2012 - Jeremy Long. All Rights Reserved.
|
||||
<parent>
|
||||
<groupId>org.owasp</groupId>
|
||||
<artifactId>dependency-check-parent</artifactId>
|
||||
<version>1.4.1-SNAPSHOT</version>
|
||||
<version>1.4.3-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>dependency-check-cli</artifactId>
|
||||
|
||||
@@ -37,6 +37,10 @@ import org.owasp.dependencycheck.utils.Settings;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import ch.qos.logback.core.FileAppender;
|
||||
import org.owasp.dependencycheck.data.update.exception.UpdateException;
|
||||
import org.owasp.dependencycheck.exception.ExceptionCollection;
|
||||
import org.owasp.dependencycheck.exception.ReportException;
|
||||
import org.owasp.dependencycheck.utils.InvalidSettingException;
|
||||
import org.slf4j.impl.StaticLoggerBinder;
|
||||
|
||||
/**
|
||||
@@ -57,21 +61,26 @@ public class App {
|
||||
* @param args the command line arguments
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
int exitCode = 0;
|
||||
try {
|
||||
Settings.initialize();
|
||||
final App app = new App();
|
||||
app.run(args);
|
||||
exitCode = app.run(args);
|
||||
LOGGER.debug("Exit code: " + exitCode);
|
||||
} finally {
|
||||
Settings.cleanup(true);
|
||||
}
|
||||
System.exit(exitCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Main CLI entry-point into the application.
|
||||
*
|
||||
* @param args the command line arguments
|
||||
* @return the exit code to return
|
||||
*/
|
||||
public void run(String[] args) {
|
||||
public int run(String[] args) {
|
||||
int exitCode = 0;
|
||||
final CliParser cli = new CliParser();
|
||||
|
||||
try {
|
||||
@@ -79,11 +88,11 @@ public class App {
|
||||
} catch (FileNotFoundException ex) {
|
||||
System.err.println(ex.getMessage());
|
||||
cli.printHelp();
|
||||
return;
|
||||
return -1;
|
||||
} catch (ParseException ex) {
|
||||
System.err.println(ex.getMessage());
|
||||
cli.printHelp();
|
||||
return;
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (cli.getVerboseLog() != null) {
|
||||
@@ -93,8 +102,15 @@ public class App {
|
||||
if (cli.isPurge()) {
|
||||
if (cli.getConnectionString() != null) {
|
||||
LOGGER.error("Unable to purge the database when using a non-default connection string");
|
||||
exitCode = -3;
|
||||
} else {
|
||||
populateSettings(cli);
|
||||
try {
|
||||
populateSettings(cli);
|
||||
} catch (InvalidSettingException ex) {
|
||||
LOGGER.error(ex.getMessage());
|
||||
LOGGER.debug("Error loading properties file", ex);
|
||||
exitCode = -4;
|
||||
}
|
||||
File db;
|
||||
try {
|
||||
db = new File(Settings.getDataDirectory(), "dc.h2.db");
|
||||
@@ -103,46 +119,96 @@ public class App {
|
||||
LOGGER.info("Database file purged; local copy of the NVD has been removed");
|
||||
} else {
|
||||
LOGGER.error("Unable to delete '{}'; please delete the file manually", db.getAbsolutePath());
|
||||
exitCode = -5;
|
||||
}
|
||||
} else {
|
||||
LOGGER.error("Unable to purge database; the database file does not exists: {}", db.getAbsolutePath());
|
||||
exitCode = -6;
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
LOGGER.error("Unable to delete the database");
|
||||
exitCode = -7;
|
||||
}
|
||||
}
|
||||
} else if (cli.isGetVersion()) {
|
||||
cli.printVersionInfo();
|
||||
} else if (cli.isUpdateOnly()) {
|
||||
populateSettings(cli);
|
||||
runUpdateOnly();
|
||||
try {
|
||||
populateSettings(cli);
|
||||
} catch (InvalidSettingException ex) {
|
||||
LOGGER.error(ex.getMessage());
|
||||
LOGGER.debug("Error loading properties file", ex);
|
||||
exitCode = -4;
|
||||
}
|
||||
try {
|
||||
runUpdateOnly();
|
||||
} catch (UpdateException ex) {
|
||||
LOGGER.error(ex.getMessage());
|
||||
exitCode = -8;
|
||||
} catch (DatabaseException ex) {
|
||||
LOGGER.error(ex.getMessage());
|
||||
exitCode = -9;
|
||||
}
|
||||
} else if (cli.isRunScan()) {
|
||||
populateSettings(cli);
|
||||
try {
|
||||
populateSettings(cli);
|
||||
} catch (InvalidSettingException ex) {
|
||||
LOGGER.error(ex.getMessage());
|
||||
LOGGER.debug("Error loading properties file", ex);
|
||||
exitCode = -4;
|
||||
}
|
||||
try {
|
||||
runScan(cli.getReportDirectory(), cli.getReportFormat(), cli.getProjectName(), cli.getScanFiles(),
|
||||
cli.getExcludeList(), cli.getSymLinkDepth());
|
||||
} catch (InvalidScanPathException ex) {
|
||||
LOGGER.error("An invalid scan path was detected; unable to scan '//*' paths");
|
||||
exitCode = -10;
|
||||
} catch (DatabaseException ex) {
|
||||
LOGGER.error(ex.getMessage());
|
||||
exitCode = -11;
|
||||
} catch (ReportException ex) {
|
||||
LOGGER.error(ex.getMessage());
|
||||
exitCode = -12;
|
||||
} catch (ExceptionCollection ex) {
|
||||
if (ex.isFatal()) {
|
||||
exitCode = -13;
|
||||
LOGGER.error("One or more fatal errors occured");
|
||||
} else {
|
||||
exitCode = -14;
|
||||
}
|
||||
for (Throwable e : ex.getExceptions()) {
|
||||
LOGGER.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
cli.printHelp();
|
||||
}
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scans the specified directories and writes the dependency reports to the reportDirectory.
|
||||
* 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 reportDirectory the path to the directory where the reports will
|
||||
* be written
|
||||
* @param outputFormat the output format of the report
|
||||
* @param applicationName the application name for the report
|
||||
* @param files the files/directories to scan
|
||||
* @param excludes the patterns for files/directories to exclude
|
||||
* @param symLinkDepth the depth that symbolic links will be followed
|
||||
*
|
||||
* @throws InvalidScanPathException thrown if the path to scan starts with "//"
|
||||
* @throws InvalidScanPathException thrown if the path to scan starts with
|
||||
* "//"
|
||||
* @throws ReportException thrown when the report cannot be generated
|
||||
* @throws DatabaseException thrown when there is an error connecting to the
|
||||
* database
|
||||
* @throws ExceptionCollection thrown when an exception occurs during
|
||||
* analysis; there may be multiple exceptions contained within the
|
||||
* collection.
|
||||
*/
|
||||
private void runScan(String reportDirectory, String outputFormat, String applicationName, String[] files,
|
||||
String[] excludes, int symLinkDepth) throws InvalidScanPathException {
|
||||
String[] excludes, int symLinkDepth) throws InvalidScanPathException, DatabaseException, ExceptionCollection, ReportException {
|
||||
Engine engine = null;
|
||||
try {
|
||||
engine = new Engine();
|
||||
@@ -174,8 +240,6 @@ public class App {
|
||||
include = "**/*";
|
||||
}
|
||||
}
|
||||
//LOGGER.debug("baseDir: {}", baseDir);
|
||||
//LOGGER.debug("include: {}", include);
|
||||
scanner.setBasedir(baseDir);
|
||||
final String[] includes = {include};
|
||||
scanner.setIncludes(includes);
|
||||
@@ -197,7 +261,15 @@ public class App {
|
||||
}
|
||||
engine.scan(paths);
|
||||
|
||||
engine.analyzeDependencies();
|
||||
ExceptionCollection exCol = null;
|
||||
try {
|
||||
engine.analyzeDependencies();
|
||||
} catch (ExceptionCollection ex) {
|
||||
if (ex.isFatal()) {
|
||||
throw ex;
|
||||
}
|
||||
exCol = ex;
|
||||
}
|
||||
final List<Dependency> dependencies = engine.getDependencies();
|
||||
DatabaseProperties prop = null;
|
||||
CveDB cve = null;
|
||||
@@ -205,8 +277,6 @@ public class App {
|
||||
cve = new CveDB();
|
||||
cve.open();
|
||||
prop = cve.getDatabaseProperties();
|
||||
} catch (DatabaseException ex) {
|
||||
LOGGER.debug("Unable to retrieve DB Properties", ex);
|
||||
} finally {
|
||||
if (cve != null) {
|
||||
cve.close();
|
||||
@@ -215,34 +285,37 @@ public class App {
|
||||
final ReportGenerator report = new ReportGenerator(applicationName, dependencies, engine.getAnalyzers(), prop);
|
||||
try {
|
||||
report.generateReports(reportDirectory, outputFormat);
|
||||
} catch (IOException ex) {
|
||||
LOGGER.error("There was an IO error while attempting to generate the report.");
|
||||
LOGGER.debug("", ex);
|
||||
} catch (Throwable ex) {
|
||||
LOGGER.error("There was an error while attempting to generate the report.");
|
||||
LOGGER.debug("", ex);
|
||||
} catch (ReportException ex) {
|
||||
if (exCol != null) {
|
||||
exCol.addException(ex);
|
||||
throw exCol;
|
||||
} else {
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
if (exCol != null && exCol.getExceptions().size()>0) {
|
||||
throw exCol;
|
||||
}
|
||||
} catch (DatabaseException ex) {
|
||||
LOGGER.error("Unable to connect to the dependency-check database; analysis has stopped");
|
||||
LOGGER.debug("", ex);
|
||||
} finally {
|
||||
if (engine != null) {
|
||||
engine.cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Only executes the update phase of dependency-check.
|
||||
*
|
||||
* @throws UpdateException thrown if there is an error updating
|
||||
* @throws DatabaseException thrown if a fatal error occurred and a
|
||||
* connection to the database could not be established
|
||||
*/
|
||||
private void runUpdateOnly() {
|
||||
private void runUpdateOnly() throws UpdateException, DatabaseException {
|
||||
Engine engine = null;
|
||||
try {
|
||||
engine = new Engine();
|
||||
engine.doUpdates();
|
||||
} catch (DatabaseException ex) {
|
||||
LOGGER.error("Unable to connect to the dependency-check database; analysis has stopped");
|
||||
LOGGER.debug("", ex);
|
||||
} finally {
|
||||
if (engine != null) {
|
||||
engine.cleanup();
|
||||
@@ -253,11 +326,13 @@ public class App {
|
||||
/**
|
||||
* Updates the global Settings.
|
||||
*
|
||||
* @param cli a reference to the CLI Parser that contains the command line arguments used to set the corresponding settings in
|
||||
* the core engine.
|
||||
* @param cli a reference to the CLI Parser that contains the command line
|
||||
* arguments used to set the corresponding settings in the core engine.
|
||||
*
|
||||
* @throws InvalidSettingException thrown when a user defined properties
|
||||
* file is unable to be loaded.
|
||||
*/
|
||||
private void populateSettings(CliParser cli) {
|
||||
|
||||
private void populateSettings(CliParser cli) throws InvalidSettingException {
|
||||
final boolean autoUpdate = cli.isAutoUpdate();
|
||||
final String connectionTimeout = cli.getConnectionTimeout();
|
||||
final String proxyServer = cli.getProxyServer();
|
||||
@@ -286,11 +361,9 @@ public class App {
|
||||
try {
|
||||
Settings.mergeProperties(propertiesFile);
|
||||
} catch (FileNotFoundException ex) {
|
||||
LOGGER.error("Unable to load properties file '{}'", propertiesFile.getPath());
|
||||
LOGGER.debug("", ex);
|
||||
throw new InvalidSettingException("Unable to find properties file '" + propertiesFile.getPath() + "'", ex);
|
||||
} catch (IOException ex) {
|
||||
LOGGER.error("Unable to find properties file '{}'", propertiesFile.getPath());
|
||||
LOGGER.debug("", ex);
|
||||
throw new InvalidSettingException("Error reading properties file '" + propertiesFile.getPath() + "'", ex);
|
||||
}
|
||||
}
|
||||
// We have to wait until we've merged the properties before attempting to set whether we use
|
||||
@@ -385,15 +458,16 @@ public class App {
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a path and resolves it to be a canonical & absolute path. The caveats are that this method will take an Ant style
|
||||
* file selector path (../someDir/**\/*.jar) and convert it to an absolute/canonical path (at least to the left of the first *
|
||||
* or ?).
|
||||
* Takes a path and resolves it to be a canonical & absolute path. The
|
||||
* caveats are that this method will take an Ant style file selector path
|
||||
* (../someDir/**\/*.jar) and convert it to an absolute/canonical path (at
|
||||
* least to the left of the first * or ?).
|
||||
*
|
||||
* @param path the path to canonicalize
|
||||
* @return the canonical path
|
||||
*/
|
||||
protected String ensureCanonicalPath(String path) {
|
||||
String basePath = null;
|
||||
String basePath;
|
||||
String wildCards = null;
|
||||
final String file = path.replace('\\', '/');
|
||||
if (file.contains("*") || file.contains("?")) {
|
||||
|
||||
@@ -966,7 +966,7 @@ public final class CliParser {
|
||||
*/
|
||||
public void printVersionInfo() {
|
||||
final String version = String.format("%s version %s",
|
||||
Settings.getString(Settings.KEYS.APPLICATION_VAME, "dependency-check"),
|
||||
Settings.getString(Settings.KEYS.APPLICATION_NAME, "dependency-check"),
|
||||
Settings.getString(Settings.KEYS.APPLICATION_VERSION, "Unknown"));
|
||||
System.out.println(version);
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
|
||||
<parent>
|
||||
<groupId>org.owasp</groupId>
|
||||
<artifactId>dependency-check-parent</artifactId>
|
||||
<version>1.4.1-SNAPSHOT</version>
|
||||
<version>1.4.3-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>dependency-check-core</artifactId>
|
||||
|
||||
@@ -30,6 +30,8 @@ import org.owasp.dependencycheck.data.update.UpdateService;
|
||||
import org.owasp.dependencycheck.data.update.exception.UpdateException;
|
||||
import org.owasp.dependencycheck.dependency.Dependency;
|
||||
import org.owasp.dependencycheck.exception.NoDataException;
|
||||
import org.owasp.dependencycheck.exception.ExceptionCollection;
|
||||
import org.owasp.dependencycheck.exception.InitializationException;
|
||||
import org.owasp.dependencycheck.utils.InvalidSettingException;
|
||||
import org.owasp.dependencycheck.utils.Settings;
|
||||
import org.slf4j.Logger;
|
||||
@@ -47,8 +49,10 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Scans files, directories, etc. for Dependencies. Analyzers are loaded and used to process the files found by the scan, if a
|
||||
* file is encountered and an Analyzer is associated with the file type then the file is turned into a dependency.
|
||||
* Scans files, directories, etc. for Dependencies. Analyzers are loaded and
|
||||
* used to process the files found by the scan, if a file is encountered and an
|
||||
* Analyzer is associated with the file type then the file is turned into a
|
||||
* dependency.
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@@ -69,7 +73,8 @@ public class Engine implements FileFilter {
|
||||
private final Set<FileTypeAnalyzer> fileTypeAnalyzers = new HashSet<FileTypeAnalyzer>();
|
||||
|
||||
/**
|
||||
* The ClassLoader to use when dynamically loading Analyzer and Update services.
|
||||
* The ClassLoader to use when dynamically loading Analyzer and Update
|
||||
* services.
|
||||
*/
|
||||
private ClassLoader serviceClassLoader = Thread.currentThread().getContextClassLoader();
|
||||
/**
|
||||
@@ -80,7 +85,8 @@ public class Engine implements FileFilter {
|
||||
/**
|
||||
* Creates a new Engine.
|
||||
*
|
||||
* @throws DatabaseException thrown if there is an error connecting to the database
|
||||
* @throws DatabaseException thrown if there is an error connecting to the
|
||||
* database
|
||||
*/
|
||||
public Engine() throws DatabaseException {
|
||||
initializeEngine();
|
||||
@@ -90,7 +96,8 @@ public class Engine implements FileFilter {
|
||||
* Creates a new Engine.
|
||||
*
|
||||
* @param serviceClassLoader a reference the class loader being used
|
||||
* @throws DatabaseException thrown if there is an error connecting to the database
|
||||
* @throws DatabaseException thrown if there is an error connecting to the
|
||||
* database
|
||||
*/
|
||||
public Engine(ClassLoader serviceClassLoader) throws DatabaseException {
|
||||
this.serviceClassLoader = serviceClassLoader;
|
||||
@@ -98,9 +105,11 @@ public class Engine implements FileFilter {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Engine using the specified classloader to dynamically load Analyzer and Update services.
|
||||
* Creates a new Engine using the specified classloader to dynamically load
|
||||
* Analyzer and Update services.
|
||||
*
|
||||
* @throws DatabaseException thrown if there is an error connecting to the database
|
||||
* @throws DatabaseException thrown if there is an error connecting to the
|
||||
* database
|
||||
*/
|
||||
protected final void initializeEngine() throws DatabaseException {
|
||||
ConnectionFactory.initialize();
|
||||
@@ -115,7 +124,8 @@ public class Engine implements FileFilter {
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the analyzers specified in the configuration file (or system properties).
|
||||
* Loads the analyzers specified in the configuration file (or system
|
||||
* properties).
|
||||
*/
|
||||
private void loadAnalyzers() {
|
||||
if (!analyzers.isEmpty()) {
|
||||
@@ -164,8 +174,9 @@ public class Engine implements FileFilter {
|
||||
}
|
||||
|
||||
/**
|
||||
* Scans an array of files or directories. If a directory is specified, it will be scanned recursively. Any dependencies
|
||||
* identified are added to the dependency collection.
|
||||
* Scans an array of files or directories. If a directory is specified, it
|
||||
* will be scanned recursively. Any dependencies identified are added to the
|
||||
* dependency collection.
|
||||
*
|
||||
* @param paths an array of paths to files or directories to be analyzed
|
||||
* @return the list of dependencies scanned
|
||||
@@ -183,8 +194,9 @@ public class Engine implements FileFilter {
|
||||
}
|
||||
|
||||
/**
|
||||
* Scans a given file or directory. If a directory is specified, it will be scanned recursively. Any dependencies identified
|
||||
* are added to the dependency collection.
|
||||
* Scans a given file or directory. If a directory is specified, it will be
|
||||
* scanned recursively. Any dependencies identified are added to the
|
||||
* dependency collection.
|
||||
*
|
||||
* @param path the path to a file or directory to be analyzed
|
||||
* @return the list of dependencies scanned
|
||||
@@ -195,8 +207,9 @@ public class Engine implements FileFilter {
|
||||
}
|
||||
|
||||
/**
|
||||
* Scans an array of files or directories. If a directory is specified, it will be scanned recursively. Any dependencies
|
||||
* identified are added to the dependency collection.
|
||||
* Scans an array of files or directories. If a directory is specified, it
|
||||
* will be scanned recursively. Any dependencies identified are added to the
|
||||
* dependency collection.
|
||||
*
|
||||
* @param files an array of paths to files or directories to be analyzed.
|
||||
* @return the list of dependencies
|
||||
@@ -214,8 +227,9 @@ public class Engine implements FileFilter {
|
||||
}
|
||||
|
||||
/**
|
||||
* Scans a collection of files or directories. If a directory is specified, it will be scanned recursively. Any dependencies
|
||||
* identified are added to the dependency collection.
|
||||
* Scans a collection of files or directories. If a directory is specified,
|
||||
* it will be scanned recursively. Any dependencies identified are added to
|
||||
* the dependency collection.
|
||||
*
|
||||
* @param files a set of paths to files or directories to be analyzed
|
||||
* @return the list of dependencies scanned
|
||||
@@ -233,8 +247,9 @@ public class Engine implements FileFilter {
|
||||
}
|
||||
|
||||
/**
|
||||
* Scans a given file or directory. If a directory is specified, it will be scanned recursively. Any dependencies identified
|
||||
* are added to the dependency collection.
|
||||
* Scans a given file or directory. If a directory is specified, it will be
|
||||
* scanned recursively. Any dependencies identified are added to the
|
||||
* dependency collection.
|
||||
*
|
||||
* @param file the path to a file or directory to be analyzed
|
||||
* @return the list of dependencies scanned
|
||||
@@ -257,7 +272,8 @@ public class Engine implements FileFilter {
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively scans files and directories. Any dependencies identified are added to the dependency collection.
|
||||
* Recursively scans files and directories. Any dependencies identified are
|
||||
* added to the dependency collection.
|
||||
*
|
||||
* @param dir the directory to scan
|
||||
* @return the list of Dependency objects scanned
|
||||
@@ -282,7 +298,8 @@ public class Engine implements FileFilter {
|
||||
}
|
||||
|
||||
/**
|
||||
* Scans a specified file. If a dependency is identified it is added to the dependency collection.
|
||||
* Scans a specified file. If a dependency is identified it is added to the
|
||||
* dependency collection.
|
||||
*
|
||||
* @param file The file to scan
|
||||
* @return the scanned dependency
|
||||
@@ -301,20 +318,38 @@ public class Engine implements FileFilter {
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the analyzers against all of the dependencies. Since the mutable dependencies list is exposed via
|
||||
* {@link #getDependencies()}, this method iterates over a copy of the dependencies list. Thus, the potential for
|
||||
* {@link java.util.ConcurrentModificationException}s is avoided, and analyzers may safely add or remove entries from the
|
||||
* dependencies list.
|
||||
* Runs the analyzers against all of the dependencies. Since the mutable
|
||||
* dependencies list is exposed via {@link #getDependencies()}, this method
|
||||
* iterates over a copy of the dependencies list. Thus, the potential for
|
||||
* {@link java.util.ConcurrentModificationException}s is avoided, and
|
||||
* analyzers may safely add or remove entries from the dependencies list.
|
||||
*
|
||||
* Every effort is made to complete analysis on the dependencies. In some
|
||||
* cases an exception will occur with part of the analysis being performed
|
||||
* which may not affect the entire analysis. If an exception occurs it will
|
||||
* be included in the thrown exception collection.
|
||||
*
|
||||
* @throws ExceptionCollection a collections of any exceptions that occurred
|
||||
* during analysis
|
||||
*/
|
||||
public void analyzeDependencies() {
|
||||
public void analyzeDependencies() throws ExceptionCollection {
|
||||
final List<Throwable> exceptions = new ArrayList<Throwable>();
|
||||
boolean autoUpdate = true;
|
||||
try {
|
||||
autoUpdate = Settings.getBoolean(Settings.KEYS.AUTO_UPDATE);
|
||||
} catch (InvalidSettingException ex) {
|
||||
LOGGER.debug("Invalid setting for auto-update; using true.");
|
||||
exceptions.add(ex);
|
||||
}
|
||||
if (autoUpdate) {
|
||||
doUpdates();
|
||||
try {
|
||||
doUpdates();
|
||||
} catch (UpdateException ex) {
|
||||
exceptions.add(ex);
|
||||
LOGGER.warn("Unable to update Cached Web DataSource, using local "
|
||||
+ "data instead. Results may not include recent vulnerabilities.");
|
||||
LOGGER.debug("Update Error", ex);
|
||||
}
|
||||
}
|
||||
|
||||
//need to ensure that data exists
|
||||
@@ -323,12 +358,13 @@ public class Engine implements FileFilter {
|
||||
} catch (NoDataException ex) {
|
||||
LOGGER.error("{}\n\nUnable to continue dependency-check analysis.", ex.getMessage());
|
||||
LOGGER.debug("", ex);
|
||||
return;
|
||||
exceptions.add(ex);
|
||||
throw new ExceptionCollection("Unable to continue dependency-check analysis.", exceptions, true);
|
||||
} catch (DatabaseException ex) {
|
||||
LOGGER.error("{}\n\nUnable to continue dependency-check analysis.", ex.getMessage());
|
||||
LOGGER.debug("", ex);
|
||||
return;
|
||||
|
||||
exceptions.add(ex);
|
||||
throw new ExceptionCollection("Unable to connect to the dependency-check database", exceptions, true);
|
||||
}
|
||||
|
||||
LOGGER.debug("\n----------------------------------------------------\nBEGIN ANALYSIS\n----------------------------------------------------");
|
||||
@@ -340,7 +376,12 @@ public class Engine implements FileFilter {
|
||||
final List<Analyzer> analyzerList = analyzers.get(phase);
|
||||
|
||||
for (Analyzer a : analyzerList) {
|
||||
a = initializeAnalyzer(a);
|
||||
try {
|
||||
a = initializeAnalyzer(a);
|
||||
} catch (InitializationException ex) {
|
||||
exceptions.add(ex);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* need to create a copy of the collection because some of the
|
||||
* analyzers may modify it. This prevents ConcurrentModificationExceptions.
|
||||
@@ -361,10 +402,12 @@ public class Engine implements FileFilter {
|
||||
} catch (AnalysisException ex) {
|
||||
LOGGER.warn("An error occurred while analyzing '{}'.", d.getActualFilePath());
|
||||
LOGGER.debug("", ex);
|
||||
exceptions.add(ex);
|
||||
} catch (Throwable ex) {
|
||||
//final AnalysisException ax = new AnalysisException(axMsg, ex);
|
||||
LOGGER.warn("An unexpected error occurred during analysis of '{}'", d.getActualFilePath());
|
||||
LOGGER.debug("", ex);
|
||||
exceptions.add(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -380,6 +423,9 @@ public class Engine implements FileFilter {
|
||||
|
||||
LOGGER.debug("\n----------------------------------------------------\nEND ANALYSIS\n----------------------------------------------------");
|
||||
LOGGER.info("Analysis Complete ({} ms)", System.currentTimeMillis() - analysisStart);
|
||||
if (exceptions.size() > 0) {
|
||||
throw new ExceptionCollection("One or more exceptions occured during dependency-check analysis", exceptions);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -387,12 +433,14 @@ public class Engine implements FileFilter {
|
||||
*
|
||||
* @param analyzer the analyzer to initialize
|
||||
* @return the initialized analyzer
|
||||
* @throws InitializationException thrown when there is a problem
|
||||
* initializing the analyzer
|
||||
*/
|
||||
protected Analyzer initializeAnalyzer(Analyzer analyzer) {
|
||||
protected Analyzer initializeAnalyzer(Analyzer analyzer) throws InitializationException {
|
||||
try {
|
||||
LOGGER.debug("Initializing {}", analyzer.getName());
|
||||
analyzer.initialize();
|
||||
} catch (Throwable ex) {
|
||||
} catch (InitializationException ex) {
|
||||
LOGGER.error("Exception occurred initializing {}.", analyzer.getName());
|
||||
LOGGER.debug("", ex);
|
||||
try {
|
||||
@@ -400,6 +448,16 @@ public class Engine implements FileFilter {
|
||||
} catch (Throwable ex1) {
|
||||
LOGGER.trace("", ex1);
|
||||
}
|
||||
throw ex;
|
||||
} catch (Throwable ex) {
|
||||
LOGGER.error("Unexpected exception occurred initializing {}.", analyzer.getName());
|
||||
LOGGER.debug("", ex);
|
||||
try {
|
||||
analyzer.close();
|
||||
} catch (Throwable ex1) {
|
||||
LOGGER.trace("", ex1);
|
||||
}
|
||||
throw new InitializationException("Unexpected Exception", ex);
|
||||
}
|
||||
return analyzer;
|
||||
}
|
||||
@@ -419,28 +477,26 @@ public class Engine implements FileFilter {
|
||||
}
|
||||
|
||||
/**
|
||||
* Cycles through the cached web data sources and calls update on all of them.
|
||||
* Cycles through the cached web data sources and calls update on all of
|
||||
* them.
|
||||
*
|
||||
* @throws UpdateException thrown if the operation fails
|
||||
*/
|
||||
public void doUpdates() {
|
||||
public void doUpdates() throws UpdateException {
|
||||
LOGGER.info("Checking for updates");
|
||||
final long updateStart = System.currentTimeMillis();
|
||||
final UpdateService service = new UpdateService(serviceClassLoader);
|
||||
final Iterator<CachedWebDataSource> iterator = service.getDataSources();
|
||||
while (iterator.hasNext()) {
|
||||
final CachedWebDataSource source = iterator.next();
|
||||
try {
|
||||
source.update();
|
||||
} catch (UpdateException ex) {
|
||||
LOGGER.warn(
|
||||
"Unable to update Cached Web DataSource, using local data instead. Results may not include recent vulnerabilities.");
|
||||
LOGGER.debug("Unable to update details for {}", source.getClass().getName(), ex);
|
||||
}
|
||||
source.update();
|
||||
}
|
||||
LOGGER.info("Check for updates complete ({} ms)", System.currentTimeMillis() - updateStart);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a full list of all of the analyzers. This is useful for reporting which analyzers where used.
|
||||
* Returns a full list of all of the analyzers. This is useful for reporting
|
||||
* which analyzers where used.
|
||||
*
|
||||
* @return a list of Analyzers
|
||||
*/
|
||||
@@ -457,7 +513,8 @@ public class Engine implements FileFilter {
|
||||
* Checks all analyzers to see if an extension is supported.
|
||||
*
|
||||
* @param file a file extension
|
||||
* @return true or false depending on whether or not the file extension is supported
|
||||
* @return true or false depending on whether or not the file extension is
|
||||
* supported
|
||||
*/
|
||||
@Override
|
||||
public boolean accept(File file) {
|
||||
@@ -483,10 +540,12 @@ public class Engine implements FileFilter {
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the CPE Index to ensure documents exists. If none exist a NoDataException is thrown.
|
||||
* Checks the CPE Index to ensure documents exists. If none exist a
|
||||
* NoDataException is thrown.
|
||||
*
|
||||
* @throws NoDataException thrown if no data exists in the CPE Index
|
||||
* @throws DatabaseException thrown if there is an exception opening the database
|
||||
* @throws DatabaseException thrown if there is an exception opening the
|
||||
* database
|
||||
*/
|
||||
private void ensureDataExists() throws NoDataException, DatabaseException {
|
||||
final CveDB cve = new CveDB();
|
||||
|
||||
@@ -27,6 +27,7 @@ import org.owasp.dependencycheck.data.nvdcve.DatabaseProperties;
|
||||
import org.owasp.dependencycheck.dependency.Dependency;
|
||||
import org.owasp.dependencycheck.dependency.Identifier;
|
||||
import org.owasp.dependencycheck.dependency.Vulnerability;
|
||||
import org.owasp.dependencycheck.exception.ExceptionCollection;
|
||||
import org.owasp.dependencycheck.exception.ScanAgentException;
|
||||
import org.owasp.dependencycheck.reporting.ReportGenerator;
|
||||
import org.owasp.dependencycheck.utils.Settings;
|
||||
@@ -34,10 +35,12 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* This class provides a way to easily conduct a scan solely based on existing evidence metadata rather than collecting evidence
|
||||
* from the files themselves. This class is based on the Ant task and Maven plugin with the exception that it takes a list of
|
||||
* dependencies that can be programmatically added from data in a spreadsheet, database or some other datasource and conduct a
|
||||
* scan based on this pre-defined evidence.
|
||||
* This class provides a way to easily conduct a scan solely based on existing
|
||||
* evidence metadata rather than collecting evidence from the files themselves.
|
||||
* This class is based on the Ant task and Maven plugin with the exception that
|
||||
* it takes a list of dependencies that can be programmatically added from data
|
||||
* in a spreadsheet, database or some other datasource and conduct a scan based
|
||||
* on this pre-defined evidence.
|
||||
*
|
||||
* <h2>Example:</h2>
|
||||
* <pre>
|
||||
@@ -138,7 +141,8 @@ public class DependencyCheckScanAgent {
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the destination directory for the generated Dependency-Check report.
|
||||
* Specifies the destination directory for the generated Dependency-Check
|
||||
* report.
|
||||
*/
|
||||
private String reportOutputDirectory;
|
||||
|
||||
@@ -161,9 +165,11 @@ public class DependencyCheckScanAgent {
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies if the build should be failed if a CVSS score above a specified level is identified. The default is 11 which
|
||||
* means since the CVSS scores are 0-10, by default the build will never fail and the CVSS score is set to 11. The valid range
|
||||
* for the fail build on CVSS is 0 to 11, where anything above 10 will not cause the build to fail.
|
||||
* Specifies if the build should be failed if a CVSS score above a specified
|
||||
* level is identified. The default is 11 which means since the CVSS scores
|
||||
* are 0-10, by default the build will never fail and the CVSS score is set
|
||||
* to 11. The valid range for the fail build on CVSS is 0 to 11, where
|
||||
* anything above 10 will not cause the build to fail.
|
||||
*/
|
||||
private float failBuildOnCVSS = 11;
|
||||
|
||||
@@ -186,8 +192,8 @@ public class DependencyCheckScanAgent {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether auto-updating of the NVD CVE/CPE data is enabled. It is not recommended that this be turned to false. Default
|
||||
* is true.
|
||||
* Sets whether auto-updating of the NVD CVE/CPE data is enabled. It is not
|
||||
* recommended that this be turned to false. Default is true.
|
||||
*/
|
||||
private boolean autoUpdate = true;
|
||||
|
||||
@@ -233,8 +239,9 @@ public class DependencyCheckScanAgent {
|
||||
}
|
||||
|
||||
/**
|
||||
* The report format to be generated (HTML, XML, VULN, ALL). This configuration option has no affect if using this within the
|
||||
* Site plugin unless the externalReport is set to true. Default is HTML.
|
||||
* The report format to be generated (HTML, XML, VULN, ALL). This
|
||||
* configuration option has no affect if using this within the Site plugin
|
||||
* unless the externalReport is set to true. Default is HTML.
|
||||
*/
|
||||
private ReportGenerator.Format reportFormat = ReportGenerator.Format.HTML;
|
||||
|
||||
@@ -283,7 +290,9 @@ public class DependencyCheckScanAgent {
|
||||
* Get the value of proxyServer.
|
||||
*
|
||||
* @return the value of proxyServer
|
||||
* @deprecated use {@link org.owasp.dependencycheck.agent.DependencyCheckScanAgent#getProxyServer()} instead
|
||||
* @deprecated use
|
||||
* {@link org.owasp.dependencycheck.agent.DependencyCheckScanAgent#getProxyServer()}
|
||||
* instead
|
||||
*/
|
||||
@Deprecated
|
||||
public String getProxyUrl() {
|
||||
@@ -694,8 +703,8 @@ public class DependencyCheckScanAgent {
|
||||
}
|
||||
|
||||
/**
|
||||
* Additional ZIP File extensions to add analyze. This should be a comma-separated list of file extensions to treat like ZIP
|
||||
* files.
|
||||
* Additional ZIP File extensions to add analyze. This should be a
|
||||
* comma-separated list of file extensions to treat like ZIP files.
|
||||
*/
|
||||
private String zipExtensions;
|
||||
|
||||
@@ -836,11 +845,17 @@ public class DependencyCheckScanAgent {
|
||||
* Executes the Dependency-Check on the dependent libraries.
|
||||
*
|
||||
* @return the Engine used to scan the dependencies.
|
||||
* @throws org.owasp.dependencycheck.data.nvdcve.DatabaseException thrown if there is an exception connecting to the database
|
||||
* @throws ExceptionCollection a collection of one or more exceptions that
|
||||
* occurred during analysis.
|
||||
*/
|
||||
private Engine executeDependencyCheck() throws DatabaseException {
|
||||
private Engine executeDependencyCheck() throws ExceptionCollection {
|
||||
populateSettings();
|
||||
final Engine engine = new Engine();
|
||||
final Engine engine;
|
||||
try {
|
||||
engine = new Engine();
|
||||
} catch (DatabaseException ex) {
|
||||
throw new ExceptionCollection(ex, true);
|
||||
}
|
||||
engine.setDependencies(this.dependencies);
|
||||
engine.analyzeDependencies();
|
||||
return engine;
|
||||
@@ -881,8 +896,9 @@ public class DependencyCheckScanAgent {
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes the properties supplied and updates the dependency-check settings. Additionally, this sets the system properties
|
||||
* required to change the proxy server, port, and connection timeout.
|
||||
* Takes the properties supplied and updates the dependency-check settings.
|
||||
* Additionally, this sets the system properties required to change the
|
||||
* proxy server, port, and connection timeout.
|
||||
*/
|
||||
private void populateSettings() {
|
||||
Settings.initialize();
|
||||
@@ -925,7 +941,8 @@ public class DependencyCheckScanAgent {
|
||||
* Executes the dependency-check and generates the report.
|
||||
*
|
||||
* @return a reference to the engine used to perform the scan.
|
||||
* @throws org.owasp.dependencycheck.exception.ScanAgentException thrown if there is an exception executing the scan.
|
||||
* @throws org.owasp.dependencycheck.exception.ScanAgentException thrown if
|
||||
* there is an exception executing the scan.
|
||||
*/
|
||||
public Engine execute() throws ScanAgentException {
|
||||
Engine engine = null;
|
||||
@@ -940,10 +957,12 @@ public class DependencyCheckScanAgent {
|
||||
if (this.failBuildOnCVSS <= 10) {
|
||||
checkForFailure(engine.getDependencies());
|
||||
}
|
||||
} catch (DatabaseException ex) {
|
||||
LOGGER.error(
|
||||
"Unable to connect to the dependency-check database; analysis has stopped");
|
||||
LOGGER.debug("", ex);
|
||||
} catch (ExceptionCollection ex) {
|
||||
if (ex.isFatal()) {
|
||||
LOGGER.error("A fatal exception occurred during analysis; analysis has stopped. Please see the debug log for more details.");
|
||||
LOGGER.debug("", ex);
|
||||
}
|
||||
throw new ScanAgentException("One or more exceptions occurred during analysis; please see the debug log for more details.", ex);
|
||||
} finally {
|
||||
Settings.cleanup(true);
|
||||
if (engine != null) {
|
||||
@@ -954,11 +973,12 @@ public class DependencyCheckScanAgent {
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if a vulnerability has been identified with a CVSS score that is above the threshold set in the
|
||||
* configuration.
|
||||
* Checks to see if a vulnerability has been identified with a CVSS score
|
||||
* that is above the threshold set in the configuration.
|
||||
*
|
||||
* @param dependencies the list of dependency objects
|
||||
* @throws org.owasp.dependencycheck.exception.ScanAgentException thrown if there is an exception executing the scan.
|
||||
* @throws org.owasp.dependencycheck.exception.ScanAgentException thrown if
|
||||
* there is an exception executing the scan.
|
||||
*/
|
||||
private void checkForFailure(List<Dependency> dependencies) throws ScanAgentException {
|
||||
final StringBuilder ids = new StringBuilder();
|
||||
@@ -986,7 +1006,8 @@ public class DependencyCheckScanAgent {
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a warning message listing a summary of dependencies and their associated CPE and CVE entries.
|
||||
* Generates a warning message listing a summary of dependencies and their
|
||||
* associated CPE and CVE entries.
|
||||
*
|
||||
* @param dependencies a list of dependency objects
|
||||
*/
|
||||
|
||||
@@ -367,7 +367,7 @@ public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
final String archiveExt = FileUtils.getFileExtension(archive.getName()).toLowerCase();
|
||||
try {
|
||||
if (ZIPPABLES.contains(archiveExt)) {
|
||||
BufferedInputStream in = new BufferedInputStream(fis);
|
||||
final BufferedInputStream in = new BufferedInputStream(fis);
|
||||
ensureReadableJar(archiveExt, in);
|
||||
extractArchive(new ZipArchiveInputStream(in), destination, engine);
|
||||
} else if ("tar".equals(archiveExt)) {
|
||||
@@ -413,7 +413,7 @@ public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
private void ensureReadableJar(final String archiveExt, BufferedInputStream in) throws IOException {
|
||||
if ("jar".equals(archiveExt) && in.markSupported()) {
|
||||
in.mark(7);
|
||||
byte[] b = new byte[7];
|
||||
final byte[] b = new byte[7];
|
||||
in.read(b);
|
||||
if (b[0] == '#'
|
||||
&& b[1] == '!'
|
||||
@@ -441,6 +441,8 @@ public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
in.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -574,15 +574,14 @@ public class CPEAnalyzer implements Analyzer {
|
||||
final String url = String.format(NVD_SEARCH_URL, URLEncoder.encode(vs.getName(), "UTF-8"));
|
||||
final IdentifierMatch match = new IdentifierMatch("cpe", vs.getName(), url, IdentifierConfidence.EXACT_MATCH, conf);
|
||||
collected.add(match);
|
||||
} else //TODO the following isn't quite right is it? need to think about this guessing game a bit more.
|
||||
{
|
||||
if (evVer.getVersionParts().size() <= dbVer.getVersionParts().size()
|
||||
&& evVer.matchesAtLeastThreeLevels(dbVer)) {
|
||||
if (bestGuessConf == null || bestGuessConf.compareTo(conf) > 0) {
|
||||
if (bestGuess.getVersionParts().size() < dbVer.getVersionParts().size()) {
|
||||
bestGuess = dbVer;
|
||||
bestGuessConf = conf;
|
||||
}
|
||||
|
||||
//TODO the following isn't quite right is it? need to think about this guessing game a bit more.
|
||||
} else if (evVer.getVersionParts().size() <= dbVer.getVersionParts().size()
|
||||
&& evVer.matchesAtLeastThreeLevels(dbVer)) {
|
||||
if (bestGuessConf == null || bestGuessConf.compareTo(conf) > 0) {
|
||||
if (bestGuess.getVersionParts().size() < dbVer.getVersionParts().size()) {
|
||||
bestGuess = dbVer;
|
||||
bestGuessConf = conf;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,26 +93,27 @@ public class FileNameAnalyzer extends AbstractAnalyzer implements Analyzer {
|
||||
|
||||
//add version evidence
|
||||
final DependencyVersion version = DependencyVersionUtil.parseVersion(fileName);
|
||||
final String packageName = DependencyVersionUtil.parsePreVersion(fileName);
|
||||
if (version != null) {
|
||||
// If the version number is just a number like 2 or 23, reduce the confidence
|
||||
// a shade. This should hopefully correct for cases like log4j.jar or
|
||||
// struts2-core.jar
|
||||
if (version.getVersionParts() == null || version.getVersionParts().size() < 2) {
|
||||
dependency.getVersionEvidence().addEvidence("file", "name",
|
||||
dependency.getVersionEvidence().addEvidence("file", "version",
|
||||
version.toString(), Confidence.MEDIUM);
|
||||
} else {
|
||||
dependency.getVersionEvidence().addEvidence("file", "version",
|
||||
version.toString(), Confidence.HIGHEST);
|
||||
}
|
||||
dependency.getVersionEvidence().addEvidence("file", "name",
|
||||
fileName, Confidence.MEDIUM);
|
||||
packageName, Confidence.MEDIUM);
|
||||
}
|
||||
|
||||
if (!IGNORED_FILES.accept(f)) {
|
||||
dependency.getProductEvidence().addEvidence("file", "name",
|
||||
fileName, Confidence.HIGH);
|
||||
packageName, Confidence.HIGH);
|
||||
dependency.getVendorEvidence().addEvidence("file", "name",
|
||||
fileName, Confidence.HIGH);
|
||||
packageName, Confidence.HIGH);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,6 @@ import org.owasp.dependencycheck.dependency.Dependency;
|
||||
import org.owasp.dependencycheck.dependency.Evidence;
|
||||
import org.owasp.dependencycheck.exception.InitializationException;
|
||||
import org.owasp.dependencycheck.xml.suppression.PropertyType;
|
||||
import org.owasp.dependencycheck.xml.suppression.SuppressionParseException;
|
||||
import org.owasp.dependencycheck.utils.DownloadFailedException;
|
||||
import org.owasp.dependencycheck.utils.Downloader;
|
||||
import org.owasp.dependencycheck.utils.FileUtils;
|
||||
@@ -255,7 +254,7 @@ public class HintAnalyzer extends AbstractAnalyzer implements Analyzer {
|
||||
if (product.contains(zendframeworkProduct)) {
|
||||
dependency.getProductEvidence().addEvidence("hint analyzer", "vendor", "zend_framework", Confidence.HIGHEST);
|
||||
}
|
||||
|
||||
|
||||
//sun/oracle problem
|
||||
final Iterator<Evidence> itr = dependency.getVendorEvidence().iterator();
|
||||
final List<Evidence> newEntries = new ArrayList<Evidence>();
|
||||
@@ -279,7 +278,7 @@ public class HintAnalyzer extends AbstractAnalyzer implements Analyzer {
|
||||
/**
|
||||
* Loads the hint rules file.
|
||||
*
|
||||
* @throws SuppressionParseException thrown if the XML cannot be parsed.
|
||||
* @throws HintParseException thrown if the XML cannot be parsed.
|
||||
*/
|
||||
private void loadHintRules() throws HintParseException {
|
||||
final HintParser parser = new HintParser();
|
||||
@@ -293,7 +292,7 @@ public class HintAnalyzer extends AbstractAnalyzer implements Analyzer {
|
||||
LOGGER.error("Unable to parse the base hint data file");
|
||||
LOGGER.debug("Unable to parse the base hint data file", ex);
|
||||
}
|
||||
final String filePath = Settings.getString(Settings.KEYS.SUPPRESSION_FILE);
|
||||
final String filePath = Settings.getString(Settings.KEYS.HINTS_FILE);
|
||||
if (filePath == null) {
|
||||
return;
|
||||
}
|
||||
@@ -327,7 +326,7 @@ public class HintAnalyzer extends AbstractAnalyzer implements Analyzer {
|
||||
|
||||
if (file != null) {
|
||||
try {
|
||||
Hints newHints = parser.parseHints(file);
|
||||
final Hints newHints = parser.parseHints(file);
|
||||
hints.getHintRules().addAll(newHints.getHintRules());
|
||||
hints.getVendorDuplicatingHintRules().addAll(newHints.getVendorDuplicatingHintRules());
|
||||
LOGGER.debug("{} hint rules were loaded.", hints.getHintRules().size());
|
||||
|
||||
@@ -39,7 +39,6 @@ import java.util.jar.Attributes;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.jar.Manifest;
|
||||
import java.util.logging.Level;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.zip.ZipEntry;
|
||||
import org.apache.commons.compress.utils.IOUtils;
|
||||
@@ -646,9 +645,7 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
* @return whether evidence was identified parsing the manifest
|
||||
* @throws IOException if there is an issue reading the JAR file
|
||||
*/
|
||||
protected boolean parseManifest(Dependency dependency,
|
||||
List<ClassNameInformation> classInformation)
|
||||
throws IOException {
|
||||
protected boolean parseManifest(Dependency dependency, List<ClassNameInformation> classInformation) throws IOException {
|
||||
boolean foundSomething = false;
|
||||
JarFile jar = null;
|
||||
try {
|
||||
@@ -667,7 +664,6 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
final EvidenceCollection vendorEvidence = dependency.getVendorEvidence();
|
||||
final EvidenceCollection productEvidence = dependency.getProductEvidence();
|
||||
final EvidenceCollection versionEvidence = dependency.getVersionEvidence();
|
||||
|
||||
String source = "Manifest";
|
||||
String specificationVersion = null;
|
||||
boolean hasImplementationVersion = false;
|
||||
@@ -689,7 +685,7 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
foundSomething = true;
|
||||
versionEvidence.addEvidence(source, key, value, Confidence.HIGH);
|
||||
} else if ("specification-version".equalsIgnoreCase(key)) {
|
||||
specificationVersion = key;
|
||||
specificationVersion = value;
|
||||
} else if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_VENDOR.toString())) {
|
||||
foundSomething = true;
|
||||
vendorEvidence.addEvidence(source, key, value, Confidence.HIGH);
|
||||
@@ -784,7 +780,6 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (Map.Entry<String, Attributes> item : manifest.getEntries().entrySet()) {
|
||||
final String name = item.getKey();
|
||||
source = "manifest: " + name;
|
||||
|
||||
@@ -53,6 +53,9 @@ import org.slf4j.LoggerFactory;
|
||||
@Experimental
|
||||
public class RubyBundleAuditAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
|
||||
/**
|
||||
* The logger.
|
||||
*/
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(RubyBundleAuditAnalyzer.class);
|
||||
|
||||
/**
|
||||
@@ -151,7 +154,7 @@ public class RubyBundleAuditAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
setEnabled(false);
|
||||
cvedb.close();
|
||||
cvedb = null;
|
||||
String msg = String.format("Exception from bundle-audit process: %s. Disabling %s", ae.getCause(), ANALYZER_NAME);
|
||||
final String msg = String.format("Exception from bundle-audit process: %s. Disabling %s", ae.getCause(), ANALYZER_NAME);
|
||||
throw new InitializationException(msg, ae);
|
||||
} catch (IOException ex) {
|
||||
setEnabled(false);
|
||||
@@ -163,12 +166,12 @@ public class RubyBundleAuditAnalyzer extends AbstractFileTypeAnalyzer {
|
||||
exitValue = process.waitFor();
|
||||
} catch (InterruptedException ex) {
|
||||
setEnabled(false);
|
||||
String msg = String.format("Bundle-audit process was interupted. Disabling %s", ANALYZER_NAME);
|
||||
final String msg = String.format("Bundle-audit process was interupted. Disabling %s", ANALYZER_NAME);
|
||||
throw new InitializationException(msg);
|
||||
}
|
||||
if (0 == exitValue) {
|
||||
setEnabled(false);
|
||||
String msg = String.format("Unexpected exit code from bundle-audit process. Disabling %s: %s", ANALYZER_NAME, exitValue);
|
||||
final String msg = String.format("Unexpected exit code from bundle-audit process. Disabling %s: %s", ANALYZER_NAME, exitValue);
|
||||
throw new InitializationException(msg);
|
||||
} else {
|
||||
BufferedReader reader = null;
|
||||
|
||||
@@ -38,7 +38,6 @@ import org.apache.lucene.search.IndexSearcher;
|
||||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.search.TopDocs;
|
||||
import org.apache.lucene.store.RAMDirectory;
|
||||
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;
|
||||
@@ -48,8 +47,8 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* An in memory lucene index that contains the vendor/product combinations from the CPE (application) identifiers within the NVD
|
||||
* CVE data.
|
||||
* An in memory lucene index that contains the vendor/product combinations from
|
||||
* the CPE (application) identifiers within the NVD CVE data.
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@@ -144,19 +143,6 @@ public final class CpeMemoryIndex {
|
||||
return openState;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the indexing analyzer for the CPE Index.
|
||||
*
|
||||
* @return the CPE Analyzer.
|
||||
* @deprecated the search field analyzer must be used to include the token concatenating filter.
|
||||
*/
|
||||
@Deprecated
|
||||
private Analyzer createIndexingAnalyzer() {
|
||||
final Map<String, Analyzer> fieldAnalyzers = new HashMap<String, Analyzer>();
|
||||
fieldAnalyzers.put(Fields.DOCUMENT_KEY, new KeywordAnalyzer());
|
||||
return new PerFieldAnalyzerWrapper(new FieldAnalyzer(LuceneUtils.CURRENT_VERSION), fieldAnalyzers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an Analyzer for searching the CPE Index.
|
||||
*
|
||||
@@ -275,7 +261,8 @@ public final class CpeMemoryIndex {
|
||||
* @param maxQueryResults the maximum number of documents to return
|
||||
* @return the TopDocs found by the search
|
||||
* @throws ParseException thrown when the searchString is invalid
|
||||
* @throws IOException is thrown if there is an issue with the underlying Index
|
||||
* @throws IOException is thrown if there is an issue with the underlying
|
||||
* Index
|
||||
*/
|
||||
public TopDocs search(String searchString, int maxQueryResults) throws ParseException, IOException {
|
||||
if (searchString == null || searchString.trim().isEmpty()) {
|
||||
|
||||
@@ -34,7 +34,7 @@ import org.apache.lucene.util.Version;
|
||||
* index the CPE fields vendor and product.</p>
|
||||
*
|
||||
* @author Jeremy Long
|
||||
* @Deprecated the field analyzer should not be used, instead use the
|
||||
* @deprecated the field analyzer should not be used, instead use the
|
||||
* SearchFieldAnalyzer so that the token analyzing filter is used.
|
||||
*/
|
||||
@Deprecated
|
||||
|
||||
@@ -68,17 +68,16 @@ public class CveDB {
|
||||
private ResourceBundle statementBundle = null;
|
||||
|
||||
/**
|
||||
* Creates a new CveDB object and opens the database
|
||||
* connection. Note, the connection must be closed by the caller by calling
|
||||
* the close method. ======= Does the underlying connection support batch
|
||||
* operations?
|
||||
* Creates a new CveDB object and opens the database connection. Note, the
|
||||
* connection must be closed by the caller by calling the close method.
|
||||
* ======= Does the underlying connection support batch operations?
|
||||
*/
|
||||
private boolean batchSupported;
|
||||
|
||||
/**
|
||||
* Creates a new CveDB object and opens the database connection. Note, the
|
||||
* connection must be closed by the caller by calling the close method.
|
||||
*
|
||||
*
|
||||
* @throws DatabaseException thrown if there is an exception opening the
|
||||
* database.
|
||||
*/
|
||||
@@ -659,7 +658,7 @@ public class CveDB {
|
||||
+ "If the problem persist try deleting the files in '{}' and running {} again. If the problem continues, please "
|
||||
+ "create a log file (see documentation at http://jeremylong.github.io/DependencyCheck/) and open a ticket at "
|
||||
+ "https://github.com/jeremylong/DependencyCheck/issues and include the log file.\n\n",
|
||||
dd, dd, Settings.getString(Settings.KEYS.APPLICATION_VAME));
|
||||
dd, dd, Settings.getString(Settings.KEYS.APPLICATION_NAME));
|
||||
LOGGER.debug("", ex);
|
||||
} finally {
|
||||
DBUtils.closeResultSet(rs);
|
||||
|
||||
@@ -43,9 +43,10 @@ public class CPEHandler extends DefaultHandler {
|
||||
/**
|
||||
* The Starts with expression to filter CVE entries by CPE.
|
||||
*/
|
||||
private static final String CPE_STARTS_WITH = Settings.getString(Settings.KEYS.CVE_CPE_STARTS_WITH_FILTER,"cpe:/a:");
|
||||
private static final String CPE_STARTS_WITH = Settings.getString(Settings.KEYS.CVE_CPE_STARTS_WITH_FILTER, "cpe:/a:");
|
||||
/**
|
||||
* The text content of the node being processed. This can be used during the end element event.
|
||||
* The text content of the node being processed. This can be used during the
|
||||
* end element event.
|
||||
*/
|
||||
private StringBuilder nodeText = null;
|
||||
/**
|
||||
@@ -77,7 +78,8 @@ public class CPEHandler extends DefaultHandler {
|
||||
* @param localName the local name
|
||||
* @param qName the qualified name
|
||||
* @param attributes the attributes
|
||||
* @throws SAXException thrown if there is an exception processing the element
|
||||
* @throws SAXException thrown if there is an exception processing the
|
||||
* element
|
||||
*/
|
||||
@Override
|
||||
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
|
||||
@@ -128,7 +130,8 @@ public class CPEHandler extends DefaultHandler {
|
||||
* @param ch the char array
|
||||
* @param start the start position of the data read
|
||||
* @param length the length of the data read
|
||||
* @throws SAXException thrown if there is an exception processing the characters
|
||||
* @throws SAXException thrown if there is an exception processing the
|
||||
* characters
|
||||
*/
|
||||
@Override
|
||||
public void characters(char[] ch, int start, int length) throws SAXException {
|
||||
@@ -138,12 +141,14 @@ public class CPEHandler extends DefaultHandler {
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the end element event. Stores the CPE data in the Cve Database if the cpe item node is ending.
|
||||
* Handles the end element event. Stores the CPE data in the Cve Database if
|
||||
* the cpe item node is ending.
|
||||
*
|
||||
* @param uri the element's uri
|
||||
* @param localName the local name
|
||||
* @param qName the qualified name
|
||||
* @throws SAXException thrown if there is an exception processing the element
|
||||
* @throws SAXException thrown if there is an exception processing the
|
||||
* element
|
||||
*/
|
||||
@Override
|
||||
public void endElement(String uri, String localName, String qName) throws SAXException {
|
||||
@@ -182,7 +187,8 @@ public class CPEHandler extends DefaultHandler {
|
||||
|
||||
// <editor-fold defaultstate="collapsed" desc="The Element Class that maintains state information about the current node">
|
||||
/**
|
||||
* A simple class to maintain information about the current element while parsing the CPE XML.
|
||||
* A simple class to maintain information about the current element while
|
||||
* parsing the CPE XML.
|
||||
*/
|
||||
protected static final class Element {
|
||||
|
||||
|
||||
@@ -36,6 +36,9 @@ import org.slf4j.LoggerFactory;
|
||||
*/
|
||||
public class UpdateableNvdCve implements Iterable<NvdCveInfo>, Iterator<NvdCveInfo> {
|
||||
|
||||
/**
|
||||
* A reference to the logger.
|
||||
*/
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(UpdateableNvdCve.class);
|
||||
/**
|
||||
* A collection of sources of data.
|
||||
|
||||
@@ -0,0 +1,214 @@
|
||||
/*
|
||||
* 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) 2016 Jeremy Long. All Rights Reserved.
|
||||
*/
|
||||
package org.owasp.dependencycheck.exception;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A collection of several exceptions.
|
||||
*
|
||||
* @author Jeremy Lomg
|
||||
*/
|
||||
public class ExceptionCollection extends Exception {
|
||||
|
||||
/**
|
||||
* Instantiates a new exception collection.
|
||||
*
|
||||
* @param exceptions a list of exceptions
|
||||
*/
|
||||
public ExceptionCollection(List<Throwable> exceptions) {
|
||||
super();
|
||||
this.exceptions = exceptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new exception collection.
|
||||
*
|
||||
* @param msg the exception message
|
||||
* @param exceptions a list of exceptions
|
||||
*/
|
||||
public ExceptionCollection(String msg, List<Throwable> exceptions) {
|
||||
super(msg);
|
||||
this.exceptions = exceptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new exception collection.
|
||||
*
|
||||
* @param exceptions a list of exceptions
|
||||
* @param fatal indicates if the exception that occurred is fatal - meaning
|
||||
* that no analysis was performed.
|
||||
*/
|
||||
public ExceptionCollection(List<Throwable> exceptions, boolean fatal) {
|
||||
super();
|
||||
this.exceptions = exceptions;
|
||||
this.fatal = fatal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new exception collection.
|
||||
*
|
||||
* @param msg the exception message
|
||||
* @param exceptions a list of exceptions
|
||||
* @param fatal indicates if the exception that occurred is fatal - meaning
|
||||
* that no analysis was performed.
|
||||
*/
|
||||
public ExceptionCollection(String msg, List<Throwable> exceptions, boolean fatal) {
|
||||
super(msg);
|
||||
this.exceptions = exceptions;
|
||||
this.fatal = fatal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new exception collection.
|
||||
*
|
||||
* @param exceptions a list of exceptions
|
||||
* @param fatal indicates if the exception that occurred is fatal - meaning
|
||||
* that no analysis was performed.
|
||||
*/
|
||||
public ExceptionCollection(Throwable exceptions, boolean fatal) {
|
||||
super();
|
||||
this.exceptions = new ArrayList<Throwable>();
|
||||
this.exceptions.add(exceptions);
|
||||
this.fatal = fatal;
|
||||
}
|
||||
/**
|
||||
* Instantiates a new exception collection.
|
||||
*
|
||||
* @param msg the exception message
|
||||
* @param exception a list of exceptions
|
||||
*/
|
||||
public ExceptionCollection(String msg, Throwable exception) {
|
||||
super(msg);
|
||||
this.exceptions = new ArrayList<Throwable>();
|
||||
this.exceptions.add(exception);
|
||||
this.fatal = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new exception collection.
|
||||
*/
|
||||
public ExceptionCollection() {
|
||||
super();
|
||||
this.exceptions = new ArrayList<Throwable>();
|
||||
}
|
||||
/**
|
||||
* The serial version uid.
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* A collection of exceptions.
|
||||
*/
|
||||
private List<Throwable> exceptions;
|
||||
|
||||
/**
|
||||
* Get the value of exceptions.
|
||||
*
|
||||
* @return the value of exceptions
|
||||
*/
|
||||
public List<Throwable> getExceptions() {
|
||||
return exceptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an exception to the collection.
|
||||
*
|
||||
* @param ex the exception to add
|
||||
*/
|
||||
public void addException(Throwable ex) {
|
||||
this.exceptions.add(ex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an exception to the collection.
|
||||
*
|
||||
* @param ex the exception to add
|
||||
* @param fatal flag indicating if this is a fatal error
|
||||
*/
|
||||
public void addException(Throwable ex, boolean fatal) {
|
||||
addException(ex);
|
||||
this.fatal = fatal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flag indicating if a fatal exception occurred that would prevent the
|
||||
* attempt at completing the analysis even if exceptions occurred.
|
||||
*/
|
||||
private boolean fatal = false;
|
||||
|
||||
/**
|
||||
* Get the value of fatal.
|
||||
*
|
||||
* @return the value of fatal
|
||||
*/
|
||||
public boolean isFatal() {
|
||||
return fatal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of fatal.
|
||||
*
|
||||
* @param fatal new value of fatal
|
||||
*/
|
||||
public void setFatal(boolean fatal) {
|
||||
this.fatal = fatal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the stack trace.
|
||||
*
|
||||
* @param s the writer to print to
|
||||
*/
|
||||
@Override
|
||||
public void printStackTrace(PrintWriter s) {
|
||||
s.println("Multiple Exceptions Occured");
|
||||
super.printStackTrace(s);
|
||||
for (Throwable t : this.exceptions) {
|
||||
s.println("Next Exception:");
|
||||
t.printStackTrace(s);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the stack trace.
|
||||
*
|
||||
* @param s the stream to write the stack trace to
|
||||
*/
|
||||
@Override
|
||||
public void printStackTrace(PrintStream s) {
|
||||
s.println("Multiple Exceptions Occured");
|
||||
super.printStackTrace(s);
|
||||
for (Throwable t : this.exceptions) {
|
||||
s.println("Next Exception:");
|
||||
t.printStackTrace(s);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the stack trace to standard error.
|
||||
*/
|
||||
@Override
|
||||
public void printStackTrace() {
|
||||
this.printStackTrace(System.err);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* 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) 2016 Jeremy Long. All Rights Reserved.
|
||||
*/
|
||||
package org.owasp.dependencycheck.exception;
|
||||
|
||||
/**
|
||||
* An exception used when generating reports.
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
public class ReportException extends Exception {
|
||||
|
||||
/**
|
||||
* The serial version uid.
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* Creates a new ReportException.
|
||||
*/
|
||||
public ReportException() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new ReportException.
|
||||
*
|
||||
* @param msg a message for the exception.
|
||||
*/
|
||||
public ReportException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new ReportException.
|
||||
*
|
||||
* @param ex the cause of the exception.
|
||||
*/
|
||||
public ReportException(Throwable ex) {
|
||||
super(ex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new ReportException.
|
||||
*
|
||||
* @param msg a message for the exception.
|
||||
* @param ex the cause of the exception.
|
||||
*/
|
||||
public ReportException(String msg, Throwable ex) {
|
||||
super(msg, ex);
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,7 @@ import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
@@ -37,13 +38,16 @@ import org.apache.velocity.runtime.RuntimeConstants;
|
||||
import org.owasp.dependencycheck.analyzer.Analyzer;
|
||||
import org.owasp.dependencycheck.data.nvdcve.DatabaseProperties;
|
||||
import org.owasp.dependencycheck.dependency.Dependency;
|
||||
import org.owasp.dependencycheck.exception.ReportException;
|
||||
import org.owasp.dependencycheck.utils.Settings;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The ReportGenerator is used to, as the name implies, generate reports. Internally the generator uses the Velocity
|
||||
* Templating Engine. The ReportGenerator exposes a list of Dependencies to the template when generating the report.
|
||||
* The ReportGenerator is used to, as the name implies, generate reports.
|
||||
* Internally the generator uses the Velocity Templating Engine. The
|
||||
* ReportGenerator exposes a list of Dependencies to the template when
|
||||
* generating the report.
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@@ -79,7 +83,7 @@ public class ReportGenerator {
|
||||
/**
|
||||
* The Velocity Engine.
|
||||
*/
|
||||
private final VelocityEngine engine;
|
||||
private final VelocityEngine velocityEngine;
|
||||
/**
|
||||
* The Velocity Engine Context.
|
||||
*/
|
||||
@@ -91,13 +95,14 @@ public class ReportGenerator {
|
||||
* @param applicationName the application name being analyzed
|
||||
* @param dependencies the list of dependencies
|
||||
* @param analyzers the list of analyzers used
|
||||
* @param properties the database properties (containing timestamps of the NVD CVE data)
|
||||
* @param properties the database properties (containing timestamps of the
|
||||
* NVD CVE data)
|
||||
*/
|
||||
public ReportGenerator(String applicationName, List<Dependency> dependencies, List<Analyzer> analyzers, DatabaseProperties properties) {
|
||||
engine = createVelocityEngine();
|
||||
velocityEngine = createVelocityEngine();
|
||||
context = createContext();
|
||||
|
||||
engine.init();
|
||||
velocityEngine.init();
|
||||
|
||||
final DateFormat dateFormat = new SimpleDateFormat("MMM d, yyyy 'at' HH:mm:ss z");
|
||||
final DateFormat dateFormatXML = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
|
||||
@@ -119,19 +124,19 @@ public class ReportGenerator {
|
||||
/**
|
||||
* Creates a new Velocity Engine.
|
||||
*
|
||||
* @return a velocity engine.
|
||||
* @return a velocity engine
|
||||
*/
|
||||
private VelocityEngine createVelocityEngine() {
|
||||
final VelocityEngine engine = new VelocityEngine();
|
||||
final VelocityEngine velocity = new VelocityEngine();
|
||||
// Logging redirection for Velocity - Required by Jenkins and other server applications
|
||||
engine.setProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM_CLASS, VelocityLoggerRedirect.class.getName());
|
||||
return engine;
|
||||
velocity.setProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM_CLASS, VelocityLoggerRedirect.class.getName());
|
||||
return velocity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Velocity Context.
|
||||
*
|
||||
* @return a Velocity Context.
|
||||
* @return a Velocity Context
|
||||
*/
|
||||
private Context createContext() {
|
||||
return new VelocityContext();
|
||||
@@ -143,7 +148,7 @@ public class ReportGenerator {
|
||||
* @param outputStream the OutputStream to send the generated report to
|
||||
* @param format the format the report should be written in
|
||||
* @throws IOException is thrown when the template file does not exist
|
||||
* @throws Exception is thrown if there is an error writing out the reports.
|
||||
* @throws Exception is thrown if there is an error writing out the reports
|
||||
*/
|
||||
public void generateReports(OutputStream outputStream, Format format) throws IOException, Exception {
|
||||
if (format == Format.XML || format == Format.ALL) {
|
||||
@@ -162,10 +167,9 @@ public class ReportGenerator {
|
||||
*
|
||||
* @param outputDir the path where the reports should be written
|
||||
* @param format the format the report should be written in
|
||||
* @throws IOException is thrown when the template file does not exist
|
||||
* @throws Exception is thrown if there is an error writing out the reports.
|
||||
* @throws ReportException is thrown if there is an error writing out the reports
|
||||
*/
|
||||
public void generateReports(String outputDir, Format format) throws IOException, Exception {
|
||||
public void generateReports(String outputDir, Format format) throws ReportException {
|
||||
if (format == Format.XML || format == Format.ALL) {
|
||||
generateReport("XmlReport", outputDir + File.separator + "dependency-check-report.xml");
|
||||
}
|
||||
@@ -181,11 +185,12 @@ public class ReportGenerator {
|
||||
* Generates the Dependency Reports for the identified dependencies.
|
||||
*
|
||||
* @param outputDir the path where the reports should be written
|
||||
* @param outputFormat the format the report should be written in (XML, HTML, ALL)
|
||||
* @throws IOException is thrown when the template file does not exist
|
||||
* @throws Exception is thrown if there is an error writing out the reports.
|
||||
* @param outputFormat the format the report should be written in (XML,
|
||||
* HTML, ALL)
|
||||
* @throws ReportException is thrown if there is an error creating out the
|
||||
* reports
|
||||
*/
|
||||
public void generateReports(String outputDir, String outputFormat) throws IOException, Exception {
|
||||
public void generateReports(String outputDir, String outputFormat) throws ReportException {
|
||||
final String format = outputFormat.toUpperCase();
|
||||
final String pathToCheck = outputDir.toLowerCase();
|
||||
if (format.matches("^(XML|HTML|VULN|ALL)$")) {
|
||||
@@ -217,16 +222,16 @@ public class ReportGenerator {
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a report from a given Velocity Template. The template name provided can be the name of a template
|
||||
* contained in the jar file, such as 'XmlReport' or 'HtmlReport', or the template name can be the path to a
|
||||
* Generates a report from a given Velocity Template. The template name
|
||||
* provided can be the name of a template contained in the jar file, such as
|
||||
* 'XmlReport' or 'HtmlReport', or the template name can be the path to a
|
||||
* template file.
|
||||
*
|
||||
* @param templateName the name of the template to load.
|
||||
* @param outputStream the OutputStream to write the report to.
|
||||
* @throws IOException is thrown when the template file does not exist.
|
||||
* @throws Exception is thrown when an exception occurs.
|
||||
* @param templateName the name of the template to load
|
||||
* @param outputStream the OutputStream to write the report to
|
||||
* @throws ReportException is thrown when an exception occurs
|
||||
*/
|
||||
protected void generateReport(String templateName, OutputStream outputStream) throws IOException, Exception {
|
||||
protected void generateReport(String templateName, OutputStream outputStream) throws ReportException {
|
||||
InputStream input = null;
|
||||
String templatePath = null;
|
||||
final File f = new File(templateName);
|
||||
@@ -235,27 +240,30 @@ public class ReportGenerator {
|
||||
templatePath = templateName;
|
||||
input = new FileInputStream(f);
|
||||
} catch (FileNotFoundException ex) {
|
||||
LOGGER.error("Unable to generate the report, the report template file could not be found.");
|
||||
LOGGER.debug("", ex);
|
||||
throw new ReportException("Unable to locate template file: " + templateName, ex);
|
||||
}
|
||||
} else {
|
||||
templatePath = "templates/" + templateName + ".vsl";
|
||||
input = this.getClass().getClassLoader().getResourceAsStream(templatePath);
|
||||
}
|
||||
if (input == null) {
|
||||
throw new IOException("Template file doesn't exist");
|
||||
throw new ReportException("Template file doesn't exist: " + templatePath);
|
||||
}
|
||||
|
||||
final InputStreamReader reader = new InputStreamReader(input, "UTF-8");
|
||||
InputStreamReader reader = null;
|
||||
OutputStreamWriter writer = null;
|
||||
|
||||
try {
|
||||
reader = new InputStreamReader(input, "UTF-8");
|
||||
writer = new OutputStreamWriter(outputStream, "UTF-8");
|
||||
|
||||
if (!engine.evaluate(context, writer, templatePath, reader)) {
|
||||
throw new Exception("Failed to convert the template into html.");
|
||||
if (!velocityEngine.evaluate(context, writer, templatePath, reader)) {
|
||||
throw new ReportException("Failed to convert the template into html.");
|
||||
}
|
||||
writer.flush();
|
||||
} catch (UnsupportedEncodingException ex) {
|
||||
throw new ReportException("Unable to generate the report using UTF-8", ex);
|
||||
} catch (IOException ex) {
|
||||
throw new ReportException("Unable to write the report", ex);
|
||||
} finally {
|
||||
if (writer != null) {
|
||||
try {
|
||||
@@ -271,25 +279,27 @@ public class ReportGenerator {
|
||||
LOGGER.trace("", ex);
|
||||
}
|
||||
}
|
||||
try {
|
||||
reader.close();
|
||||
} catch (IOException ex) {
|
||||
LOGGER.trace("", ex);
|
||||
if (reader != null) {
|
||||
try {
|
||||
reader.close();
|
||||
} catch (IOException ex) {
|
||||
LOGGER.trace("", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a report from a given Velocity Template. The template name provided can be the name of a template
|
||||
* contained in the jar file, such as 'XmlReport' or 'HtmlReport', or the template name can be the path to a
|
||||
* Generates a report from a given Velocity Template. The template name
|
||||
* provided can be the name of a template contained in the jar file, such as
|
||||
* 'XmlReport' or 'HtmlReport', or the template name can be the path to a
|
||||
* template file.
|
||||
*
|
||||
* @param templateName the name of the template to load.
|
||||
* @param outFileName the filename and path to write the report to.
|
||||
* @throws IOException is thrown when the template file does not exist.
|
||||
* @throws Exception is thrown when an exception occurs.
|
||||
* @param templateName the name of the template to load
|
||||
* @param outFileName the filename and path to write the report to
|
||||
* @throws ReportException is thrown when the report cannot be generated
|
||||
*/
|
||||
protected void generateReport(String templateName, String outFileName) throws Exception {
|
||||
protected void generateReport(String templateName, String outFileName) throws ReportException {
|
||||
File outFile = new File(outFileName);
|
||||
if (outFile.getParentFile() == null) {
|
||||
outFile = new File(".", outFileName);
|
||||
@@ -297,7 +307,7 @@ public class ReportGenerator {
|
||||
if (!outFile.getParentFile().exists()) {
|
||||
final boolean created = outFile.getParentFile().mkdirs();
|
||||
if (!created) {
|
||||
throw new Exception("Unable to create directory '" + outFile.getParentFile().getAbsolutePath() + "'.");
|
||||
throw new ReportException("Unable to create directory '" + outFile.getParentFile().getAbsolutePath() + "'.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -305,6 +315,8 @@ public class ReportGenerator {
|
||||
try {
|
||||
outputSteam = new FileOutputStream(outFile);
|
||||
generateReport(templateName, outputSteam);
|
||||
} catch (FileNotFoundException ex) {
|
||||
throw new ReportException("Unable to write to file: " + outFile, ex);
|
||||
} finally {
|
||||
if (outputSteam != null) {
|
||||
try {
|
||||
|
||||
@@ -39,6 +39,11 @@ public final class DependencyVersionUtil {
|
||||
* are missing a version number using the previous regex.
|
||||
*/
|
||||
private static final Pattern RX_SINGLE_VERSION = Pattern.compile("\\d+(\\.?([_-](release|beta|alpha)|[a-zA-Z_-]{1,3}\\d{1,8}))?");
|
||||
|
||||
/**
|
||||
* Regular expression to extract the part before the version numbers if there are any based on RX_VERSION. In most cases, this part represents a more accurate name.
|
||||
*/
|
||||
private static final Pattern RX_PRE_VERSION = Pattern.compile("^(.+)[_-](\\d+\\.\\d{1,6})+");
|
||||
|
||||
/**
|
||||
* Private constructor for utility class.
|
||||
@@ -95,4 +100,27 @@ public final class DependencyVersionUtil {
|
||||
}
|
||||
return new DependencyVersion(version);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* A utility class to extract the part before version numbers from file names (or other strings containing version numbers.
|
||||
* In most cases, this part represents a more accurate name than the full file name.</p>
|
||||
* <pre>
|
||||
* Example:
|
||||
* Give the file name: library-name-1.4.1r2-release.jar
|
||||
* This function would return: library-name</pre>
|
||||
*
|
||||
* @param text the text being analyzed
|
||||
* @return the part before the version numbers if any, otherwise return the text itself.
|
||||
*/
|
||||
public static String parsePreVersion(String text) {
|
||||
if(parseVersion(text) == null)
|
||||
return text;
|
||||
|
||||
Matcher matcher = RX_PRE_VERSION.matcher(text);
|
||||
if (matcher.find()) {
|
||||
return matcher.group(1);
|
||||
}
|
||||
return text;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,11 +197,11 @@ public class HintHandler extends DefaultHandler {
|
||||
vendorDuplicatingHintRules.add(new VendorDuplicatingHintRule(attr.getValue(VALUE), attr.getValue(DUPLICATE)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handles the end element event.
|
||||
*
|
||||
* @param uri the element's uri
|
||||
* @param uri the element's URI
|
||||
* @param localName the local name
|
||||
* @param qName the qualified name
|
||||
* @throws SAXException thrown if there is an exception processing the
|
||||
|
||||
@@ -72,9 +72,9 @@ public class HintRule {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of givenProduct
|
||||
* Get the value of givenProduct.
|
||||
*
|
||||
* @return the value of givenProduct.
|
||||
* @return the value of givenProduct
|
||||
*/
|
||||
public List<Evidence> getGivenProduct() {
|
||||
return givenProduct;
|
||||
|
||||
@@ -32,7 +32,7 @@ public class Hints {
|
||||
private List<HintRule> hintRules;
|
||||
|
||||
/**
|
||||
* Get the value of hintRules
|
||||
* Get the value of hintRules.
|
||||
*
|
||||
* @return the value of hintRules
|
||||
*/
|
||||
@@ -41,7 +41,7 @@ public class Hints {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of hintRules
|
||||
* Set the value of hintRules.
|
||||
*
|
||||
* @param hintRules new value of hintRules
|
||||
*/
|
||||
@@ -55,7 +55,7 @@ public class Hints {
|
||||
private List<VendorDuplicatingHintRule> vendorDuplicatingHintRules;
|
||||
|
||||
/**
|
||||
* Get the value of vendorDuplicatingHintRules
|
||||
* Get the value of vendorDuplicatingHintRules.
|
||||
*
|
||||
* @return the value of vendorDuplicatingHintRules
|
||||
*/
|
||||
@@ -64,12 +64,11 @@ public class Hints {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of vendorDuplicatingHintRules
|
||||
* Set the value of vendorDuplicatingHintRules.
|
||||
*
|
||||
* @param vendorDuplicatingHintRules new value of vendorDuplicatingHintRules
|
||||
*/
|
||||
public void setVendorDuplicatingHintRules(List<VendorDuplicatingHintRule> vendorDuplicatingHintRules) {
|
||||
this.vendorDuplicatingHintRules = vendorDuplicatingHintRules;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ public class SuppressionErrorHandler implements ErrorHandler {
|
||||
*/
|
||||
@Override
|
||||
public void warning(SAXParseException ex) throws SAXException {
|
||||
LOGGER.debug("", ex);
|
||||
//LOGGER.debug("", ex);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,12 +17,19 @@
|
||||
*/
|
||||
package org.owasp.dependencycheck;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.owasp.dependencycheck.data.nvdcve.CveDB;
|
||||
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
|
||||
import org.owasp.dependencycheck.data.nvdcve.DatabaseProperties;
|
||||
import org.owasp.dependencycheck.exception.ExceptionCollection;
|
||||
import org.owasp.dependencycheck.exception.ReportException;
|
||||
import org.owasp.dependencycheck.reporting.ReportGenerator;
|
||||
import org.owasp.dependencycheck.utils.InvalidSettingException;
|
||||
import org.owasp.dependencycheck.utils.Settings;
|
||||
|
||||
/**
|
||||
@@ -34,10 +41,14 @@ public class EngineIntegrationTest extends BaseDBTestCase {
|
||||
/**
|
||||
* Test running the entire engine.
|
||||
*
|
||||
* @throws Exception is thrown when an exception occurs.
|
||||
* @throws java.io.IOException
|
||||
* @throws org.owasp.dependencycheck.utils.InvalidSettingException
|
||||
* @throws org.owasp.dependencycheck.data.nvdcve.DatabaseException
|
||||
* @throws org.owasp.dependencycheck.exception.ReportException
|
||||
* @throws org.owasp.dependencycheck.exception.ExceptionCollection
|
||||
*/
|
||||
@Test
|
||||
public void testEngine() throws Exception {
|
||||
public void testEngine() throws IOException, InvalidSettingException, DatabaseException, ReportException, ExceptionCollection {
|
||||
String testClasses = "target/test-classes";
|
||||
boolean autoUpdate = Settings.getBoolean(Settings.KEYS.AUTO_UPDATE);
|
||||
Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, false);
|
||||
@@ -45,7 +56,23 @@ public class EngineIntegrationTest extends BaseDBTestCase {
|
||||
Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, autoUpdate);
|
||||
instance.scan(testClasses);
|
||||
assertTrue(instance.getDependencies().size() > 0);
|
||||
instance.analyzeDependencies();
|
||||
try {
|
||||
instance.analyzeDependencies();
|
||||
} catch (ExceptionCollection ex) {
|
||||
if (ex.getExceptions().size()==1 &&
|
||||
(ex.getExceptions().get(0).getMessage().contains("bundle-audit") ||
|
||||
ex.getExceptions().get(0).getMessage().contains("AssemblyAnalyzer"))) {
|
||||
//this is fine to ignore
|
||||
} else if (ex.getExceptions().size()==2 &&
|
||||
((ex.getExceptions().get(0).getMessage().contains("bundle-audit") &&
|
||||
ex.getExceptions().get(1).getMessage().contains("AssemblyAnalyzer")) ||
|
||||
(ex.getExceptions().get(1).getMessage().contains("bundle-audit") &&
|
||||
ex.getExceptions().get(0).getMessage().contains("AssemblyAnalyzer")))) {
|
||||
//this is fine to ignore
|
||||
} else {
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
CveDB cveDB = new CveDB();
|
||||
cveDB.open();
|
||||
DatabaseProperties dbProp = cveDB.getDatabaseProperties();
|
||||
|
||||
@@ -26,6 +26,7 @@ import java.io.File;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Assume;
|
||||
@@ -40,6 +41,7 @@ import org.owasp.dependencycheck.dependency.Dependency;
|
||||
import org.owasp.dependencycheck.dependency.Evidence;
|
||||
import org.owasp.dependencycheck.dependency.Identifier;
|
||||
import org.owasp.dependencycheck.dependency.Vulnerability;
|
||||
import org.owasp.dependencycheck.exception.ExceptionCollection;
|
||||
import org.owasp.dependencycheck.utils.Settings;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -175,6 +177,7 @@ public class RubyBundleAuditAnalyzerTest extends BaseDBTestCase {
|
||||
* Test Ruby dependencies and their paths.
|
||||
*
|
||||
* @throws AnalysisException is thrown when an exception occurs.
|
||||
* @throws DatabaseException thrown when an exception occurs
|
||||
*/
|
||||
@Test
|
||||
public void testDependenciesPath() throws AnalysisException, DatabaseException {
|
||||
@@ -186,6 +189,8 @@ public class RubyBundleAuditAnalyzerTest extends BaseDBTestCase {
|
||||
} catch (NullPointerException ex) {
|
||||
LOGGER.error("NPE", ex);
|
||||
throw ex;
|
||||
} catch (ExceptionCollection ex) {
|
||||
Assume.assumeNoException("Exception setting up RubyBundleAuditAnalyzer; bundle audit may not be installed, or property \"analyzer.bundle.audit.path\" may not be set.", ex);
|
||||
}
|
||||
List<Dependency> dependencies = engine.getDependencies();
|
||||
LOGGER.info(dependencies.size() + " dependencies found.");
|
||||
|
||||
@@ -20,7 +20,7 @@ Copyright (c) 2013 Jeremy Long. All Rights Reserved.
|
||||
<parent>
|
||||
<groupId>org.owasp</groupId>
|
||||
<artifactId>dependency-check-parent</artifactId>
|
||||
<version>1.4.1-SNAPSHOT</version>
|
||||
<version>1.4.3-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>dependency-check-maven</artifactId>
|
||||
|
||||
@@ -36,11 +36,13 @@ import org.owasp.dependencycheck.analyzer.DependencyBundlingAnalyzer;
|
||||
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
|
||||
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
|
||||
import org.owasp.dependencycheck.dependency.Dependency;
|
||||
import org.owasp.dependencycheck.exception.ExceptionCollection;
|
||||
import org.owasp.dependencycheck.exception.ReportException;
|
||||
import org.owasp.dependencycheck.utils.Settings;
|
||||
|
||||
/**
|
||||
* Maven Plugin that checks project dependencies and the dependencies of all child modules to see if they have any known published
|
||||
* vulnerabilities.
|
||||
* Maven Plugin that checks project dependencies and the dependencies of all
|
||||
* child modules to see if they have any known published vulnerabilities.
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@@ -55,18 +57,27 @@ import org.owasp.dependencycheck.utils.Settings;
|
||||
public class AggregateMojo extends BaseDependencyCheckMojo {
|
||||
|
||||
/**
|
||||
* Executes the aggregate dependency-check goal. This runs dependency-check and generates the subsequent reports.
|
||||
* The key to store aggregate exception in the root Maven execution context.
|
||||
*/
|
||||
private static final String AGGREGATE_EXCEPTIONS = "AggregateExceptions";
|
||||
|
||||
/**
|
||||
* Executes the aggregate dependency-check goal. This runs dependency-check
|
||||
* and generates the subsequent reports.
|
||||
*
|
||||
* @throws MojoExecutionException thrown if there is ane exception running the mojo
|
||||
* @throws MojoFailureException thrown if dependency-check is configured to fail the build
|
||||
* @throws MojoExecutionException thrown if there is ane exception running
|
||||
* the mojo
|
||||
* @throws MojoFailureException thrown if dependency-check is configured to
|
||||
* fail the build
|
||||
*/
|
||||
@Override
|
||||
public void runCheck() throws MojoExecutionException, MojoFailureException {
|
||||
final Engine engine = generateDataFile();
|
||||
final MavenEngine engine = generateDataFile();
|
||||
if (engine == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
//if (getProject() == getReactorProjects().get(getReactorProjects().size() - 1)) {
|
||||
if (getProject() == getLastProject()) {
|
||||
|
||||
//ensure that the .ser file was created for each.
|
||||
for (MavenProject current : getReactorProjects()) {
|
||||
final File dataFile = getDataFile(current);
|
||||
@@ -76,7 +87,6 @@ public class AggregateMojo extends BaseDependencyCheckMojo {
|
||||
generateDataFile(engine, current);
|
||||
}
|
||||
}
|
||||
|
||||
for (MavenProject current : getReactorProjects()) {
|
||||
List<Dependency> dependencies = readDataFile(current);
|
||||
if (dependencies == null) {
|
||||
@@ -90,10 +100,8 @@ public class AggregateMojo extends BaseDependencyCheckMojo {
|
||||
getLog().debug(String.format("Adding %d dependencies from %s", childDeps.size(), reportOn.getName()));
|
||||
}
|
||||
dependencies.addAll(childDeps);
|
||||
} else {
|
||||
if (getLog().isDebugEnabled()) {
|
||||
getLog().debug(String.format("No dependencies read for %s", reportOn.getName()));
|
||||
}
|
||||
} else if (getLog().isDebugEnabled()) {
|
||||
getLog().debug(String.format("No dependencies read for %s", reportOn.getName()));
|
||||
}
|
||||
}
|
||||
engine.getDependencies().clear();
|
||||
@@ -118,7 +126,21 @@ public class AggregateMojo extends BaseDependencyCheckMojo {
|
||||
//we shouldn't write this because nothing is configured to generate this report.
|
||||
outputDir = new File(current.getBuild().getDirectory());
|
||||
}
|
||||
writeReports(engine, current, outputDir);
|
||||
try {
|
||||
writeReports(engine, current, outputDir);
|
||||
} catch (ReportException ex) {
|
||||
ExceptionCollection exCol = (ExceptionCollection) engine.getExecutionRoot().getContextValue(AGGREGATE_EXCEPTIONS);
|
||||
if (exCol == null) {
|
||||
exCol = new ExceptionCollection("Error writing aggregate report", ex);
|
||||
} else {
|
||||
exCol.addException(ex);
|
||||
}
|
||||
if (this.isFailOnError()) {
|
||||
throw new MojoExecutionException("One or more exceptions occured during dependency-check analysis", exCol);
|
||||
} else {
|
||||
getLog().debug("One or more exceptions occured during dependency-check analysis", exCol);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
engine.cleanup();
|
||||
@@ -126,7 +148,8 @@ public class AggregateMojo extends BaseDependencyCheckMojo {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the last project in the reactor - taking into account skipped projects.
|
||||
* Gets the last project in the reactor - taking into account skipped
|
||||
* projects.
|
||||
*
|
||||
* @return the last project in the reactor
|
||||
*/
|
||||
@@ -152,7 +175,8 @@ public class AggregateMojo extends BaseDependencyCheckMojo {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a set containing all the descendant projects of the given project.
|
||||
* Returns a set containing all the descendant projects of the given
|
||||
* project.
|
||||
*
|
||||
* @param project the project for which all descendants will be returned
|
||||
* @return the set of descendant projects
|
||||
@@ -232,49 +256,85 @@ public class AggregateMojo extends BaseDependencyCheckMojo {
|
||||
* Test if the project has pom packaging
|
||||
*
|
||||
* @param mavenProject Project to test
|
||||
* @return <code>true</code> if it has a pom packaging; otherwise <code>false</code>
|
||||
* @return <code>true</code> if it has a pom packaging; otherwise
|
||||
* <code>false</code>
|
||||
*/
|
||||
protected boolean isMultiModule(MavenProject mavenProject) {
|
||||
return "pom".equals(mavenProject.getPackaging());
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the engine, runs a scan, and writes the serialized dependencies to disk.
|
||||
* Initializes the engine, runs a scan, and writes the serialized
|
||||
* dependencies to disk.
|
||||
*
|
||||
* @return the Engine used to execute dependency-check
|
||||
* @throws MojoExecutionException thrown if there is an exception running the mojo
|
||||
* @throws MojoFailureException thrown if dependency-check is configured to fail the build if severe CVEs are identified.
|
||||
* @return the MavenEngine used to execute dependency-check
|
||||
* @throws MojoExecutionException thrown if there is an exception running
|
||||
* the mojo
|
||||
* @throws MojoFailureException thrown if dependency-check is configured to
|
||||
* fail the build if severe CVEs are identified.
|
||||
*/
|
||||
protected Engine generateDataFile() throws MojoExecutionException, MojoFailureException {
|
||||
final Engine engine;
|
||||
protected MavenEngine generateDataFile() throws MojoExecutionException, MojoFailureException {
|
||||
MavenEngine engine = null;
|
||||
try {
|
||||
engine = initializeEngine();
|
||||
} catch (DatabaseException ex) {
|
||||
if (getLog().isDebugEnabled()) {
|
||||
getLog().debug("Database connection error", ex);
|
||||
}
|
||||
throw new MojoExecutionException("An exception occured connecting to the local database. Please see the log file for more details.", ex);
|
||||
final String msg = "An exception occured connecting to the local database. Please see the log file for more details.";
|
||||
if (this.isFailOnError()) {
|
||||
throw new MojoExecutionException(msg, ex);
|
||||
}
|
||||
getLog().error(msg, ex);
|
||||
return null;
|
||||
}
|
||||
return generateDataFile(engine, getProject());
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs dependency-check's Engine and writes the serialized dependencies to disk.
|
||||
* Runs dependency-check's MavenEngine and writes the serialized
|
||||
* dependencies to disk.
|
||||
*
|
||||
* @param engine the Engine to use when scanning.
|
||||
* @param engine the MavenEngine to use when scanning.
|
||||
* @param project the project to scan and generate the data file for
|
||||
* @return the Engine used to execute dependency-check
|
||||
* @throws MojoExecutionException thrown if there is an exception running the mojo
|
||||
* @throws MojoFailureException thrown if dependency-check is configured to fail the build if severe CVEs are identified.
|
||||
* @return the MavenEngine used to execute dependency-check
|
||||
* @throws MojoExecutionException thrown if there is an exception running
|
||||
* the mojo
|
||||
* @throws MojoFailureException thrown if dependency-check is configured to
|
||||
* fail the build if severe CVEs are identified.
|
||||
*/
|
||||
protected Engine generateDataFile(Engine engine, MavenProject project) throws MojoExecutionException, MojoFailureException {
|
||||
protected MavenEngine generateDataFile(MavenEngine engine, MavenProject project) throws MojoExecutionException, MojoFailureException {
|
||||
if (getLog().isDebugEnabled()) {
|
||||
getLog().debug(String.format("Begin Scanning: %s", project.getName()));
|
||||
}
|
||||
engine.getDependencies().clear();
|
||||
engine.resetFileTypeAnalyzers();
|
||||
scanArtifacts(project, engine);
|
||||
engine.analyzeDependencies();
|
||||
try {
|
||||
engine.analyzeDependencies();
|
||||
} catch (ExceptionCollection ex) {
|
||||
ExceptionCollection col = (ExceptionCollection) engine.getExecutionRoot().getContextValue(AGGREGATE_EXCEPTIONS);
|
||||
if (col == null) {
|
||||
col = ex;
|
||||
} else if (ex.isFatal()) {
|
||||
col.setFatal(true);
|
||||
col.getExceptions().addAll(ex.getExceptions());
|
||||
}
|
||||
if (col.isFatal()) {
|
||||
final String msg = String.format("Fatal exception(s) analyzing %s", project.getName());
|
||||
if (this.isFailOnError()) {
|
||||
throw new MojoExecutionException(msg, ex);
|
||||
}
|
||||
getLog().error(msg, col);
|
||||
return null;
|
||||
} else {
|
||||
final String msg = String.format("Exception(s) analyzing %s", project.getName());
|
||||
if (getLog().isDebugEnabled()) {
|
||||
getLog().debug(msg, ex);
|
||||
}
|
||||
engine.getExecutionRoot().setContextValue(AGGREGATE_EXCEPTIONS, col);
|
||||
}
|
||||
}
|
||||
final File target = new File(project.getBuild().getDirectory());
|
||||
writeDataFile(project, target, engine.getDependencies());
|
||||
showSummary(project, engine.getDependencies());
|
||||
@@ -306,7 +366,8 @@ public class AggregateMojo extends BaseDependencyCheckMojo {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the description of the Dependency-Check report to be displayed in the Maven Generated Reports page.
|
||||
* Gets the description of the Dependency-Check report to be displayed in
|
||||
* the Maven Generated Reports page.
|
||||
*
|
||||
* @param locale The Locale to get the description for
|
||||
* @return the description
|
||||
|
||||
@@ -47,6 +47,7 @@ import org.owasp.dependencycheck.dependency.Confidence;
|
||||
import org.owasp.dependencycheck.dependency.Dependency;
|
||||
import org.owasp.dependencycheck.dependency.Identifier;
|
||||
import org.owasp.dependencycheck.dependency.Vulnerability;
|
||||
import org.owasp.dependencycheck.exception.ReportException;
|
||||
import org.owasp.dependencycheck.reporting.ReportGenerator;
|
||||
import org.owasp.dependencycheck.utils.ExpectedOjectInputStream;
|
||||
import org.owasp.dependencycheck.utils.Settings;
|
||||
@@ -69,14 +70,28 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
|
||||
* System specific new line character.
|
||||
*/
|
||||
private static final String NEW_LINE = System.getProperty("line.separator", "\n").intern();
|
||||
//</editor-fold>
|
||||
// <editor-fold defaultstate="collapsed" desc="Maven bound parameters and components">
|
||||
/**
|
||||
* Sets whether or not the external report format should be used.
|
||||
*/
|
||||
@Parameter(property = "metaFileName", defaultValue = "dependency-check.ser", required = true)
|
||||
private String dataFileName;
|
||||
/**
|
||||
* Sets whether or not the external report format should be used.
|
||||
*/
|
||||
@Parameter(property = "failOnError", defaultValue = "true", required = true)
|
||||
private boolean failOnError;
|
||||
|
||||
/**
|
||||
* Returns if the mojo should fail the build if an exception occurs.
|
||||
*
|
||||
* @return whether or not the mojo should fail the build
|
||||
*/
|
||||
protected boolean isFailOnError() {
|
||||
return failOnError;
|
||||
}
|
||||
|
||||
//</editor-fold>
|
||||
// <editor-fold defaultstate="collapsed" desc="Maven bound parameters and components">
|
||||
/**
|
||||
* The Maven Project Object.
|
||||
*/
|
||||
@@ -111,13 +126,11 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
|
||||
* Sets whether auto-updating of the NVD CVE/CPE data is enabled. It is not
|
||||
* recommended that this be turned to false. Default is true.
|
||||
*/
|
||||
@SuppressWarnings("CanBeFinal")
|
||||
@Parameter(property = "autoUpdate")
|
||||
private Boolean autoUpdate;
|
||||
/**
|
||||
* Sets whether Experimental analyzers are enabled. Default is false.
|
||||
*/
|
||||
@SuppressWarnings("CanBeFinal")
|
||||
@Parameter(property = "enableExperimental")
|
||||
private Boolean enableExperimental;
|
||||
/**
|
||||
@@ -145,7 +158,6 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
|
||||
/**
|
||||
* The maven settings proxy id.
|
||||
*/
|
||||
@SuppressWarnings("CanBeFinal")
|
||||
@Parameter(property = "mavenSettingsProxyId", required = false)
|
||||
private String mavenSettingsProxyId;
|
||||
|
||||
@@ -162,6 +174,7 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
|
||||
/**
|
||||
* Flag indicating whether or not to show a summary in the output.
|
||||
*/
|
||||
@SuppressWarnings("CanBeFinal")
|
||||
@Parameter(property = "showSummary", defaultValue = "true", required = false)
|
||||
private boolean showSummary = true;
|
||||
|
||||
@@ -541,7 +554,7 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
|
||||
* @param project the project to scan the dependencies of
|
||||
* @param engine the engine to use to scan the dependencies
|
||||
*/
|
||||
protected void scanArtifacts(MavenProject project, Engine engine) {
|
||||
protected void scanArtifacts(MavenProject project, MavenEngine engine) {
|
||||
for (Artifact a : project.getArtifacts()) {
|
||||
if (excludeFromScan(a)) {
|
||||
continue;
|
||||
@@ -649,14 +662,14 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
|
||||
//</editor-fold>
|
||||
|
||||
/**
|
||||
* Initializes a new <code>Engine</code> that can be used for scanning.
|
||||
* Initializes a new <code>MavenEngine</code> that can be used for scanning.
|
||||
*
|
||||
* @return a newly instantiated <code>Engine</code>
|
||||
* @return a newly instantiated <code>MavenEngine</code>
|
||||
* @throws DatabaseException thrown if there is a database exception
|
||||
*/
|
||||
protected Engine initializeEngine() throws DatabaseException {
|
||||
protected MavenEngine initializeEngine() throws DatabaseException {
|
||||
populateSettings();
|
||||
return new Engine(this.project,
|
||||
return new MavenEngine(this.project,
|
||||
this.reactorProjects);
|
||||
}
|
||||
|
||||
@@ -875,10 +888,11 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
|
||||
* Generates the reports for a given dependency-check engine.
|
||||
*
|
||||
* @param engine a dependency-check engine
|
||||
* @param p the maven project
|
||||
* @param outputDir the directory path to write the report(s).
|
||||
* @param p the Maven project
|
||||
* @param outputDir the directory path to write the report(s)
|
||||
* @throws ReportException thrown if there is an error writing the report
|
||||
*/
|
||||
protected void writeReports(Engine engine, MavenProject p, File outputDir) {
|
||||
protected void writeReports(MavenEngine engine, MavenProject p, File outputDir) throws ReportException {
|
||||
DatabaseProperties prop = null;
|
||||
CveDB cve = null;
|
||||
try {
|
||||
@@ -897,19 +911,11 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
|
||||
final ReportGenerator r = new ReportGenerator(p.getName(), engine.getDependencies(), engine.getAnalyzers(), prop);
|
||||
try {
|
||||
r.generateReports(outputDir.getAbsolutePath(), format);
|
||||
} catch (IOException ex) {
|
||||
getLog().error(
|
||||
"Unexpected exception occurred during analysis; please see the verbose error log for more details.");
|
||||
if (getLog().isDebugEnabled()) {
|
||||
getLog().debug("", ex);
|
||||
}
|
||||
} catch (Throwable ex) {
|
||||
getLog().error(
|
||||
"Unexpected exception occurred during analysis; please see the verbose error log for more details.");
|
||||
if (getLog().isDebugEnabled()) {
|
||||
getLog().debug("", ex);
|
||||
}
|
||||
} catch (ReportException ex) {
|
||||
final String msg = String.format("Error generating the report for %s", p.getName());
|
||||
throw new ReportException(msg, ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//<editor-fold defaultstate="collapsed" desc="Methods to fail build or show summary">
|
||||
@@ -1074,8 +1080,8 @@ public abstract class BaseDependencyCheckMojo extends AbstractMojo implements Ma
|
||||
* scan data between the "check" and "aggregate" phase.
|
||||
*
|
||||
* @param project the Maven project to read the data file from
|
||||
* @return a <code>Engine</code> object populated with dependencies if the
|
||||
* serialized data file exists; otherwise <code>null</code> is returned
|
||||
* @return a <code>MavenEngine</code> object populated with dependencies if
|
||||
* the serialized data file exists; otherwise <code>null</code> is returned
|
||||
*/
|
||||
protected List<Dependency> readDataFile(MavenProject project) {
|
||||
final Object oPath = project.getContextValue(this.getDataFileContextKey());
|
||||
|
||||
@@ -26,10 +26,13 @@ import org.apache.maven.plugins.annotations.Mojo;
|
||||
import org.apache.maven.plugins.annotations.Parameter;
|
||||
import org.apache.maven.plugins.annotations.ResolutionScope;
|
||||
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
|
||||
import org.owasp.dependencycheck.exception.ExceptionCollection;
|
||||
import org.owasp.dependencycheck.exception.ReportException;
|
||||
import org.owasp.dependencycheck.utils.Settings;
|
||||
|
||||
/**
|
||||
* Maven Plugin that checks the project dependencies to see if they have any known published vulnerabilities.
|
||||
* Maven Plugin that checks the project dependencies to see if they have any
|
||||
* known published vulnerabilities.
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@@ -45,7 +48,8 @@ public class CheckMojo extends BaseDependencyCheckMojo {
|
||||
/**
|
||||
* Returns whether or not a the report can be generated.
|
||||
*
|
||||
* @return <code>true</code> if the report can be generated; otherwise <code>false</code>
|
||||
* @return <code>true</code> if the report can be generated; otherwise
|
||||
* <code>false</code>
|
||||
*/
|
||||
@Override
|
||||
public boolean canGenerateReport() {
|
||||
@@ -60,33 +64,65 @@ public class CheckMojo extends BaseDependencyCheckMojo {
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the dependency-check engine on the project's dependencies and generates the report.
|
||||
* Executes the dependency-check engine on the project's dependencies and
|
||||
* generates the report.
|
||||
*
|
||||
* @throws MojoExecutionException thrown if there is an exception executing the goal
|
||||
* @throws MojoFailureException thrown if dependency-check is configured to fail the build
|
||||
* @throws MojoExecutionException thrown if there is an exception executing
|
||||
* the goal
|
||||
* @throws MojoFailureException thrown if dependency-check is configured to
|
||||
* fail the build
|
||||
*/
|
||||
@Override
|
||||
public void runCheck() throws MojoExecutionException, MojoFailureException {
|
||||
final Engine engine;
|
||||
MavenEngine engine = null;
|
||||
try {
|
||||
engine = initializeEngine();
|
||||
} catch (DatabaseException ex) {
|
||||
if (getLog().isDebugEnabled()) {
|
||||
getLog().debug("Database connection error", ex);
|
||||
}
|
||||
throw new MojoExecutionException("An exception occured connecting to the local database. Please see the log file for more details.", ex);
|
||||
final String msg = "An exception occured connecting to the local database. Please see the log file for more details.";
|
||||
if (this.isFailOnError()) {
|
||||
throw new MojoExecutionException(msg, ex);
|
||||
}
|
||||
getLog().error(msg);
|
||||
}
|
||||
scanArtifacts(getProject(), engine);
|
||||
if (engine.getDependencies().isEmpty()) {
|
||||
getLog().info("No dependencies were identified that could be analyzed by dependency-check");
|
||||
} else {
|
||||
engine.analyzeDependencies();
|
||||
writeReports(engine, getProject(), getCorrectOutputDirectory());
|
||||
writeDataFile(getProject(), null, engine.getDependencies());
|
||||
showSummary(getProject(), engine.getDependencies());
|
||||
checkForFailure(engine.getDependencies());
|
||||
if (engine != null) {
|
||||
scanArtifacts(getProject(), engine);
|
||||
if (engine.getDependencies().isEmpty()) {
|
||||
getLog().info("No dependencies were identified that could be analyzed by dependency-check");
|
||||
} else {
|
||||
ExceptionCollection exCol = null;
|
||||
try {
|
||||
engine.analyzeDependencies();
|
||||
} catch (ExceptionCollection ex) {
|
||||
if (this.isFailOnError() && ex.isFatal()) {
|
||||
throw new MojoExecutionException("One or more exceptions occured during analysis", ex);
|
||||
}
|
||||
exCol = ex;
|
||||
}
|
||||
if (exCol == null || !exCol.isFatal()) {
|
||||
try {
|
||||
writeReports(engine, getProject(), getCorrectOutputDirectory());
|
||||
} catch (ReportException ex) {
|
||||
if (this.isFailOnError()) {
|
||||
if (exCol != null) {
|
||||
exCol.addException(ex);
|
||||
} else {
|
||||
exCol = new ExceptionCollection("Unable to write the dependency-check report", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
writeDataFile(getProject(), null, engine.getDependencies());
|
||||
showSummary(getProject(), engine.getDependencies());
|
||||
checkForFailure(engine.getDependencies());
|
||||
if (exCol != null && this.isFailOnError()) {
|
||||
throw new MojoExecutionException("One or more exceptions occured during dependency-check analysis", exCol);
|
||||
}
|
||||
}
|
||||
}
|
||||
engine.cleanup();
|
||||
}
|
||||
engine.cleanup();
|
||||
Settings.cleanup();
|
||||
}
|
||||
|
||||
@@ -109,7 +145,8 @@ public class CheckMojo extends BaseDependencyCheckMojo {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the description of the Dependency-Check report to be displayed in the Maven Generated Reports page.
|
||||
* Gets the description of the Dependency-Check report to be displayed in
|
||||
* the Maven Generated Reports page.
|
||||
*
|
||||
* @param locale The Locale to get the description for
|
||||
* @return the description
|
||||
|
||||
@@ -23,22 +23,25 @@ import org.owasp.dependencycheck.analyzer.Analyzer;
|
||||
import org.owasp.dependencycheck.analyzer.CPEAnalyzer;
|
||||
import org.owasp.dependencycheck.analyzer.FileTypeAnalyzer;
|
||||
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
|
||||
import org.owasp.dependencycheck.data.update.exception.UpdateException;
|
||||
import org.owasp.dependencycheck.exception.ExceptionCollection;
|
||||
import org.owasp.dependencycheck.exception.InitializationException;
|
||||
import org.owasp.dependencycheck.utils.Settings;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* A modified version of the core engine specifically designed to persist some data between multiple executions of a multi-module
|
||||
* Maven project.
|
||||
* A modified version of the core engine specifically designed to persist some
|
||||
* data between multiple executions of a multi-module Maven project.
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
public class Engine extends org.owasp.dependencycheck.Engine {
|
||||
public class MavenEngine extends org.owasp.dependencycheck.Engine {
|
||||
|
||||
/**
|
||||
* The logger.
|
||||
*/
|
||||
private static final transient Logger LOGGER = LoggerFactory.getLogger(Engine.class);
|
||||
private static final transient Logger LOGGER = LoggerFactory.getLogger(MavenEngine.class);
|
||||
/**
|
||||
* A key used to persist an object in the MavenProject.
|
||||
*/
|
||||
@@ -52,18 +55,21 @@ public class Engine extends org.owasp.dependencycheck.Engine {
|
||||
*/
|
||||
private List<MavenProject> reactorProjects;
|
||||
/**
|
||||
* Key used in the MavenProject context values to note whether or not an update has been executed.
|
||||
* Key used in the MavenProject context values to note whether or not an
|
||||
* update has been executed.
|
||||
*/
|
||||
public static final String UPDATE_EXECUTED_FLAG = "dependency-check-update-executed";
|
||||
|
||||
/**
|
||||
* Creates a new Engine to perform anyalsis on dependencies.
|
||||
* Creates a new Engine to perform analysis on dependencies.
|
||||
*
|
||||
* @param project the current Maven project
|
||||
* @param reactorProjects the reactor projects for the current Maven execution
|
||||
* @throws DatabaseException thrown if there is an issue connecting to the database
|
||||
* @param reactorProjects the reactor projects for the current Maven
|
||||
* execution
|
||||
* @throws DatabaseException thrown if there is an issue connecting to the
|
||||
* database
|
||||
*/
|
||||
public Engine(MavenProject project, List<MavenProject> reactorProjects) throws DatabaseException {
|
||||
public MavenEngine(MavenProject project, List<MavenProject> reactorProjects) throws DatabaseException {
|
||||
this.currentProject = project;
|
||||
this.reactorProjects = reactorProjects;
|
||||
initializeEngine();
|
||||
@@ -71,9 +77,12 @@ public class Engine extends org.owasp.dependencycheck.Engine {
|
||||
|
||||
/**
|
||||
* Runs the analyzers against all of the dependencies.
|
||||
*
|
||||
* @throws ExceptionCollection thrown if an exception occurred; contains a
|
||||
* collection of exceptions that occurred during analysis.
|
||||
*/
|
||||
@Override
|
||||
public void analyzeDependencies() {
|
||||
public void analyzeDependencies() throws ExceptionCollection {
|
||||
final MavenProject root = getExecutionRoot();
|
||||
if (root != null) {
|
||||
LOGGER.debug("Checking root project, {}, if updates have already been completed", root.getArtifactId());
|
||||
@@ -91,8 +100,10 @@ public class Engine extends org.owasp.dependencycheck.Engine {
|
||||
|
||||
/**
|
||||
* Runs the update steps of dependency-check.
|
||||
*
|
||||
* @throws UpdateException thrown if there is an exception
|
||||
*/
|
||||
public void update() {
|
||||
public void update() throws UpdateException {
|
||||
final MavenProject root = getExecutionRoot();
|
||||
if (root != null && root.getContextValue(UPDATE_EXECUTED_FLAG) != null) {
|
||||
System.setProperty(Settings.KEYS.AUTO_UPDATE, Boolean.FALSE.toString());
|
||||
@@ -103,20 +114,21 @@ public class Engine extends org.owasp.dependencycheck.Engine {
|
||||
/**
|
||||
* This constructor should not be called. Use Engine(MavenProject) instead.
|
||||
*
|
||||
* @throws DatabaseException thrown if there is an issue connecting to the database
|
||||
* @throws DatabaseException thrown if there is an issue connecting to the
|
||||
* database
|
||||
*/
|
||||
private Engine() throws DatabaseException {
|
||||
private MavenEngine() throws DatabaseException {
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the given analyzer. This skips the initialization of the CPEAnalyzer if it has been initialized by a previous
|
||||
* execution.
|
||||
* Initializes the given analyzer. This skips the initialization of the
|
||||
* CPEAnalyzer if it has been initialized by a previous execution.
|
||||
*
|
||||
* @param analyzer the analyzer to initialize
|
||||
* @return the initialized analyzer
|
||||
*/
|
||||
@Override
|
||||
protected Analyzer initializeAnalyzer(Analyzer analyzer) {
|
||||
protected Analyzer initializeAnalyzer(Analyzer analyzer) throws InitializationException {
|
||||
if (analyzer instanceof CPEAnalyzer) {
|
||||
CPEAnalyzer cpe = getPreviouslyLoadedCPEAnalyzer();
|
||||
if (cpe != null && cpe.isOpen()) {
|
||||
@@ -129,7 +141,8 @@ public class Engine extends org.owasp.dependencycheck.Engine {
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases resources used by the analyzers by calling close() on each analyzer.
|
||||
* Releases resources used by the analyzers by calling close() on each
|
||||
* analyzer.
|
||||
*/
|
||||
@Override
|
||||
public void cleanup() {
|
||||
@@ -195,7 +208,7 @@ public class Engine extends org.owasp.dependencycheck.Engine {
|
||||
*
|
||||
* @return the root Maven Project
|
||||
*/
|
||||
private MavenProject getExecutionRoot() {
|
||||
MavenProject getExecutionRoot() {
|
||||
if (reactorProjects == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -216,8 +229,10 @@ public class Engine extends org.owasp.dependencycheck.Engine {
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the file type analyzers so that they can be re-used to scan additional directories. Without the reset the analyzer
|
||||
* might be disabled because the first scan/analyze did not identify any files that could be processed by the analyzer.
|
||||
* Resets the file type analyzers so that they can be re-used to scan
|
||||
* additional directories. Without the reset the analyzer might be disabled
|
||||
* because the first scan/analyze did not identify any files that could be
|
||||
* processed by the analyzer.
|
||||
*/
|
||||
public void resetFileTypeAnalyzers() {
|
||||
for (FileTypeAnalyzer a : getFileTypeAnalyzers()) {
|
||||
@@ -54,14 +54,20 @@ public class PurgeMojo extends BaseDependencyCheckMojo {
|
||||
/**
|
||||
* Purges the local copy of the NVD.
|
||||
*
|
||||
* @throws MojoExecutionException thrown if there is an exception executing the goal
|
||||
* @throws MojoFailureException thrown if dependency-check is configured to fail the build
|
||||
* @throws MojoExecutionException thrown if there is an exception executing
|
||||
* the goal
|
||||
* @throws MojoFailureException thrown if dependency-check is configured to
|
||||
* fail the build
|
||||
*/
|
||||
@Override
|
||||
public void runCheck() throws MojoExecutionException, MojoFailureException {
|
||||
|
||||
if (getConnectionString() != null && !getConnectionString().isEmpty()) {
|
||||
getLog().error("Unable to purge the local NVD when using a non-default connection string");
|
||||
final String msg = "Unable to purge the local NVD when using a non-default connection string";
|
||||
if (this.isFailOnError()) {
|
||||
throw new MojoFailureException(msg);
|
||||
}
|
||||
getLog().error(msg);
|
||||
} else {
|
||||
populateSettings();
|
||||
File db;
|
||||
@@ -71,13 +77,25 @@ public class PurgeMojo extends BaseDependencyCheckMojo {
|
||||
if (db.delete()) {
|
||||
getLog().info("Database file purged; local copy of the NVD has been removed");
|
||||
} else {
|
||||
getLog().error(String.format("Unable to delete '%s'; please delete the file manually", db.getAbsolutePath()));
|
||||
final String msg = String.format("Unable to delete '%s'; please delete the file manually", db.getAbsolutePath());
|
||||
if (this.isFailOnError()) {
|
||||
throw new MojoFailureException(msg);
|
||||
}
|
||||
getLog().error(msg);
|
||||
}
|
||||
} else {
|
||||
getLog().error(String.format("Unable to purge database; the database file does not exists: %s", db.getAbsolutePath()));
|
||||
final String msg = String.format("Unable to purge database; the database file does not exists: %s", db.getAbsolutePath());
|
||||
if (this.isFailOnError()) {
|
||||
throw new MojoFailureException(msg);
|
||||
}
|
||||
getLog().error(msg);
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
getLog().error("Unable to delete the database");
|
||||
final String msg = "Unable to delete the database";
|
||||
if (this.isFailOnError()) {
|
||||
throw new MojoExecutionException(msg, ex);
|
||||
}
|
||||
getLog().error(msg);
|
||||
}
|
||||
Settings.cleanup();
|
||||
}
|
||||
@@ -95,7 +113,8 @@ public class PurgeMojo extends BaseDependencyCheckMojo {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the description of the Dependency-Check report to be displayed in the Maven Generated Reports page.
|
||||
* Gets the description of the Dependency-Check report to be displayed in
|
||||
* the Maven Generated Reports page.
|
||||
*
|
||||
* @param locale The Locale to get the description for
|
||||
* @return the description
|
||||
|
||||
@@ -24,10 +24,12 @@ import org.apache.maven.plugins.annotations.LifecyclePhase;
|
||||
import org.apache.maven.plugins.annotations.Mojo;
|
||||
import org.apache.maven.plugins.annotations.ResolutionScope;
|
||||
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
|
||||
import org.owasp.dependencycheck.data.update.exception.UpdateException;
|
||||
import org.owasp.dependencycheck.utils.Settings;
|
||||
|
||||
/**
|
||||
* Maven Plugin that checks the project dependencies to see if they have any known published vulnerabilities.
|
||||
* Maven Plugin that checks the project dependencies to see if they have any
|
||||
* known published vulnerabilities.
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
@@ -51,14 +53,17 @@ public class UpdateMojo extends BaseDependencyCheckMojo {
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the dependency-check engine on the project's dependencies and generates the report.
|
||||
* Executes the dependency-check engine on the project's dependencies and
|
||||
* generates the report.
|
||||
*
|
||||
* @throws MojoExecutionException thrown if there is an exception executing the goal
|
||||
* @throws MojoFailureException thrown if dependency-check is configured to fail the build
|
||||
* @throws MojoExecutionException thrown if there is an exception executing
|
||||
* the goal
|
||||
* @throws MojoFailureException thrown if dependency-check is configured to
|
||||
* fail the build
|
||||
*/
|
||||
@Override
|
||||
public void runCheck() throws MojoExecutionException, MojoFailureException {
|
||||
final Engine engine;
|
||||
MavenEngine engine = null;
|
||||
try {
|
||||
engine = initializeEngine();
|
||||
engine.update();
|
||||
@@ -66,9 +71,21 @@ public class UpdateMojo extends BaseDependencyCheckMojo {
|
||||
if (getLog().isDebugEnabled()) {
|
||||
getLog().debug("Database connection error", ex);
|
||||
}
|
||||
throw new MojoExecutionException("An exception occured connecting to the local database. Please see the log file for more details.", ex);
|
||||
final String msg = "An exception occured connecting to the local database. Please see the log file for more details.";
|
||||
if (this.isFailOnError()) {
|
||||
throw new MojoExecutionException(msg, ex);
|
||||
}
|
||||
getLog().error(msg);
|
||||
} catch (UpdateException ex) {
|
||||
final String msg = "An exception occured while downloading updates. Please see the log file for more details.";
|
||||
if (this.isFailOnError()) {
|
||||
throw new MojoExecutionException(msg, ex);
|
||||
}
|
||||
getLog().error(msg);
|
||||
}
|
||||
if (engine != null) {
|
||||
engine.cleanup();
|
||||
}
|
||||
engine.cleanup();
|
||||
Settings.cleanup();
|
||||
}
|
||||
|
||||
@@ -84,7 +101,8 @@ public class UpdateMojo extends BaseDependencyCheckMojo {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the description of the Dependency-Check report to be displayed in the Maven Generated Reports page.
|
||||
* Gets the description of the Dependency-Check report to be displayed in
|
||||
* the Maven Generated Reports page.
|
||||
*
|
||||
* @param locale The Locale to get the description for
|
||||
* @return the description
|
||||
@@ -93,5 +111,4 @@ public class UpdateMojo extends BaseDependencyCheckMojo {
|
||||
public String getDescription(Locale locale) {
|
||||
return "Updates the local cache of the NVD data from NIST.";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ Property | Description | Default Value
|
||||
autoUpdate | Sets whether auto-updating of the NVD CVE/CPE data is enabled. It is not recommended that this be turned to false. | true
|
||||
cveValidForHours | Sets the number of hours to wait before checking for new updates from the NVD. | 4
|
||||
failBuildOnCVSS | Specifies if the build should be failed if a CVSS score above a specified level is identified. The default is 11 which means since the CVSS scores are 0-10, by default the build will never fail. | 11
|
||||
failOnError | Whether the build should fail if there is an error executing the dependency-check analysis | true
|
||||
format | The report format to be generated (HTML, XML, VULN, ALL). This configuration option has no affect if using this within the Site plugin unless the externalReport is set to true. | HTML
|
||||
name | The name of the report in the site | dependency-check or dependency-check:aggregate
|
||||
outputDirectory | The location to write the report(s). Note, this is not used if generating the report as part of a `mvn site` build | 'target'
|
||||
|
||||
@@ -53,18 +53,16 @@ Create an aggregated dependency-check report within the site.
|
||||
<plugins>
|
||||
...
|
||||
<plugin>
|
||||
<plugin>
|
||||
<groupId>org.owasp</groupId>
|
||||
<artifactId>dependency-check-maven</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<reportSets>
|
||||
<reportSet>
|
||||
<reports>
|
||||
<report>aggregate</report>
|
||||
</reports>
|
||||
</reportSet>
|
||||
</reportSets>
|
||||
</plugin>
|
||||
<groupId>org.owasp</groupId>
|
||||
<artifactId>dependency-check-maven</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<reportSets>
|
||||
<reportSet>
|
||||
<reports>
|
||||
<report>aggregate</report>
|
||||
</reports>
|
||||
</reportSet>
|
||||
</reportSets>
|
||||
</plugin>
|
||||
...
|
||||
</plugins>
|
||||
|
||||
@@ -90,7 +90,7 @@ public class BaseDependencyCheckMojoTest extends BaseTest {
|
||||
|
||||
boolean autoUpdate = Settings.getBoolean(Settings.KEYS.AUTO_UPDATE);
|
||||
Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, false);
|
||||
Engine engine = new Engine(null, null);
|
||||
MavenEngine engine = new MavenEngine(null, null);
|
||||
Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, autoUpdate);
|
||||
|
||||
assertTrue(engine.getDependencies().isEmpty());
|
||||
|
||||
@@ -20,7 +20,7 @@ Copyright (c) 2014 - Jeremy Long. All Rights Reserved.
|
||||
<parent>
|
||||
<groupId>org.owasp</groupId>
|
||||
<artifactId>dependency-check-parent</artifactId>
|
||||
<version>1.4.1-SNAPSHOT</version>
|
||||
<version>1.4.3-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>dependency-check-utils</artifactId>
|
||||
|
||||
@@ -175,7 +175,7 @@ public final class Downloader {
|
||||
}
|
||||
LOGGER.debug("Download of {} complete", url.toString());
|
||||
} catch (IOException ex) {
|
||||
checkForSslExceptionn(ex);
|
||||
checkForCommonExceptionTypes(ex);
|
||||
final String msg = format("Error saving '%s' to file '%s'%nConnection Timeout: %d%nEncoding: %s%n",
|
||||
url.toString(), outputPath.getAbsolutePath(), conn.getConnectTimeout(), encoding);
|
||||
throw new DownloadFailedException(msg, ex);
|
||||
@@ -261,8 +261,9 @@ public final class Downloader {
|
||||
} catch (URLConnectionFailureException ex) {
|
||||
throw new DownloadFailedException(format("Error creating URL Connection for HTTP %s request.", httpMethod), ex);
|
||||
} catch (IOException ex) {
|
||||
checkForSslExceptionn(ex);
|
||||
LOGGER.debug("IO Exception: " + ex.getMessage(), ex);
|
||||
checkForCommonExceptionTypes(ex);
|
||||
LOGGER.error("IO Exception: " + ex.getMessage());
|
||||
LOGGER.debug("Exception details", ex);
|
||||
if (ex.getCause() != null) {
|
||||
LOGGER.debug("IO Exception cause: " + ex.getCause().getMessage(), ex.getCause());
|
||||
}
|
||||
@@ -292,15 +293,21 @@ public final class Downloader {
|
||||
/**
|
||||
* Analyzes the IOException, logs the appropriate information for debugging
|
||||
* purposes, and then throws a DownloadFailedException that wraps the IO
|
||||
* Exception.
|
||||
* Exception for common IO Exceptions. This is to provide additional details
|
||||
* to assist in resolution of the exception.
|
||||
*
|
||||
* @param ex the original exception
|
||||
* @throws DownloadFailedException a wrapper exception that contains the
|
||||
* original exception as the cause
|
||||
*/
|
||||
protected static void checkForSslExceptionn(IOException ex) throws DownloadFailedException {
|
||||
protected static void checkForCommonExceptionTypes(IOException ex) throws DownloadFailedException {
|
||||
Throwable cause = ex;
|
||||
while (cause != null) {
|
||||
if (cause instanceof java.net.UnknownHostException) {
|
||||
final String msg = String.format("Unable to resolve domain '%s'", cause.getMessage());
|
||||
LOGGER.error(msg);
|
||||
throw new DownloadFailedException(msg);
|
||||
}
|
||||
if (cause instanceof InvalidAlgorithmParameterException) {
|
||||
final String keystore = System.getProperty("javax.net.ssl.keyStore");
|
||||
final String version = System.getProperty("java.version");
|
||||
|
||||
@@ -0,0 +1,385 @@
|
||||
package org.owasp.dependencycheck.utils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Socket;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import javax.net.ssl.KeyManager;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLSocket;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* This class is used to enable additional ciphers used by the SSL Socket. This
|
||||
* is specifically because the NVD stopped supporting TLS 1.0 and Java 6 and 7
|
||||
* clients by default were unable to connect to download the NVD data feeds.
|
||||
*
|
||||
* The following code was copied from
|
||||
* http://stackoverflow.com/questions/1037590/which-cipher-suites-to-enable-for-ssl-socket/23365536#23365536
|
||||
*
|
||||
* @author <a href="http://stackoverflow.com/users/608639/jww">jww</a>
|
||||
*/
|
||||
public class SSLSocketFactoryEx extends SSLSocketFactory {
|
||||
|
||||
/**
|
||||
* The Logger for use throughout the class.
|
||||
*/
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(SSLSocketFactoryEx.class);
|
||||
|
||||
/**
|
||||
* Constructs a new SSLSocketFactory.
|
||||
*
|
||||
* @throws NoSuchAlgorithmException thrown when an algorithm is not
|
||||
* supported
|
||||
* @throws KeyManagementException thrown if initialization fails
|
||||
*/
|
||||
public SSLSocketFactoryEx() throws NoSuchAlgorithmException, KeyManagementException {
|
||||
initSSLSocketFactoryEx(null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new SSLSocketFactory.
|
||||
*
|
||||
* @param km the key manager
|
||||
* @param tm the trust manager
|
||||
* @param random secure random
|
||||
* @throws NoSuchAlgorithmException thrown when an algorithm is not
|
||||
* supported
|
||||
* @throws KeyManagementException thrown if initialization fails
|
||||
*/
|
||||
public SSLSocketFactoryEx(KeyManager[] km, TrustManager[] tm, SecureRandom random) throws NoSuchAlgorithmException, KeyManagementException {
|
||||
initSSLSocketFactoryEx(km, tm, random);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new SSLSocketFactory.
|
||||
*
|
||||
* @param ctx the SSL context
|
||||
* @throws NoSuchAlgorithmException thrown when an algorithm is not
|
||||
* supported
|
||||
* @throws KeyManagementException thrown if initialization fails
|
||||
*/
|
||||
public SSLSocketFactoryEx(SSLContext ctx) throws NoSuchAlgorithmException, KeyManagementException {
|
||||
initSSLSocketFactoryEx(ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default cipher suites.
|
||||
*
|
||||
* @return the default cipher suites
|
||||
*/
|
||||
@Override
|
||||
public String[] getDefaultCipherSuites() {
|
||||
return Arrays.copyOf(ciphers, ciphers.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the supported cipher suites.
|
||||
*
|
||||
* @return the supported cipher suites
|
||||
*/
|
||||
@Override
|
||||
public String[] getSupportedCipherSuites() {
|
||||
return Arrays.copyOf(ciphers, ciphers.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default protocols.
|
||||
*
|
||||
* @return the default protocols
|
||||
*/
|
||||
public String[] getDefaultProtocols() {
|
||||
return Arrays.copyOf(protocols, protocols.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the supported protocols.
|
||||
*
|
||||
* @return the supported protocols
|
||||
*/
|
||||
public String[] getSupportedProtocols() {
|
||||
return Arrays.copyOf(protocols, protocols.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an SSL Socket.
|
||||
*
|
||||
* @param s the base socket
|
||||
* @param host the host
|
||||
* @param port the port
|
||||
* @param autoClose if the socket should auto-close
|
||||
* @return the SSL Socket
|
||||
* @throws IOException thrown if the creation fails
|
||||
*/
|
||||
@Override
|
||||
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
|
||||
final SSLSocketFactory factory = sslCtxt.getSocketFactory();
|
||||
final SSLSocket ss = (SSLSocket) factory.createSocket(s, host, port, autoClose);
|
||||
|
||||
ss.setEnabledProtocols(protocols);
|
||||
ss.setEnabledCipherSuites(ciphers);
|
||||
|
||||
return ss;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new SSL Socket.
|
||||
*
|
||||
* @param address the address to connect to
|
||||
* @param port the port number
|
||||
* @param localAddress the local address
|
||||
* @param localPort the local port
|
||||
* @return the SSL Socket
|
||||
* @throws IOException thrown if the creation fails
|
||||
*/
|
||||
@Override
|
||||
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
|
||||
final SSLSocketFactory factory = sslCtxt.getSocketFactory();
|
||||
final SSLSocket ss = (SSLSocket) factory.createSocket(address, port, localAddress, localPort);
|
||||
|
||||
ss.setEnabledProtocols(protocols);
|
||||
ss.setEnabledCipherSuites(ciphers);
|
||||
|
||||
return ss;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new SSL Socket.
|
||||
*
|
||||
* @param host the host to connect to
|
||||
* @param port the port to connect to
|
||||
* @param localHost the local host
|
||||
* @param localPort the local port
|
||||
* @return the SSL Socket
|
||||
* @throws IOException thrown if the creation fails
|
||||
*/
|
||||
@Override
|
||||
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException {
|
||||
final SSLSocketFactory factory = sslCtxt.getSocketFactory();
|
||||
final SSLSocket ss = (SSLSocket) factory.createSocket(host, port, localHost, localPort);
|
||||
|
||||
ss.setEnabledProtocols(protocols);
|
||||
ss.setEnabledCipherSuites(ciphers);
|
||||
|
||||
return ss;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new SSL Socket.
|
||||
*
|
||||
* @param host the host to connect to
|
||||
* @param port the port to connect to
|
||||
* @return the SSL Socket
|
||||
* @throws IOException thrown if the creation fails
|
||||
*/
|
||||
@Override
|
||||
public Socket createSocket(InetAddress host, int port) throws IOException {
|
||||
final SSLSocketFactory factory = sslCtxt.getSocketFactory();
|
||||
final SSLSocket ss = (SSLSocket) factory.createSocket(host, port);
|
||||
|
||||
ss.setEnabledProtocols(protocols);
|
||||
ss.setEnabledCipherSuites(ciphers);
|
||||
|
||||
return ss;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new SSL Socket.
|
||||
*
|
||||
* @param host the host to connect to
|
||||
* @param port the port to connect to
|
||||
* @return the SSL Socket
|
||||
* @throws IOException thrown if the creation fails
|
||||
*/
|
||||
@Override
|
||||
public Socket createSocket(String host, int port) throws IOException {
|
||||
final SSLSocketFactory factory = sslCtxt.getSocketFactory();
|
||||
final SSLSocket ss = (SSLSocket) factory.createSocket(host, port);
|
||||
|
||||
ss.setEnabledProtocols(protocols);
|
||||
ss.setEnabledCipherSuites(ciphers);
|
||||
|
||||
return ss;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the SSL Socket Factory Extension.
|
||||
*
|
||||
* @param km the key managers
|
||||
* @param tm the trust managers
|
||||
* @param random the secure random number generator
|
||||
* @throws NoSuchAlgorithmException thrown when an algorithm is not
|
||||
* supported
|
||||
* @throws KeyManagementException thrown if initialization fails
|
||||
*/
|
||||
private void initSSLSocketFactoryEx(KeyManager[] km, TrustManager[] tm, SecureRandom random)
|
||||
throws NoSuchAlgorithmException, KeyManagementException {
|
||||
sslCtxt = SSLContext.getInstance("TLS");
|
||||
sslCtxt.init(km, tm, random);
|
||||
|
||||
protocols = getProtocolList();
|
||||
ciphers = getCipherList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the SSL Socket Factory Extension.
|
||||
*
|
||||
* @param ctx the SSL context
|
||||
* @throws NoSuchAlgorithmException thrown when an algorithm is not
|
||||
* supported
|
||||
* @throws KeyManagementException thrown if initialization fails
|
||||
*/
|
||||
private void initSSLSocketFactoryEx(SSLContext ctx)
|
||||
throws NoSuchAlgorithmException, KeyManagementException {
|
||||
sslCtxt = ctx;
|
||||
|
||||
protocols = getProtocolList();
|
||||
ciphers = getCipherList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the protocol list.
|
||||
*
|
||||
* @return the protocol list
|
||||
*/
|
||||
protected String[] getProtocolList() {
|
||||
final String[] preferredProtocols = {"TLSv1", "TLSv1.1", "TLSv1.2", "TLSv1.3"};
|
||||
String[] availableProtocols = null;
|
||||
|
||||
SSLSocket socket = null;
|
||||
|
||||
try {
|
||||
final SSLSocketFactory factory = sslCtxt.getSocketFactory();
|
||||
socket = (SSLSocket) factory.createSocket();
|
||||
|
||||
availableProtocols = socket.getSupportedProtocols();
|
||||
Arrays.sort(availableProtocols);
|
||||
} catch (Exception ex) {
|
||||
LOGGER.debug("Error getting protocol list, using TLSv1", ex);
|
||||
return new String[]{"TLSv1"};
|
||||
} finally {
|
||||
if (socket != null) {
|
||||
try {
|
||||
socket.close();
|
||||
} catch (IOException ex) {
|
||||
LOGGER.trace("Error closing socket", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final List<String> aa = new ArrayList<String>();
|
||||
for (String preferredProtocol : preferredProtocols) {
|
||||
final int idx = Arrays.binarySearch(availableProtocols, preferredProtocol);
|
||||
if (idx >= 0) {
|
||||
aa.add(preferredProtocol);
|
||||
}
|
||||
}
|
||||
|
||||
return aa.toArray(new String[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the cipher list.
|
||||
*
|
||||
* @return the cipher list
|
||||
*/
|
||||
protected String[] getCipherList() {
|
||||
final String[] preferredCiphers = {
|
||||
// *_CHACHA20_POLY1305 are 3x to 4x faster than existing cipher suites.
|
||||
// http://googleonlinesecurity.blogspot.com/2014/04/speeding-up-and-strengthening-https.html
|
||||
// Use them if available. Normative names can be found at (TLS spec depends on IPSec spec):
|
||||
// http://tools.ietf.org/html/draft-nir-ipsecme-chacha20-poly1305-01
|
||||
// http://tools.ietf.org/html/draft-mavrogiannopoulos-chacha-tls-02
|
||||
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305",
|
||||
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305",
|
||||
"TLS_ECDHE_ECDSA_WITH_CHACHA20_SHA",
|
||||
"TLS_ECDHE_RSA_WITH_CHACHA20_SHA",
|
||||
"TLS_DHE_RSA_WITH_CHACHA20_POLY1305",
|
||||
"TLS_RSA_WITH_CHACHA20_POLY1305",
|
||||
"TLS_DHE_RSA_WITH_CHACHA20_SHA",
|
||||
"TLS_RSA_WITH_CHACHA20_SHA",
|
||||
// Done with bleeding edge, back to TLS v1.2 and below
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384",
|
||||
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
|
||||
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
|
||||
"TLS_DHE_DSS_WITH_AES_256_GCM_SHA384",
|
||||
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
||||
"TLS_DHE_DSS_WITH_AES_128_GCM_SHA256",
|
||||
// TLS v1.0 (with some SSLv3 interop)
|
||||
"TLS_DHE_RSA_WITH_AES_256_CBC_SHA384",
|
||||
"TLS_DHE_DSS_WITH_AES_256_CBC_SHA256",
|
||||
"TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
|
||||
"TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
|
||||
"TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA",
|
||||
"TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA",
|
||||
"SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA",
|
||||
"SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA",
|
||||
// RSA key transport sucks, but they are needed as a fallback.
|
||||
// For example, microsoft.com fails under all versions of TLS
|
||||
// if they are not included. If only TLS 1.0 is available at
|
||||
// the client, then google.com will fail too. TLS v1.3 is
|
||||
// trying to deprecate them, so it will be interesteng to see
|
||||
// what happens.
|
||||
"TLS_RSA_WITH_AES_256_CBC_SHA256",
|
||||
"TLS_RSA_WITH_AES_256_CBC_SHA",
|
||||
"TLS_RSA_WITH_AES_128_CBC_SHA256",
|
||||
"TLS_RSA_WITH_AES_128_CBC_SHA",
|
||||
};
|
||||
|
||||
String[] availableCiphers;
|
||||
|
||||
try {
|
||||
final SSLSocketFactory factory = sslCtxt.getSocketFactory();
|
||||
availableCiphers = factory.getSupportedCipherSuites();
|
||||
Arrays.sort(availableCiphers);
|
||||
} catch (Exception e) {
|
||||
LOGGER.debug("Error retrieving ciphers", e);
|
||||
return new String[]{
|
||||
"TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
|
||||
"TLS_DHE_DSS_WITH_AES_256_CBC_SHA",
|
||||
"TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
|
||||
"TLS_DHE_RSA_WITH_AES_256_CBC_SHA",
|
||||
"TLS_RSA_WITH_AES_256_CBC_SHA256",
|
||||
"TLS_RSA_WITH_AES_256_CBC_SHA",
|
||||
"TLS_RSA_WITH_AES_128_CBC_SHA256",
|
||||
"TLS_RSA_WITH_AES_128_CBC_SHA",
|
||||
"TLS_EMPTY_RENEGOTIATION_INFO_SCSV",
|
||||
};
|
||||
}
|
||||
|
||||
final List<String> aa = new ArrayList<String>();
|
||||
for (String preferredCipher : preferredCiphers) {
|
||||
final int idx = Arrays.binarySearch(availableCiphers, preferredCipher);
|
||||
if (idx >= 0) {
|
||||
aa.add(preferredCipher);
|
||||
}
|
||||
}
|
||||
|
||||
aa.add("TLS_EMPTY_RENEGOTIATION_INFO_SCSV");
|
||||
|
||||
return aa.toArray(new String[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* The SSL context.
|
||||
*/
|
||||
private SSLContext sslCtxt;
|
||||
/**
|
||||
* The cipher suites.
|
||||
*/
|
||||
private String[] ciphers;
|
||||
/**
|
||||
* The protocols.
|
||||
*/
|
||||
private String[] protocols;
|
||||
}
|
||||
@@ -46,7 +46,8 @@ public final class Settings {
|
||||
public static final class KEYS {
|
||||
|
||||
/**
|
||||
* private constructor because this is a "utility" class containing constants
|
||||
* private constructor because this is a "utility" class containing
|
||||
* constants
|
||||
*/
|
||||
private KEYS() {
|
||||
//do nothing
|
||||
@@ -54,29 +55,34 @@ public final class Settings {
|
||||
/**
|
||||
* The key to obtain the application name.
|
||||
*/
|
||||
public static final String APPLICATION_VAME = "application.name";
|
||||
public static final String APPLICATION_NAME = "application.name";
|
||||
/**
|
||||
* The key to obtain the application version.
|
||||
*/
|
||||
public static final String APPLICATION_VERSION = "application.version";
|
||||
/**
|
||||
* The key to obtain the URL to retrieve the current release version from.
|
||||
* The key to obtain the URL to retrieve the current release version
|
||||
* from.
|
||||
*/
|
||||
public static final String ENGINE_VERSION_CHECK_URL = "engine.version.url";
|
||||
/**
|
||||
* The properties key indicating whether or not the cached data sources should be updated.
|
||||
* The properties key indicating whether or not the cached data sources
|
||||
* should be updated.
|
||||
*/
|
||||
public static final String AUTO_UPDATE = "autoupdate";
|
||||
/**
|
||||
* The database driver class name. If this is not in the properties file the embedded database is used.
|
||||
* The database driver class name. If this is not in the properties file
|
||||
* the embedded database is used.
|
||||
*/
|
||||
public static final String DB_DRIVER_NAME = "data.driver_name";
|
||||
/**
|
||||
* The database driver class name. If this is not in the properties file the embedded database is used.
|
||||
* The database driver class name. If this is not in the properties file
|
||||
* the embedded database is used.
|
||||
*/
|
||||
public static final String DB_DRIVER_PATH = "data.driver_path";
|
||||
/**
|
||||
* The database connection string. If this is not in the properties file the embedded database is used.
|
||||
* The database connection string. If this is not in the properties file
|
||||
* the embedded database is used.
|
||||
*/
|
||||
public static final String DB_CONNECTION_STRING = "data.connection_string";
|
||||
/**
|
||||
@@ -101,36 +107,41 @@ public final class Settings {
|
||||
public static final String DB_VERSION = "data.version";
|
||||
/**
|
||||
* The starts with filter used to exclude CVE entries from the database.
|
||||
* By default this is set to 'cpe:/a:' which limits the CVEs imported to
|
||||
* just those that are related to applications. If this were set to just
|
||||
* 'cpe:' the OS, hardware, and application related CVEs would be imported.
|
||||
* By default this is set to 'cpe:/a:' which limits the CVEs imported to
|
||||
* just those that are related to applications. If this were set to just
|
||||
* 'cpe:' the OS, hardware, and application related CVEs would be
|
||||
* imported.
|
||||
*/
|
||||
public static final String CVE_CPE_STARTS_WITH_FILTER = "cve.cpe.startswith.filter";
|
||||
/**
|
||||
* The properties key for the URL to retrieve the "meta" data from about the CVE entries.
|
||||
* The properties key for the URL to retrieve the "meta" data from about
|
||||
* the CVE entries.
|
||||
*/
|
||||
public static final String CVE_META_URL = "cve.url.meta";
|
||||
/**
|
||||
* The properties key for the URL to retrieve the recently modified and added CVE entries (last 8 days) using the 2.0
|
||||
* schema.
|
||||
* The properties key for the URL to retrieve the recently modified and
|
||||
* added CVE entries (last 8 days) using the 2.0 schema.
|
||||
*/
|
||||
public static final String CVE_MODIFIED_20_URL = "cve.url-2.0.modified";
|
||||
/**
|
||||
* The properties key for the URL to retrieve the recently modified and added CVE entries (last 8 days) using the 1.2
|
||||
* schema.
|
||||
* The properties key for the URL to retrieve the recently modified and
|
||||
* added CVE entries (last 8 days) using the 1.2 schema.
|
||||
*/
|
||||
public static final String CVE_MODIFIED_12_URL = "cve.url-1.2.modified";
|
||||
/**
|
||||
* The properties key for the URL to retrieve the recently modified and added CVE entries (last 8 days).
|
||||
* The properties key for the URL to retrieve the recently modified and
|
||||
* added CVE entries (last 8 days).
|
||||
*/
|
||||
public static final String CVE_MODIFIED_VALID_FOR_DAYS = "cve.url.modified.validfordays";
|
||||
/**
|
||||
* The properties key to control the skipping of the check for CVE updates.
|
||||
* The properties key to control the skipping of the check for CVE
|
||||
* updates.
|
||||
*/
|
||||
public static final String CVE_CHECK_VALID_FOR_HOURS = "cve.check.validforhours";
|
||||
/**
|
||||
* The properties key for the telling us how many cve.url.* URLs exists. This is used in combination with CVE_BASE_URL to
|
||||
* be able to retrieve the URLs for all of the files that make up the NVD CVE listing.
|
||||
* The properties key for the telling us how many cve.url.* URLs exists.
|
||||
* This is used in combination with CVE_BASE_URL to be able to retrieve
|
||||
* the URLs for all of the files that make up the NVD CVE listing.
|
||||
*/
|
||||
public static final String CVE_START_YEAR = "cve.startyear";
|
||||
/**
|
||||
@@ -142,7 +153,8 @@ public final class Settings {
|
||||
*/
|
||||
public static final String CVE_SCHEMA_2_0 = "cve.url-2.0.base";
|
||||
/**
|
||||
* The properties key that indicates how often the CPE data needs to be updated.
|
||||
* The properties key that indicates how often the CPE data needs to be
|
||||
* updated.
|
||||
*/
|
||||
public static final String CPE_MODIFIED_VALID_FOR_DAYS = "cpe.validfordays";
|
||||
/**
|
||||
@@ -152,7 +164,9 @@ public final class Settings {
|
||||
/**
|
||||
* The properties key for the proxy server.
|
||||
*
|
||||
* @deprecated use {@link org.owasp.dependencycheck.utils.Settings.KEYS#PROXY_SERVER} instead.
|
||||
* @deprecated use
|
||||
* {@link org.owasp.dependencycheck.utils.Settings.KEYS#PROXY_SERVER}
|
||||
* instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public static final String PROXY_URL = "proxy.server";
|
||||
@@ -161,7 +175,8 @@ public final class Settings {
|
||||
*/
|
||||
public static final String PROXY_SERVER = "proxy.server";
|
||||
/**
|
||||
* The properties key for the proxy port - this must be an integer value.
|
||||
* The properties key for the proxy port - this must be an integer
|
||||
* value.
|
||||
*/
|
||||
public static final String PROXY_PORT = "proxy.port";
|
||||
/**
|
||||
@@ -209,19 +224,23 @@ public final class Settings {
|
||||
*/
|
||||
public static final String ANALYZER_ARCHIVE_ENABLED = "analyzer.archive.enabled";
|
||||
/**
|
||||
* The properties key for whether the node.js package analyzer is enabled.
|
||||
* The properties key for whether the node.js package analyzer is
|
||||
* enabled.
|
||||
*/
|
||||
public static final String ANALYZER_NODE_PACKAGE_ENABLED = "analyzer.node.package.enabled";
|
||||
/**
|
||||
* The properties key for whether the composer lock file analyzer is enabled.
|
||||
* The properties key for whether the composer lock file analyzer is
|
||||
* enabled.
|
||||
*/
|
||||
public static final String ANALYZER_COMPOSER_LOCK_ENABLED = "analyzer.composer.lock.enabled";
|
||||
/**
|
||||
* The properties key for whether the Python Distribution analyzer is enabled.
|
||||
* The properties key for whether the Python Distribution analyzer is
|
||||
* enabled.
|
||||
*/
|
||||
public static final String ANALYZER_PYTHON_DISTRIBUTION_ENABLED = "analyzer.python.distribution.enabled";
|
||||
/**
|
||||
* The properties key for whether the Python Package analyzer is enabled.
|
||||
* The properties key for whether the Python Package analyzer is
|
||||
* enabled.
|
||||
*/
|
||||
public static final String ANALYZER_PYTHON_PACKAGE_ENABLED = "analyzer.python.package.enabled";
|
||||
/**
|
||||
@@ -237,7 +256,8 @@ public final class Settings {
|
||||
*/
|
||||
public static final String ANALYZER_CMAKE_ENABLED = "analyzer.cmake.enabled";
|
||||
/**
|
||||
* The properties key for whether the Ruby Bundler Audit analyzer is enabled.
|
||||
* The properties key for whether the Ruby Bundler Audit analyzer is
|
||||
* enabled.
|
||||
*/
|
||||
public static final String ANALYZER_BUNDLE_AUDIT_ENABLED = "analyzer.bundle.audit.enabled";
|
||||
/**
|
||||
@@ -339,7 +359,8 @@ public final class Settings {
|
||||
private Properties props = null;
|
||||
|
||||
/**
|
||||
* Private constructor for the Settings class. This class loads the properties files.
|
||||
* Private constructor for the Settings class. This class loads the
|
||||
* properties files.
|
||||
*
|
||||
* @param propertiesFilePath the path to the base properties file to load
|
||||
*/
|
||||
@@ -365,16 +386,18 @@ public final class Settings {
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the thread local settings object. Note, to use the settings object you must call this method. However, you must
|
||||
* also call Settings.cleanup() to properly release resources.
|
||||
* Initializes the thread local settings object. Note, to use the settings
|
||||
* object you must call this method. However, you must also call
|
||||
* Settings.cleanup() to properly release resources.
|
||||
*/
|
||||
public static void initialize() {
|
||||
LOCAL_SETTINGS.set(new Settings(PROPERTIES_FILE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the thread local settings object. Note, to use the settings object you must call this method. However, you must
|
||||
* also call Settings.cleanup() to properly release resources.
|
||||
* Initializes the thread local settings object. Note, to use the settings
|
||||
* object you must call this method. However, you must also call
|
||||
* Settings.cleanup() to properly release resources.
|
||||
*
|
||||
* @param propertiesFilePath the path to the base properties file to load
|
||||
*/
|
||||
@@ -393,7 +416,8 @@ public final class Settings {
|
||||
/**
|
||||
* Cleans up resources to prevent memory leaks.
|
||||
*
|
||||
* @param deleteTemporary flag indicating whether any temporary directories generated should be removed
|
||||
* @param deleteTemporary flag indicating whether any temporary directories
|
||||
* generated should be removed
|
||||
*/
|
||||
public static void cleanup(boolean deleteTemporary) {
|
||||
if (deleteTemporary && tempDirectory != null && tempDirectory.exists()) {
|
||||
@@ -433,7 +457,8 @@ public final class Settings {
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs the properties. This will not log any properties that contain 'password' in the key.
|
||||
* Logs the properties. This will not log any properties that contain
|
||||
* 'password' in the key.
|
||||
*
|
||||
* @param header the header to print with the log message
|
||||
* @param properties the properties to log
|
||||
@@ -549,13 +574,16 @@ public final class Settings {
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges a new properties file into the current properties. This method allows for the loading of a user provided properties
|
||||
* file.<br><br>
|
||||
* <b>Note</b>: even if using this method - system properties will be loaded before properties loaded from files.
|
||||
* Merges a new properties file into the current properties. This method
|
||||
* allows for the loading of a user provided properties file.<br><br>
|
||||
* <b>Note</b>: 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
|
||||
* @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(File filePath) throws FileNotFoundException, IOException {
|
||||
FileInputStream fis = null;
|
||||
@@ -574,13 +602,16 @@ public final class Settings {
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges a new properties file into the current properties. This method allows for the loading of a user provided properties
|
||||
* file.<br><br>
|
||||
* Note: even if using this method - system properties will be loaded before properties loaded from files.
|
||||
* Merges a new properties file into the current properties. This method
|
||||
* allows for the loading of a user provided properties file.<br><br>
|
||||
* 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
|
||||
* @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 = null;
|
||||
@@ -599,12 +630,14 @@ public final class Settings {
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges a new properties file into the current properties. This method allows for the loading of a user provided properties
|
||||
* file.<br><br>
|
||||
* <b>Note</b>: even if using this method - system properties will be loaded before properties loaded from files.
|
||||
* Merges a new properties file into the current properties. This method
|
||||
* allows for the loading of a user provided properties file.<br><br>
|
||||
* <b>Note</b>: 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
|
||||
* @throws IOException is thrown when there is an exception loading/merging
|
||||
* the properties
|
||||
*/
|
||||
public static void mergeProperties(InputStream stream) throws IOException {
|
||||
LOCAL_SETTINGS.get().props.load(stream);
|
||||
@@ -612,9 +645,10 @@ public final class Settings {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a value from the properties file as a File object. 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.
|
||||
* Returns a value from the properties file as a File object. 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 converted to a File object
|
||||
@@ -628,13 +662,15 @@ public final class Settings {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a value from the properties file as a File object. 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.
|
||||
* Returns a value from the properties file as a File object. 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.
|
||||
*
|
||||
* This method will check the configured base directory and will use this as the base of the file path. Additionally, if the
|
||||
* base directory begins with a leading "[JAR]\" sequence with the path to the folder containing the JAR file containing this
|
||||
* class.
|
||||
* This method will check the configured base directory and will use this as
|
||||
* the base of the file path. Additionally, if the base directory begins
|
||||
* with a leading "[JAR]\" sequence with the path to the folder containing
|
||||
* the JAR file containing this class.
|
||||
*
|
||||
* @param key the key to lookup within the properties file
|
||||
* @return the property from the properties file converted to a File object
|
||||
@@ -657,7 +693,8 @@ public final class Settings {
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to retrieve the folder containing the Jar file containing the Settings class.
|
||||
* Attempts to retrieve the folder containing the Jar file containing the
|
||||
* Settings class.
|
||||
*
|
||||
* @return a File object
|
||||
*/
|
||||
@@ -679,9 +716,10 @@ public final 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.
|
||||
* 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
|
||||
@@ -693,7 +731,8 @@ public final class Settings {
|
||||
}
|
||||
|
||||
/**
|
||||
* A reference to the temporary directory; used incase it needs to be deleted during cleanup.
|
||||
* A reference to the temporary directory; used incase it needs to be
|
||||
* deleted during cleanup.
|
||||
*/
|
||||
private static File tempDirectory = null;
|
||||
|
||||
@@ -701,7 +740,8 @@ public final class Settings {
|
||||
* Returns the temporary directory.
|
||||
*
|
||||
* @return the temporary directory
|
||||
* @throws java.io.IOException thrown if the temporary directory does not exist and cannot be created
|
||||
* @throws java.io.IOException thrown if the temporary directory does not
|
||||
* exist and cannot be created
|
||||
*/
|
||||
public static File getTempDirectory() throws IOException {
|
||||
final File tmpDir = new File(Settings.getString(Settings.KEYS.TEMP_DIRECTORY, System.getProperty("java.io.tmpdir")), "dctemp");
|
||||
@@ -714,9 +754,10 @@ public final 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.
|
||||
* 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
|
||||
* @return the property from the properties file
|
||||
@@ -726,7 +767,8 @@ public final class Settings {
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a property from the local properties collection. This is mainly used in test cases.
|
||||
* Removes a property from the local properties collection. This is mainly
|
||||
* used in test cases.
|
||||
*
|
||||
* @param key the property key to remove
|
||||
*/
|
||||
@@ -735,13 +777,15 @@ public final class Settings {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* 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.
|
||||
*
|
||||
* @param key the key to lookup within the properties file
|
||||
* @return the property from the properties file
|
||||
* @throws InvalidSettingException is thrown if there is an error retrieving the setting
|
||||
* @throws InvalidSettingException is thrown if there is an error retrieving
|
||||
* the setting
|
||||
*/
|
||||
public static int getInt(String key) throws InvalidSettingException {
|
||||
try {
|
||||
@@ -752,14 +796,15 @@ public final class Settings {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* 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.
|
||||
*
|
||||
* @param key the key to lookup within the properties file
|
||||
* @param defaultValue the default value to return
|
||||
* @return the property from the properties file or the defaultValue if the property does not exist or cannot be converted to
|
||||
* an integer
|
||||
* @return the property from the properties file or the defaultValue if the
|
||||
* property does not exist or cannot be converted to an integer
|
||||
*/
|
||||
public static int getInt(String key, int defaultValue) {
|
||||
int value;
|
||||
@@ -775,13 +820,15 @@ public final class Settings {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* 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
|
||||
* @throws InvalidSettingException is thrown if there is an error retrieving the setting
|
||||
* @throws InvalidSettingException is thrown if there is an error retrieving
|
||||
* the setting
|
||||
*/
|
||||
public static long getLong(String key) throws InvalidSettingException {
|
||||
try {
|
||||
@@ -792,38 +839,47 @@ public final class Settings {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a boolean value from the properties file. If the value was specified as a system property or passed in via the
|
||||
* <code>-Dprop=value</code> argument this method will return the value from the system properties before the values in the
|
||||
* contained configuration file.
|
||||
* Returns a boolean value from the properties file. If the value was
|
||||
* specified as a system property or passed in via the
|
||||
* <code>-Dprop=value</code> 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
|
||||
* @throws InvalidSettingException is thrown if there is an error retrieving the setting
|
||||
* @throws InvalidSettingException is thrown if there is an error retrieving
|
||||
* the setting
|
||||
*/
|
||||
public static boolean getBoolean(String key) throws InvalidSettingException {
|
||||
return Boolean.parseBoolean(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
|
||||
* <code>-Dprop=value</code> argument this method will return the value from the system properties before the values in the
|
||||
* contained configuration file.
|
||||
* Returns a boolean value from the properties file. If the value was
|
||||
* specified as a system property or passed in via the
|
||||
* <code>-Dprop=value</code> 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 to return if the setting does not exist
|
||||
* @param defaultValue the default value to return if the setting does not
|
||||
* exist
|
||||
* @return the property from the properties file
|
||||
* @throws InvalidSettingException is thrown if there is an error retrieving the setting
|
||||
* @throws InvalidSettingException is thrown if there is an error retrieving
|
||||
* the setting
|
||||
*/
|
||||
public static boolean getBoolean(String key, boolean defaultValue) throws InvalidSettingException {
|
||||
return Boolean.parseBoolean(Settings.getString(key, Boolean.toString(defaultValue)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a connection string from the configured properties. If the connection string contains a %s, this method will
|
||||
* determine the 'data' directory and replace the %s with the path to the data directory. If the data directory does not
|
||||
* exists it will be created.
|
||||
* Returns a connection string from the configured properties. If the
|
||||
* connection string contains a %s, this method will determine the 'data'
|
||||
* directory and replace the %s with the path to the data directory. If the
|
||||
* data directory does not exists it will be created.
|
||||
*
|
||||
* @param connectionStringKey the property file key for the connection string
|
||||
* @param connectionStringKey the property file key for the connection
|
||||
* string
|
||||
* @param dbFileNameKey the settings key for the db filename
|
||||
* @return the connection string
|
||||
* @throws IOException thrown the data directory cannot be created
|
||||
@@ -860,8 +916,9 @@ public final class Settings {
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the directory that the JAR file exists in so that we can ensure we always use a common data directory for the
|
||||
* embedded H2 database. This is public solely for some unit tests; otherwise this should be private.
|
||||
* Retrieves the directory that the JAR file exists in so that we can ensure
|
||||
* we always use a common data directory for the embedded H2 database. This
|
||||
* is public solely for some unit tests; otherwise this should be private.
|
||||
*
|
||||
* @return the data directory to store data files
|
||||
* @throws IOException is thrown if an IOException occurs of course...
|
||||
|
||||
@@ -28,15 +28,28 @@ import java.net.PasswordAuthentication;
|
||||
import java.net.Proxy;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.URL;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
import org.apache.commons.lang3.JavaVersion;
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* A URLConnection Factory to create new connections. This encapsulates several configuration checks to ensure that the connection
|
||||
* uses the correct proxy settings.
|
||||
* A URLConnection Factory to create new connections. This encapsulates several
|
||||
* configuration checks to ensure that the connection uses the correct proxy
|
||||
* settings.
|
||||
*
|
||||
* @author Jeremy Long
|
||||
*/
|
||||
public final class URLConnectionFactory {
|
||||
|
||||
/**
|
||||
* The logger.
|
||||
*/
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(URLConnectionFactory.class);
|
||||
|
||||
/**
|
||||
* Private constructor for this factory.
|
||||
*/
|
||||
@@ -44,8 +57,9 @@ public final class URLConnectionFactory {
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to create an HttpURLConnection. If the application is configured to use a proxy this method will retrieve
|
||||
* the proxy settings and use them when setting up the connection.
|
||||
* Utility method to create an HttpURLConnection. If the application is
|
||||
* configured to use a proxy this method will retrieve the proxy settings
|
||||
* and use them when setting up the connection.
|
||||
*
|
||||
* @param url the url to connect to
|
||||
* @return an HttpURLConnection
|
||||
@@ -95,6 +109,7 @@ public final class URLConnectionFactory {
|
||||
}
|
||||
throw new URLConnectionFailureException("Error getting connection.", ex);
|
||||
}
|
||||
configureTLS(url, conn);
|
||||
return conn;
|
||||
}
|
||||
|
||||
@@ -140,8 +155,10 @@ public final class URLConnectionFactory {
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to create an HttpURLConnection. The use of a proxy here is optional as there may be cases where a proxy is
|
||||
* configured but we don't want to use it (for example, if there's an internal repository configured)
|
||||
* Utility method to create an HttpURLConnection. The use of a proxy here is
|
||||
* optional as there may be cases where a proxy is configured but we don't
|
||||
* want to use it (for example, if there's an internal repository
|
||||
* configured)
|
||||
*
|
||||
* @param url the URL to connect to
|
||||
* @param proxy whether to use the proxy (if configured)
|
||||
@@ -161,6 +178,29 @@ public final class URLConnectionFactory {
|
||||
} catch (IOException ioe) {
|
||||
throw new URLConnectionFailureException("Error getting connection.", ioe);
|
||||
}
|
||||
configureTLS(url, conn);
|
||||
return conn;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the protocol is HTTPS, this will configure the cipher suites so that
|
||||
* connections can be made to the NVD, and others, using older versions of
|
||||
* Java.
|
||||
*
|
||||
* @param url the URL
|
||||
* @param conn the connection
|
||||
*/
|
||||
private static void configureTLS(URL url, HttpURLConnection conn) {
|
||||
if ("https".equals(url.getProtocol()) && !SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_1_8)) {
|
||||
try {
|
||||
final HttpsURLConnection secCon = (HttpsURLConnection) conn;
|
||||
final SSLSocketFactoryEx factory = new SSLSocketFactoryEx();
|
||||
secCon.setSSLSocketFactory(factory);
|
||||
} catch (NoSuchAlgorithmException ex) {
|
||||
LOGGER.debug("Unsupported algorithm in SSLSocketFactoryEx", ex);
|
||||
} catch (KeyManagementException ex) {
|
||||
LOGGER.debug("Key mnagement eception in SSLSocketFactoryEx", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
2
pom.xml
2
pom.xml
@@ -20,7 +20,7 @@ Copyright (c) 2012 - Jeremy Long
|
||||
|
||||
<groupId>org.owasp</groupId>
|
||||
<artifactId>dependency-check-parent</artifactId>
|
||||
<version>1.4.1-SNAPSHOT</version>
|
||||
<version>1.4.3-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<modules>
|
||||
|
||||
@@ -28,11 +28,12 @@ More information about dependency-check can be found here:
|
||||
|
||||
OWASP dependency-check's core analysis engine can be used as:
|
||||
|
||||
- [Command Line Tool](dependency-check-cli/index.html)
|
||||
- [Maven Plugin](dependency-check-maven/index.html)
|
||||
- [Ant Task](dependency-check-ant/index.html)
|
||||
- [Command Line Tool](dependency-check-cli/index.html)
|
||||
- [Gradle Plugin](dependency-check-gradle/index.html)
|
||||
- [Jenkins Plugin](dependency-check-jenkins/index.html)
|
||||
- [Maven Plugin](dependency-check-maven/index.html)
|
||||
- [SBT Plugin](https://github.com/albuch/sbt-dependency-check)
|
||||
|
||||
For help with dependency-check the following resource can be used:
|
||||
|
||||
|
||||
@@ -3,10 +3,12 @@ Modules
|
||||
OWASP dependency-check's core analysis engine was designed to fit into an applications normal
|
||||
build and reporting process:
|
||||
|
||||
- [Maven Plugin](dependency-check-maven/index.html)
|
||||
- [Ant Task](dependency-check-ant/index.html)
|
||||
- [Gradle Plugin](dependency-check-gradle/index.html)
|
||||
- [Jenkins Plugin](dependency-check-jenkins/index.html)
|
||||
- [Ant Task](dependency-check-ant/index.html)
|
||||
- [Command Line Tool](dependency-check-cli/index.html)
|
||||
- [Gradle Plugin](dependency-check-gradle/index.html)
|
||||
- [Jenkins Plugin](dependency-check-jenkins/index.html)
|
||||
- [Maven Plugin](dependency-check-maven/index.html)
|
||||
- [SBT Plugin](https://github.com/albuch/sbt-dependency-check)
|
||||
|
||||
In addition, dependency-check can be executed from the [command line](dependency-check-cli/index.html).
|
||||
|
||||
|
||||
Reference in New Issue
Block a user