Compare commits

..

66 Commits

Author SHA1 Message Date
Jeremy Long
d22c920b35 version 1.4.1 2016-07-30 06:52:48 -04:00
Jeremy Long
f7a0982ca0 checkstyle corrections 2016-07-29 06:12:40 -04:00
Jeremy Long
bed04150e1 reverted H2 upgrade due to issues with Jenkins and Java 6 compatability 2016-07-27 06:23:56 -04:00
Jeremy Long
ba15de2218 improved error handling 2016-07-27 06:04:56 -04:00
Jeremy Long
e9ec89dc9c improved error handling 2016-07-27 06:04:08 -04:00
Jeremy Long
d09f75658c minor formating correction 2016-07-24 08:47:27 -04:00
Jeremy Long
62f92db181 added issue template 2016-07-24 08:44:09 -04:00
Jeremy Long
27a98f4244 checckstyle corrections 2016-07-24 08:12:57 -04:00
Jeremy Long
f0a3482eda findbugs correction 2016-07-24 08:07:39 -04:00
Jeremy Long
5f76843c4a findbugs correction 2016-07-24 08:06:54 -04:00
Jeremy Long
c6ea92cff9 added links to the SBT plugin 2016-07-24 07:33:28 -04:00
Jeremy Long
c253308284 checkstyle corrections 2016-07-23 07:45:48 -04:00
Jeremy Long
9ae9c111e3 checkstyle corrections 2016-07-23 07:13:09 -04:00
Jeremy Long
4894372eee minor code quality issues corrected 2016-07-23 06:50:11 -04:00
Jeremy Long
7cf040653f upgraded h2 db version 2016-07-22 06:29:01 -04:00
Jeremy Long
034bd4dba0 testing fix to resolve connection issues with NVD 2016-07-19 07:04:24 -04:00
Jeremy Long
af12a2161c testing fix to resolve connection issues with NVD 2016-07-19 06:54:25 -04:00
Jeremy Long
57fcf6fde3 testing connection errors 2016-07-17 08:18:47 -04:00
Jeremy Long
c5757dc5f4 updates to resolve issue #215 2016-07-17 07:19:56 -04:00
Jeremy Long
6d5d5ceb7b Updated exception handling so that issue #215 can be resolved 2016-07-14 06:31:54 -04:00
Jeremy Long
f23003ead3 fields can be final 2016-07-10 07:13:08 -04:00
Jeremy Long
c996f6b436 improved exception handling as part of resolution for #215 2016-07-10 07:12:43 -04:00
Jeremy Long
d2ee66a1c4 there was no need to extend IOException 2016-07-10 07:11:03 -04:00
Jeremy Long
26b0dd5ef5 updated javadoc 2016-07-10 06:56:26 -04:00
Jeremy Long
ad4149a259 updated documentation for PR #528 2016-07-10 06:27:40 -04:00
Jeremy Long
9611c3b478 Merge pull request #528 from felfert/master
Thanks for the PR!
2016-07-10 06:13:09 -04:00
Jeremy Long
cead88d221 reworked initialization exceptions as part of planned resolution for issue #215 2016-07-09 07:39:00 -04:00
Jeremy Long
c1e1a6bb4f cleaned up imports 2016-07-09 07:35:36 -04:00
Fritz Elfert
6212a5f740 Compatibility fixes for MariaDB JDBC driver 2016-07-08 22:27:10 +02:00
Jeremy Long
b3d9ea3c47 minor code reorg 2016-07-07 06:18:54 -04:00
Jeremy Long
cd51989354 Merge pull request #526 from nicolastrres/master
Updating gradle dependencyCheck documentation
2016-07-07 06:05:12 -04:00
nicolastrres
b705ae5f0c Updating gradle dependencyCheck documentation 2016-07-06 14:57:24 -03:00
Jeremy Long
13b53537fa incorrectly set quick query value during recheck - see issue #523 2016-07-06 06:48:10 -04:00
Jeremy Long
7d05aa6073 added logging for issue #523 2016-07-06 06:44:43 -04:00
Jeremy Long
85de173086 fixed StackOverflowError from issue #523 2016-07-06 06:32:57 -04:00
Jeremy Long
d264d804c8 patches and test case update for issue #522 2016-07-05 09:09:58 -04:00
Jeremy Long
8272da615e improved test cases to debug issue #522 2016-07-04 08:43:43 -04:00
Jeremy Long
857b993d51 ensured analyzers were correctly initialized and closed 2016-07-04 07:55:53 -04:00
Jeremy Long
a71edf584e additional testing added 2016-07-04 07:55:19 -04:00
Jeremy Long
461d7fec0e fixed typo 2016-07-04 07:54:57 -04:00
Jeremy Long
5e3da035dd resolved merge conflict with #525 2016-07-04 07:11:45 -04:00
Jeremy Long
ebb52995a5 converted hint analyzer to use an externalized configuration file to simplify the resolution of issue #522 2016-07-04 07:10:07 -04:00
Jeremy Long
519b82c620 minor cleanup of code/comments 2016-07-04 07:07:07 -04:00
Jeremy Long
84682d07c6 converted hint analyzer to use an externalized configuration file to simplify the resolution of issue #522 2016-07-04 07:06:17 -04:00
Jeremy Long
960eeb19af converted hint analyzer to use an externalized configuration file to simplify the resolution of issue #522 2016-07-04 07:05:31 -04:00
Hans Joachim Desserud
ab3920f8f1 Replace raw Iterator with for each 2016-07-02 16:29:32 +02:00
Hans Joachim Desserud
f5f5857897 Add missing @Overrides 2016-07-02 16:23:24 +02:00
Hans Joachim Desserud
1c400b410e Remove unused imports 2016-07-02 16:23:16 +02:00
Jeremy Long
cc751aa224 updated to skip custom scripts in executable scripts 2016-06-27 19:39:17 -04:00
Jeremy Long
c20892ee3e removed stack traces from build 2016-06-27 08:46:46 -04:00
Jeremy Long
32ab53c9e1 Merge branch 'master' of github.com:jeremylong/DependencyCheck 2016-06-26 07:32:23 -04:00
Jeremy Long
d0a7d9eb42 added test for issue #454 to ensure fully executable jar 2016-06-26 07:32:10 -04:00
Jeremy Long
a1a9602509 added support for fully executable jar files per issue #454 2016-06-26 07:31:17 -04:00
Jeremy Long
cf97c89fe0 fully exectuable jar for testing resolution for issue #454 2016-06-26 07:30:39 -04:00
Jeremy Long
8895bc85ea Merge pull request #521 from awhitford/Upg20160624
Plugin and Dependency Upgrades
2016-06-25 06:53:49 -04:00
Anthony Whitford
1a9976c6ca commons-compress 1.12, maven-jar-plugin 3.0.2, maven-source-plugin 3.0.1, maven-javadoc-plugin 2.10.4. 2016-06-24 23:51:12 -07:00
Anthony Whitford
f47ebf6145 jMockit 1.24, jSoup 1.9.2. 2016-06-24 23:35:24 -07:00
Jeremy Long
0380715311 resolved issue #514 2016-06-24 07:09:10 -04:00
Jeremy Long
80ad16c7fa updated to correctly label groovy's dependency scope 2016-06-22 06:48:11 -04:00
Jeremy Long
e56e9035b6 updated to correctly label groovy's dependency scope 2016-06-22 06:38:10 -04:00
Jeremy Long
73f22d32d2 fixed typo 2016-06-22 06:34:50 -04:00
Jeremy Long
c3bc56eebc additional suppressions 2016-06-18 07:33:30 -04:00
Jeremy Long
35cc14815e added property to solve issue #500 2016-06-18 07:32:57 -04:00
Jeremy Long
9be91474f6 staging 2016-06-18 06:46:28 -04:00
Jeremy Long
adf949bf08 added logging of URL 2016-06-18 06:18:16 -04:00
Jeremy Long
c6bf41b8ba staging 2016-06-18 06:17:55 -04:00
125 changed files with 3912 additions and 941 deletions

18
.github/issue_template.md vendored Normal file
View 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>
```

View File

@@ -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.0</version>
<version>1.4.1</version>
</parent>
<artifactId>dependency-check-ant</artifactId>

View File

@@ -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) {

View File

@@ -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 {

View File

@@ -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.
*/

View File

@@ -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

View File

@@ -24,6 +24,7 @@ proxyPort | The Proxy Port. | &nbsp;
proxyUsername | Defines the proxy user name. | &nbsp;
proxyPassword | Defines the proxy password. | &nbsp;
connectionTimeout | The URL Connection Timeout. | &nbsp;
failOnError | Whether the build should fail if there is an error executing the update | true
Advanced Configuration
====================

View File

@@ -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'

View File

@@ -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.0</version>
<version>1.4.1</version>
</parent>
<artifactId>dependency-check-cli</artifactId>

View File

@@ -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 &amp; 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 &amp; 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("?")) {

View File

@@ -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.0</version>
<version>1.4.1</version>
</parent>
<artifactId>dependency-check-core</artifactId>
@@ -459,6 +459,13 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
<scope>test</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.8</version>
<scope>test</scope>
<optional>true</optional>
</dependency>
</dependencies>
<profiles>
<profile>
@@ -587,13 +594,6 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
<scope>test</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.2</version>
<scope>test</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.apache.ws.security</groupId>
<artifactId>wss4j</artifactId>

View File

@@ -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
*/
@@ -61,15 +65,16 @@ public class Engine implements FileFilter {
/**
* A Map of analyzers grouped by Analysis phase.
*/
private Map<AnalysisPhase, List<Analyzer>> analyzers = new EnumMap<AnalysisPhase, List<Analyzer>>(AnalysisPhase.class);
private final Map<AnalysisPhase, List<Analyzer>> analyzers = new EnumMap<AnalysisPhase, List<Analyzer>>(AnalysisPhase.class);
/**
* A Map of analyzers grouped by Analysis phase.
*/
private Set<FileTypeAnalyzer> fileTypeAnalyzers = new HashSet<FileTypeAnalyzer>();
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();

View File

@@ -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
*/

View File

@@ -17,7 +17,11 @@
*/
package org.owasp.dependencycheck.analyzer;
import org.owasp.dependencycheck.exception.InitializationException;
/**
* Base class for analyzers to avoid code duplication of initialize and close
* as most analyzers do not need these methods.
*
* @author Jeremy Long
*/
@@ -26,10 +30,10 @@ public abstract class AbstractAnalyzer implements Analyzer {
/**
* The initialize method does nothing for this Analyzer.
*
* @throws Exception thrown if there is an exception
* @throws InitializationException thrown if there is an exception
*/
@Override
public void initialize() throws Exception {
public void initialize() throws InitializationException {
//do nothing
}

View File

@@ -30,9 +30,11 @@ import java.io.FileFilter;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.owasp.dependencycheck.exception.InitializationException;
/**
* The base FileTypeAnalyzer that all analyzers that have specific file types they analyze should extend.
* The base FileTypeAnalyzer that all analyzers that have specific file types
* they analyze should extend.
*
* @author Jeremy Long
*/
@@ -40,7 +42,8 @@ public abstract class AbstractFileTypeAnalyzer extends AbstractAnalyzer implemen
//<editor-fold defaultstate="collapsed" desc="Constructor">
/**
* Base constructor that all children must call. This checks the configuration to determine if the analyzer is enabled.
* Base constructor that all children must call. This checks the
* configuration to determine if the analyzer is enabled.
*/
public AbstractFileTypeAnalyzer() {
reset();
@@ -58,7 +61,8 @@ public abstract class AbstractFileTypeAnalyzer extends AbstractAnalyzer implemen
private boolean filesMatched = false;
/**
* Get the value of filesMatched. A flag indicating whether the scan included any file types this analyzer supports.
* Get the value of filesMatched. A flag indicating whether the scan
* included any file types this analyzer supports.
*
* @return the value of filesMatched
*/
@@ -67,7 +71,8 @@ public abstract class AbstractFileTypeAnalyzer extends AbstractAnalyzer implemen
}
/**
* Set the value of filesMatched. A flag indicating whether the scan included any file types this analyzer supports.
* Set the value of filesMatched. A flag indicating whether the scan
* included any file types this analyzer supports.
*
* @param filesMatched new value of filesMatched
*/
@@ -102,11 +107,13 @@ public abstract class AbstractFileTypeAnalyzer extends AbstractAnalyzer implemen
//<editor-fold defaultstate="collapsed" desc="Abstract methods children must implement">
/**
* <p>
* Returns the {@link java.io.FileFilter} used to determine which files are to be analyzed. An example would be an analyzer
* that inspected Java jar files. Implementors may use {@link org.owasp.dependencycheck.utils.FileFilterBuilder}.</p>
* Returns the {@link java.io.FileFilter} used to determine which files are
* to be analyzed. An example would be an analyzer that inspected Java jar
* files. Implementors may use
* {@link org.owasp.dependencycheck.utils.FileFilterBuilder}.</p>
* <p>
* If the analyzer returns null it will not cause additional files to be analyzed, but will be executed against every file
* loaded.</p>
* If the analyzer returns null it will not cause additional files to be
* analyzed, but will be executed against every file loaded.</p>
*
* @return the file filter used to determine which files are to be analyzed
*/
@@ -115,13 +122,15 @@ public abstract class AbstractFileTypeAnalyzer extends AbstractAnalyzer implemen
/**
* Initializes the file type analyzer.
*
* @throws Exception thrown if there is an exception during initialization
* @throws InitializationException thrown if there is an exception during
* initialization
*/
protected abstract void initializeFileTypeAnalyzer() throws Exception;
protected abstract void initializeFileTypeAnalyzer() throws InitializationException;
/**
* Analyzes a given dependency. If the dependency is an archive, such as a WAR or EAR, the contents are extracted, scanned,
* and added to the list of dependencies within the engine.
* Analyzes a given dependency. If the dependency is an archive, such as a
* WAR or EAR, the contents are extracted, scanned, and added to the list of
* dependencies within the engine.
*
* @param dependency the dependency to analyze
* @param engine the engine scanning
@@ -142,10 +151,11 @@ public abstract class AbstractFileTypeAnalyzer extends AbstractAnalyzer implemen
/**
* Initializes the analyzer.
*
* @throws Exception thrown if there is an exception during initialization
* @throws InitializationException thrown if there is an exception during
* initialization
*/
@Override
public final void initialize() throws Exception {
public final void initialize() throws InitializationException {
if (filesMatched) {
initializeFileTypeAnalyzer();
} else {
@@ -169,8 +179,9 @@ public abstract class AbstractFileTypeAnalyzer extends AbstractAnalyzer implemen
}
/**
* Analyzes a given dependency. If the dependency is an archive, such as a WAR or EAR, the contents are extracted, scanned,
* and added to the list of dependencies within the engine.
* Analyzes a given dependency. If the dependency is an archive, such as a
* WAR or EAR, the contents are extracted, scanned, and added to the list of
* dependencies within the engine.
*
* @param dependency the dependency to analyze
* @param engine the engine scanning
@@ -202,8 +213,8 @@ public abstract class AbstractFileTypeAnalyzer extends AbstractAnalyzer implemen
//<editor-fold defaultstate="collapsed" desc="Static utility methods">
/**
* <p>
* Utility method to help in the creation of the extensions set. This constructs a new Set that can be used in a final static
* declaration.</p>
* Utility method to help in the creation of the extensions set. This
* constructs a new Set that can be used in a final static declaration.</p>
* <p>
* This implementation was copied from
* http://stackoverflow.com/questions/2041778/initialize-java-hashset-values-by-construction</p>

View File

@@ -25,9 +25,10 @@ import java.net.URL;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;
import org.owasp.dependencycheck.suppression.SuppressionParseException;
import org.owasp.dependencycheck.suppression.SuppressionParser;
import org.owasp.dependencycheck.suppression.SuppressionRule;
import org.owasp.dependencycheck.exception.InitializationException;
import org.owasp.dependencycheck.xml.suppression.SuppressionParseException;
import org.owasp.dependencycheck.xml.suppression.SuppressionParser;
import org.owasp.dependencycheck.xml.suppression.SuppressionRule;
import org.owasp.dependencycheck.utils.DownloadFailedException;
import org.owasp.dependencycheck.utils.Downloader;
import org.owasp.dependencycheck.utils.FileUtils;
@@ -63,12 +64,16 @@ public abstract class AbstractSuppressionAnalyzer extends AbstractAnalyzer {
/**
* The initialize method loads the suppression XML file.
*
* @throws Exception thrown if there is an exception
* @throws InitializationException thrown if there is an exception
*/
@Override
public void initialize() throws Exception {
public void initialize() throws InitializationException {
super.initialize();
loadSuppressionData();
try {
loadSuppressionData();
} catch (SuppressionParseException ex) {
throw new InitializationException("Error initializing the suppression analyzer", ex);
}
}
/**
@@ -104,12 +109,8 @@ public abstract class AbstractSuppressionAnalyzer extends AbstractAnalyzer {
File file = null;
try {
rules = parser.parseSuppressionRules(this.getClass().getClassLoader().getResourceAsStream("dependencycheck-base-suppression.xml"));
} catch (SuppressionParseException ex) {
LOGGER.error("Unable to parse the base suppression data file");
LOGGER.debug("Unable to parse the base suppression data file", ex);
} catch (SAXException ex) {
LOGGER.error("Unable to parse the base suppression data file");
LOGGER.debug("Unable to parse the base suppression data file", ex);
throw new SuppressionParseException("Unable to parse the base suppression data file", ex);
}
final String suppressionFilePath = Settings.getString(Settings.KEYS.SUPPRESSION_FILE);
if (suppressionFilePath == null) {
@@ -142,16 +143,13 @@ public abstract class AbstractSuppressionAnalyzer extends AbstractAnalyzer {
}
}
}
if (file != null) {
try {
//rules = parser.parseSuppressionRules(file);
rules.addAll(parser.parseSuppressionRules(file));
LOGGER.debug("{} suppression rules were loaded.", rules.size());
} catch (SuppressionParseException ex) {
LOGGER.warn("Unable to parse suppression xml file '{}'", file.getPath());
LOGGER.warn(ex.getMessage());
LOGGER.debug("", ex);
throw ex;
}
}

View File

@@ -20,24 +20,28 @@ package org.owasp.dependencycheck.analyzer;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.exception.InitializationException;
/**
* An interface that defines an Analyzer that is used to identify Dependencies. An analyzer will collect information
* about the dependency in the form of Evidence.
* An interface that defines an Analyzer that is used to identify Dependencies.
* An analyzer will collect information about the dependency in the form of
* Evidence.
*
* @author Jeremy Long
*/
public interface Analyzer {
/**
* Analyzes the given dependency. The analysis could be anything from identifying an Identifier for the dependency,
* to finding vulnerabilities, etc. Additionally, if the analyzer collects enough information to add a description
* or license information for the dependency it should be added.
* Analyzes the given dependency. The analysis could be anything from
* identifying an Identifier for the dependency, to finding vulnerabilities,
* etc. Additionally, if the analyzer collects enough information to add a
* description or license information for the dependency it should be added.
*
* @param dependency a dependency to analyze.
* @param engine the engine that is scanning the dependencies - this is useful if we need to check other
* dependencies
* @throws AnalysisException is thrown if there is an error analyzing the dependency file
* @param engine the engine that is scanning the dependencies - this is
* useful if we need to check other dependencies
* @throws AnalysisException is thrown if there is an error analyzing the
* dependency file
*/
void analyze(Dependency dependency, Engine engine) throws AnalysisException;
@@ -56,14 +60,17 @@ public interface Analyzer {
AnalysisPhase getAnalysisPhase();
/**
* The initialize method is called (once) prior to the analyze method being called on all of the dependencies.
* The initialize method is called (once) prior to the analyze method being
* called on all of the dependencies.
*
* @throws Exception is thrown if an exception occurs initializing the analyzer.
* @throws InitializationException is thrown if an exception occurs
* initializing the analyzer.
*/
void initialize() throws Exception;
void initialize() throws InitializationException;
/**
* The close method is called after all of the dependencies have been analyzed.
* The close method is called after all of the dependencies have been
* analyzed.
*
* @throws Exception is thrown if an exception occurs closing the analyzer.
*/

View File

@@ -49,6 +49,7 @@ import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.analyzer.exception.ArchiveExtractionException;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.exception.InitializationException;
import org.owasp.dependencycheck.utils.FileFilterBuilder;
import org.owasp.dependencycheck.utils.FileUtils;
import org.owasp.dependencycheck.utils.Settings;
@@ -58,8 +59,8 @@ import org.slf4j.LoggerFactory;
/**
* <p>
* An analyzer that extracts files from archives and ensures any supported files contained within the archive are added to the
* dependency list.</p>
* An analyzer that extracts files from archives and ensures any supported files
* contained within the archive are added to the dependency list.</p>
*
* @author Jeremy Long
*/
@@ -70,7 +71,8 @@ public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer {
*/
private static final Logger LOGGER = LoggerFactory.getLogger(ArchiveAnalyzer.class);
/**
* The count of directories created during analysis. This is used for creating temporary directories.
* The count of directories created during analysis. This is used for
* creating temporary directories.
*/
private static int dirCount = 0;
/**
@@ -78,7 +80,8 @@ public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer {
*/
private File tempFileLocation = null;
/**
* The max scan depth that the analyzer will recursively extract nested archives.
* The max scan depth that the analyzer will recursively extract nested
* archives.
*/
private static final int MAX_SCAN_DEPTH = Settings.getInt("archive.scan.depth", 3);
/**
@@ -100,13 +103,15 @@ public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer {
*/
private static final Set<String> ZIPPABLES = newHashSet("zip", "ear", "war", "jar", "sar", "apk", "nupkg");
/**
* The set of file extensions supported by this analyzer. Note for developers, any additions to this list will need to be
* explicitly handled in {@link #extractFiles(File, File, Engine)}.
* The set of file extensions supported by this analyzer. Note for
* developers, any additions to this list will need to be explicitly handled
* in {@link #extractFiles(File, File, Engine)}.
*/
private static final Set<String> EXTENSIONS = newHashSet("tar", "gz", "tgz", "bz2", "tbz2");
/**
* Detects files with extensions to remove from the engine's collection of dependencies.
* Detects files with extensions to remove from the engine's collection of
* dependencies.
*/
private static final FileFilter REMOVE_FROM_ANALYSIS = FileFilterBuilder.newInstance().addExtensions("zip", "tar", "gz", "tgz", "bz2", "tbz2")
.build();
@@ -157,7 +162,8 @@ public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer {
//</editor-fold>
/**
* Returns the key used in the properties file to reference the analyzer's enabled property.
* Returns the key used in the properties file to reference the analyzer's
* enabled property.
*
* @return the analyzer's enabled property setting key
*/
@@ -169,26 +175,36 @@ public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer {
/**
* The initialize method does nothing for this Analyzer.
*
* @throws Exception is thrown if there is an exception deleting or creating temporary files
* @throws InitializationException is thrown if there is an exception
* deleting or creating temporary files
*/
@Override
public void initializeFileTypeAnalyzer() throws Exception {
final File baseDir = Settings.getTempDirectory();
tempFileLocation = File.createTempFile("check", "tmp", baseDir);
if (!tempFileLocation.delete()) {
final String msg = String.format("Unable to delete temporary file '%s'.", tempFileLocation.getAbsolutePath());
throw new AnalysisException(msg);
}
if (!tempFileLocation.mkdirs()) {
final String msg = String.format("Unable to create directory '%s'.", tempFileLocation.getAbsolutePath());
throw new AnalysisException(msg);
public void initializeFileTypeAnalyzer() throws InitializationException {
try {
final File baseDir = Settings.getTempDirectory();
tempFileLocation = File.createTempFile("check", "tmp", baseDir);
if (!tempFileLocation.delete()) {
setEnabled(false);
final String msg = String.format("Unable to delete temporary file '%s'.", tempFileLocation.getAbsolutePath());
throw new InitializationException(msg);
}
if (!tempFileLocation.mkdirs()) {
setEnabled(false);
final String msg = String.format("Unable to create directory '%s'.", tempFileLocation.getAbsolutePath());
throw new InitializationException(msg);
}
} catch (IOException ex) {
setEnabled(false);
throw new InitializationException("Unable to create a temporary file", ex);
}
}
/**
* The close method deletes any temporary files and directories created during analysis.
* The close method deletes any temporary files and directories created
* during analysis.
*
* @throws Exception thrown if there is an exception deleting temporary files
* @throws Exception thrown if there is an exception deleting temporary
* files
*/
@Override
public void close() throws Exception {
@@ -205,8 +221,9 @@ public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer {
}
/**
* Analyzes a given dependency. If the dependency is an archive, such as a WAR or EAR, the contents are extracted, scanned,
* and added to the list of dependencies within the engine.
* Analyzes a given dependency. If the dependency is an archive, such as a
* WAR or EAR, the contents are extracted, scanned, and added to the list of
* dependencies within the engine.
*
* @param dependency the dependency to analyze
* @param engine the engine scanning
@@ -249,7 +266,8 @@ public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer {
}
/**
* If a zip file was identified as a possible JAR, this method will add the zip to the list of dependencies.
* If a zip file was identified as a possible JAR, this method will add the
* zip to the list of dependencies.
*
* @param dependency the zip file
* @param engine the engine
@@ -349,7 +367,9 @@ public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer {
final String archiveExt = FileUtils.getFileExtension(archive.getName()).toLowerCase();
try {
if (ZIPPABLES.contains(archiveExt)) {
extractArchive(new ZipArchiveInputStream(new BufferedInputStream(fis)), destination, engine);
final BufferedInputStream in = new BufferedInputStream(fis);
ensureReadableJar(archiveExt, in);
extractArchive(new ZipArchiveInputStream(in), destination, engine);
} else if ("tar".equals(archiveExt)) {
extractArchive(new TarArchiveInputStream(new BufferedInputStream(fis)), destination, engine);
} else if ("gz".equals(archiveExt) || "tgz".equals(archiveExt)) {
@@ -377,13 +397,62 @@ public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer {
}
}
/**
* Checks if the file being scanned is a JAR that begins with '#!/bin' which
* indicates it is a fully executable jar. If a fully executable JAR is
* identified the input stream will be advanced to the start of the actual
* JAR file ( skipping the script).
*
* @see
* <a href="http://docs.spring.io/spring-boot/docs/1.3.0.BUILD-SNAPSHOT/reference/htmlsingle/#deployment-install">Installing
* Spring Boot Applications</a>
* @param archiveExt the file extension
* @param in the input stream
* @throws IOException thrown if there is an error reading the stream
*/
private void ensureReadableJar(final String archiveExt, BufferedInputStream in) throws IOException {
if ("jar".equals(archiveExt) && in.markSupported()) {
in.mark(7);
final byte[] b = new byte[7];
in.read(b);
if (b[0] == '#'
&& b[1] == '!'
&& b[2] == '/'
&& b[3] == 'b'
&& b[4] == 'i'
&& b[5] == 'n'
&& b[6] == '/') {
boolean stillLooking = true;
int chr, nxtChr;
while (stillLooking && (chr = in.read()) != -1) {
if (chr == '\n' || chr == '\r') {
in.mark(4);
if ((chr = in.read()) != -1) {
if (chr == 'P' && (chr = in.read()) != -1) {
if (chr == 'K' && (chr = in.read()) != -1) {
if ((chr == 3 || chr == 5 || chr == 7) && (nxtChr = in.read()) != -1) {
if (nxtChr == chr + 1) {
stillLooking = false;
in.reset();
}
}
}
}
}
}
}
}
}
}
/**
* Extracts files from an archive.
*
* @param input the archive to extract files from
* @param destination the location to write the files too
* @param engine the dependency-check engine
* @throws ArchiveExtractionException thrown if there is an exception extracting files from the archive
* @throws ArchiveExtractionException thrown if there is an exception
* extracting files from the archive
*/
private void extractArchive(ArchiveInputStream input, File destination, Engine engine) throws ArchiveExtractionException {
ArchiveEntry entry;
@@ -442,7 +511,8 @@ public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer {
*
* @param inputStream the compressed file
* @param outputFile the location to write the decompressed file
* @throws ArchiveExtractionException thrown if there is an exception decompressing the file
* @throws ArchiveExtractionException thrown if there is an exception
* decompressing the file
*/
private void decompressFile(CompressorInputStream inputStream, File outputFile) throws ArchiveExtractionException {
LOGGER.debug("Decompressing '{}'", outputFile.getPath());
@@ -462,7 +532,8 @@ public class ArchiveAnalyzer extends AbstractFileTypeAnalyzer {
}
/**
* Close the given {@link Closeable} instance, ignoring nulls, and logging any thrown {@link IOException}.
* Close the given {@link Closeable} instance, ignoring nulls, and logging
* any thrown {@link IOException}.
*
* @param closeable to be closed
*/

View File

@@ -43,9 +43,12 @@ import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.ParserConfigurationException;
import org.owasp.dependencycheck.exception.InitializationException;
/**
* Analyzer for getting company, product, and version information from a .NET assembly.
* Analyzer for getting company, product, and version information from a .NET
* assembly.
*
* @author colezlaw
*
@@ -178,13 +181,20 @@ public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer {
}
/**
* Initialize the analyzer. In this case, extract GrokAssembly.exe to a temporary location.
* Initialize the analyzer. In this case, extract GrokAssembly.exe to a
* temporary location.
*
* @throws Exception if anything goes wrong
* @throws InitializationException thrown if anything goes wrong
*/
@Override
public void initializeFileTypeAnalyzer() throws Exception {
final File tempFile = File.createTempFile("GKA", ".exe", Settings.getTempDirectory());
public void initializeFileTypeAnalyzer() throws InitializationException {
final File tempFile;
try {
tempFile = File.createTempFile("GKA", ".exe", Settings.getTempDirectory());
} catch (IOException ex) {
setEnabled(false);
throw new InitializationException("Unable to create temporary file for the assembly analyzerr", ex);
}
FileOutputStream fos = null;
InputStream is = null;
try {
@@ -199,7 +209,7 @@ public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer {
} catch (IOException ioe) {
this.setEnabled(false);
LOGGER.warn("Could not extract GrokAssembly.exe: {}", ioe.getMessage());
throw new AnalysisException("Could not extract GrokAssembly.exe", ioe);
throw new InitializationException("Could not extract GrokAssembly.exe", ioe);
} finally {
if (fos != null) {
try {
@@ -232,19 +242,24 @@ public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer {
LOGGER.warn("An error occurred with the .NET AssemblyAnalyzer, please see the log for more details.");
LOGGER.debug("GrokAssembly.exe is not working properly");
grokAssemblyExe = null;
this.setEnabled(false);
throw new AnalysisException("Could not execute .NET AssemblyAnalyzer");
setEnabled(false);
throw new InitializationException("Could not execute .NET AssemblyAnalyzer");
}
} catch (AnalysisException e) {
} catch (InitializationException e) {
throw e;
} catch (Throwable e) {
LOGGER.warn("An error occurred with the .NET AssemblyAnalyzer;\n"
+ "this can be ignored unless you are scanning .NET DLLs. Please see the log for more details.");
LOGGER.debug("Could not execute GrokAssembly {}", e.getMessage());
this.setEnabled(false);
throw new AnalysisException("An error occurred with the .NET AssemblyAnalyzer", e);
setEnabled(false);
throw new InitializationException("An error occurred with the .NET AssemblyAnalyzer", e);
}
try {
builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
} catch (ParserConfigurationException ex) {
setEnabled(false);
throw new InitializationException("Error initializing the assembly analyzer", ex);
}
builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
}
/**
@@ -296,7 +311,8 @@ public class AssemblyAnalyzer extends AbstractFileTypeAnalyzer {
}
/**
* Returns the key used in the properties file to reference the analyzer's enabled property.
* Returns the key used in the properties file to reference the analyzer's
* enabled property.
*
* @return the analyzer's enabled property setting key
*/

View File

@@ -35,13 +35,16 @@ import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.owasp.dependencycheck.exception.InitializationException;
/**
* Used to analyze Autoconf input files named configure.ac or configure.in. Files simply named "configure" are also analyzed,
* assuming they are generated by Autoconf, and contain certain special package descriptor variables.
* Used to analyze Autoconf input files named configure.ac or configure.in.
* Files simply named "configure" are also analyzed, assuming they are generated
* by Autoconf, and contain certain special package descriptor variables.
*
* @author Dale Visser
* @see <a href="https://www.gnu.org/software/autoconf/">Autoconf - GNU Project - Free Software Foundation (FSF)</a>
* @see <a href="https://www.gnu.org/software/autoconf/">Autoconf - GNU Project
* - Free Software Foundation (FSF)</a>
*/
@Experimental
public class AutoconfAnalyzer extends AbstractFileTypeAnalyzer {
@@ -142,7 +145,8 @@ public class AutoconfAnalyzer extends AbstractFileTypeAnalyzer {
}
/**
* Returns the key used in the properties file to reference the analyzer's enabled property.
* Returns the key used in the properties file to reference the analyzer's
* enabled property.
*
* @return the analyzer's enabled property setting key
*/
@@ -270,10 +274,11 @@ public class AutoconfAnalyzer extends AbstractFileTypeAnalyzer {
/**
* Initializes the file type analyzer.
*
* @throws Exception thrown if there is an exception during initialization
* @throws InitializationException thrown if there is an exception during
* initialization
*/
@Override
protected void initializeFileTypeAnalyzer() throws Exception {
protected void initializeFileTypeAnalyzer() throws InitializationException {
// No initialization needed.
}
}

View File

@@ -38,14 +38,18 @@ import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.owasp.dependencycheck.exception.InitializationException;
/**
* <p>
* Used to analyze CMake build files, and collect information that can be used to determine the associated CPE.</p>
* Used to analyze CMake build files, and collect information that can be used
* to determine the associated CPE.</p>
* <p>
* Note: This analyzer catches straightforward invocations of the project command, plus some other observed patterns of version
* inclusion in real CMake projects. Many projects make use of older versions of CMake and/or use custom "homebrew" ways to insert
* version information. Hopefully as the newer CMake call pattern grows in usage, this analyzer allow more CPEs to be
* Note: This analyzer catches straightforward invocations of the project
* command, plus some other observed patterns of version inclusion in real CMake
* projects. Many projects make use of older versions of CMake and/or use custom
* "homebrew" ways to insert version information. Hopefully as the newer CMake
* call pattern grows in usage, this analyzer allow more CPEs to be
* identified.</p>
*
* @author Dale Visser
@@ -135,10 +139,10 @@ public class CMakeAnalyzer extends AbstractFileTypeAnalyzer {
/**
* No-op initializer implementation.
*
* @throws Exception never thrown
* @throws InitializationException never thrown
*/
@Override
protected void initializeFileTypeAnalyzer() throws Exception {
protected void initializeFileTypeAnalyzer() throws InitializationException {
// Nothing to do here.
}
@@ -147,7 +151,8 @@ public class CMakeAnalyzer extends AbstractFileTypeAnalyzer {
*
* @param dependency the dependency being analyzed
* @param engine the engine being used to perform the scan
* @throws AnalysisException thrown if there is an unrecoverable error analyzing the dependency
* @throws AnalysisException thrown if there is an unrecoverable error
* analyzing the dependency
*/
@Override
protected void analyzeFileType(Dependency dependency, Engine engine)
@@ -183,8 +188,9 @@ public class CMakeAnalyzer extends AbstractFileTypeAnalyzer {
}
/**
* Extracts the version information from the contents. If more then one version is found additional dependencies are added to
* the dependency list.
* Extracts the version information from the contents. If more then one
* version is found additional dependencies are added to the dependency
* list.
*
* @param dependency the dependency being analyzed
* @param engine the dependency-check engine

View File

@@ -45,6 +45,7 @@ import org.owasp.dependencycheck.dependency.Evidence;
import org.owasp.dependencycheck.dependency.EvidenceCollection;
import org.owasp.dependencycheck.dependency.Identifier;
import org.owasp.dependencycheck.dependency.VulnerableSoftware;
import org.owasp.dependencycheck.exception.InitializationException;
import org.owasp.dependencycheck.utils.DependencyVersion;
import org.owasp.dependencycheck.utils.DependencyVersionUtil;
import org.slf4j.Logger;
@@ -123,11 +124,20 @@ public class CPEAnalyzer implements Analyzer {
/**
* Creates the CPE Lucene Index.
*
* @throws Exception is thrown if there is an issue opening the index.
* @throws InitializationException is thrown if there is an issue opening
* the index.
*/
@Override
public void initialize() throws Exception {
this.open();
public void initialize() throws InitializationException {
try {
this.open();
} catch (IOException ex) {
LOGGER.debug("Exception initializing the Lucene Index", ex);
throw new InitializationException("An exception occurred initializing the Lucene Index", ex);
} catch (DatabaseException ex) {
LOGGER.debug("Exception accessing the database", ex);
throw new InitializationException("An exception occurred accessing the database", ex);
}
}
/**
@@ -564,8 +574,9 @@ 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()
//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()) {

View File

@@ -33,8 +33,10 @@ import java.io.File;
import java.io.FileFilter;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import org.owasp.dependencycheck.exception.InitializationException;
import org.owasp.dependencycheck.utils.DownloadFailedException;
import org.owasp.dependencycheck.utils.Downloader;
import org.owasp.dependencycheck.utils.FileFilterBuilder;
@@ -42,8 +44,8 @@ import org.owasp.dependencycheck.utils.InvalidSettingException;
import org.owasp.dependencycheck.utils.Settings;
/**
* Analyzer which will attempt to locate a dependency, and the GAV information, by querying Central for the dependency's SHA-1
* digest.
* Analyzer which will attempt to locate a dependency, and the GAV information,
* by querying Central for the dependency's SHA-1 digest.
*
* @author colezlaw
*/
@@ -70,7 +72,8 @@ public class CentralAnalyzer extends AbstractFileTypeAnalyzer {
private static final String SUPPORTED_EXTENSIONS = "jar";
/**
* The analyzer should be disabled if there are errors, so this is a flag to determine if such an error has occurred.
* The analyzer should be disabled if there are errors, so this is a flag to
* determine if such an error has occurred.
*/
private boolean errorFlag = false;
@@ -96,7 +99,8 @@ public class CentralAnalyzer extends AbstractFileTypeAnalyzer {
/**
* Determines if this analyzer is enabled.
*
* @return <code>true</code> if the analyzer is enabled; otherwise <code>false</code>
* @return <code>true</code> if the analyzer is enabled; otherwise
* <code>false</code>
*/
private boolean checkEnabled() {
boolean retval = false;
@@ -122,16 +126,21 @@ public class CentralAnalyzer extends AbstractFileTypeAnalyzer {
/**
* Initializes the analyzer once before any analysis is performed.
*
* @throws Exception if there's an error during initialization
* @throws InitializationException if there's an error during initialization
*/
@Override
public void initializeFileTypeAnalyzer() throws Exception {
public void initializeFileTypeAnalyzer() throws InitializationException {
LOGGER.debug("Initializing Central analyzer");
LOGGER.debug("Central analyzer enabled: {}", isEnabled());
if (isEnabled()) {
final String searchUrl = Settings.getString(Settings.KEYS.ANALYZER_CENTRAL_URL);
LOGGER.debug("Central Analyzer URL: {}", searchUrl);
searcher = new CentralSearch(new URL(searchUrl));
try {
searcher = new CentralSearch(new URL(searchUrl));
} catch (MalformedURLException ex) {
setEnabled(false);
throw new InitializationException("The configured URL to Maven Central is malformed: " + searchUrl, ex);
}
}
}
@@ -146,7 +155,8 @@ public class CentralAnalyzer extends AbstractFileTypeAnalyzer {
}
/**
* Returns the key used in the properties file to to reference the analyzer's enabled property.
* Returns the key used in the properties file to to reference the
* analyzer's enabled property.
*
* @return the analyzer's enabled property setting key.
*/

View File

@@ -35,6 +35,8 @@ import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import org.owasp.dependencycheck.exception.InitializationException;
/**
* Used to analyze a composer.lock file for a composer PHP app.
@@ -77,15 +79,22 @@ public class ComposerLockAnalyzer extends AbstractFileTypeAnalyzer {
/**
* Initializes the analyzer.
*
* @throws Exception thrown if an exception occurs getting an instance of SHA1
* @throws InitializationException thrown if an exception occurs getting an
* instance of SHA1
*/
@Override
protected void initializeFileTypeAnalyzer() throws Exception {
sha1 = MessageDigest.getInstance("SHA1");
protected void initializeFileTypeAnalyzer() throws InitializationException {
try {
sha1 = MessageDigest.getInstance("SHA1");
} catch (NoSuchAlgorithmException ex) {
setEnabled(false);
throw new InitializationException("Unable to create SHA1 MmessageDigest", ex);
}
}
/**
* The MessageDigest for calculating a new digest for the new dependencies added.
* The MessageDigest for calculating a new digest for the new dependencies
* added.
*/
private MessageDigest sha1 = null;

View File

@@ -20,7 +20,7 @@ package org.owasp.dependencycheck.analyzer;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.suppression.SuppressionRule;
import org.owasp.dependencycheck.xml.suppression.SuppressionRule;
/**
* The suppression analyzer processes an externally defined XML document that complies with the suppressions.xsd schema.

View File

@@ -17,17 +17,37 @@
*/
package org.owasp.dependencycheck.analyzer;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.dependency.Confidence;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.dependency.Evidence;
import org.owasp.dependencycheck.exception.InitializationException;
import org.owasp.dependencycheck.xml.suppression.PropertyType;
import org.owasp.dependencycheck.utils.DownloadFailedException;
import org.owasp.dependencycheck.utils.Downloader;
import org.owasp.dependencycheck.utils.FileUtils;
import org.owasp.dependencycheck.utils.Settings;
import org.owasp.dependencycheck.xml.hints.VendorDuplicatingHintRule;
import org.owasp.dependencycheck.xml.hints.HintParseException;
import org.owasp.dependencycheck.xml.hints.HintParser;
import org.owasp.dependencycheck.xml.hints.HintRule;
import org.owasp.dependencycheck.xml.hints.Hints;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.SAXException;
/**
* This analyzer adds evidence to dependencies to enhance the accuracy of
* library identification.
*
* @author Jeremy Long
*/
@@ -62,18 +82,98 @@ public class HintAnalyzer extends AbstractAnalyzer implements Analyzer {
public AnalysisPhase getAnalysisPhase() {
return ANALYSIS_PHASE;
}
/**
* The initialize method does nothing for this Analyzer.
*
* @throws InitializationException thrown if there is an exception
*/
@Override
public void initialize() throws InitializationException {
try {
super.initialize();
loadHintRules();
} catch (HintParseException ex) {
LOGGER.debug("Unable to parse hint file", ex);
throw new InitializationException("Unable to parse the hint file", ex);
}
}
//</editor-fold>
/**
* The HintAnalyzer uses knowledge about a dependency to add additional information to help in identification of identifiers
* or vulnerabilities.
* The Logger for use throughout the class
*/
private static final Logger LOGGER = LoggerFactory.getLogger(HintAnalyzer.class);
/**
* The name of the hint rule file
*/
private static final String HINT_RULE_FILE_NAME = "dependencycheck-base-hint.xml";
/**
* The collection of hints.
*/
private Hints hints;
/**
* The HintAnalyzer uses knowledge about a dependency to add additional
* information to help in identification of identifiers or vulnerabilities.
*
* @param dependency The dependency being analyzed
* @param engine The scanning engine
* @throws AnalysisException is thrown if there is an exception analyzing the dependency.
* @throws AnalysisException is thrown if there is an exception analyzing
* the dependency.
*/
@Override
public void analyze(Dependency dependency, Engine engine) throws AnalysisException {
for (HintRule hint : hints.getHintRules()) {
boolean shouldAdd = false;
for (Evidence given : hint.getGivenVendor()) {
if (dependency.getVendorEvidence().getEvidence().contains(given)) {
shouldAdd = true;
break;
}
}
if (!shouldAdd) {
for (Evidence given : hint.getGivenProduct()) {
if (dependency.getProductEvidence().getEvidence().contains(given)) {
shouldAdd = true;
break;
}
}
}
if (!shouldAdd) {
for (PropertyType pt : hint.getFilenames()) {
if (pt.matches(dependency.getFileName())) {
shouldAdd = true;
}
}
}
if (shouldAdd) {
for (Evidence e : hint.getAddVendor()) {
dependency.getVendorEvidence().addEvidence(e);
}
for (Evidence e : hint.getAddProduct()) {
dependency.getProductEvidence().addEvidence(e);
}
}
}
final Iterator<Evidence> itr = dependency.getVendorEvidence().iterator();
final List<Evidence> newEntries = new ArrayList<Evidence>();
while (itr.hasNext()) {
final Evidence e = itr.next();
for (VendorDuplicatingHintRule dhr : hints.getVendorDuplicatingHintRules()) {
if (dhr.getValue().equalsIgnoreCase(e.getValue(false))) {
newEntries.add(new Evidence(e.getSource() + " (hint)",
e.getName(), dhr.getDuplicate(), e.getConfidence()));
}
}
}
for (Evidence e : newEntries) {
dependency.getVendorEvidence().addEvidence(e);
}
//<editor-fold defaultstate="collapsed" desc="Old implementation">
/*
final Evidence springTest1 = new Evidence("Manifest",
"Implementation-Title",
"Spring Framework",
@@ -171,6 +271,83 @@ public class HintAnalyzer extends AbstractAnalyzer implements Analyzer {
for (Evidence e : newEntries) {
dependency.getVendorEvidence().addEvidence(e);
}
*/
//</editor-fold>
}
/**
* Loads the hint rules file.
*
* @throws HintParseException thrown if the XML cannot be parsed.
*/
private void loadHintRules() throws HintParseException {
final HintParser parser = new HintParser();
File file = null;
try {
hints = parser.parseHints(this.getClass().getClassLoader().getResourceAsStream(HINT_RULE_FILE_NAME));
} catch (HintParseException ex) {
LOGGER.error("Unable to parse the base hint data file");
LOGGER.debug("Unable to parse the base hint data file", ex);
} catch (SAXException ex) {
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);
if (filePath == null) {
return;
}
boolean deleteTempFile = false;
try {
final Pattern uriRx = Pattern.compile("^(https?|file)\\:.*", Pattern.CASE_INSENSITIVE);
if (uriRx.matcher(filePath).matches()) {
deleteTempFile = true;
file = FileUtils.getTempFile("hint", "xml");
final URL url = new URL(filePath);
try {
Downloader.fetchFile(url, file, false);
} catch (DownloadFailedException ex) {
Downloader.fetchFile(url, file, true);
}
} else {
file = new File(filePath);
if (!file.exists()) {
final InputStream fromClasspath = this.getClass().getClassLoader().getResourceAsStream(filePath);
if (fromClasspath != null) {
deleteTempFile = true;
file = FileUtils.getTempFile("hint", "xml");
try {
org.apache.commons.io.FileUtils.copyInputStreamToFile(fromClasspath, file);
} catch (IOException ex) {
throw new HintParseException("Unable to locate suppressions file in classpath", ex);
}
}
}
}
if (file != null) {
try {
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());
LOGGER.debug("{} duplicating hint rules were loaded.", hints.getVendorDuplicatingHintRules().size());
} catch (HintParseException ex) {
LOGGER.warn("Unable to parse hint rule xml file '{}'", file.getPath());
LOGGER.warn(ex.getMessage());
LOGGER.debug("", ex);
throw ex;
}
}
} catch (DownloadFailedException ex) {
throw new HintParseException("Unable to fetch the configured hint file", ex);
} catch (MalformedURLException ex) {
throw new HintParseException("Configured hint file has an invalid URL", ex);
} catch (IOException ex) {
throw new HintParseException("Unable to create temp file for hints", ex);
} finally {
if (deleteTempFile && file != null) {
FileUtils.delete(file);
}
}
}
}

View File

@@ -49,6 +49,7 @@ import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.dependency.Confidence;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.dependency.EvidenceCollection;
import org.owasp.dependencycheck.exception.InitializationException;
import org.owasp.dependencycheck.utils.FileFilterBuilder;
import org.owasp.dependencycheck.xml.pom.License;
import org.owasp.dependencycheck.xml.pom.PomUtils;
@@ -644,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 {
@@ -665,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;
@@ -782,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;
@@ -903,20 +900,27 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
/**
* Initializes the JarAnalyzer.
*
* @throws Exception is thrown if there is an exception creating a temporary
* directory
* @throws InitializationException is thrown if there is an exception
* creating a temporary directory
*/
@Override
public void initializeFileTypeAnalyzer() throws Exception {
final File baseDir = Settings.getTempDirectory();
tempFileLocation = File.createTempFile("check", "tmp", baseDir);
if (!tempFileLocation.delete()) {
final String msg = String.format("Unable to delete temporary file '%s'.", tempFileLocation.getAbsolutePath());
throw new AnalysisException(msg);
}
if (!tempFileLocation.mkdirs()) {
final String msg = String.format("Unable to create directory '%s'.", tempFileLocation.getAbsolutePath());
throw new AnalysisException(msg);
public void initializeFileTypeAnalyzer() throws InitializationException {
try {
final File baseDir = Settings.getTempDirectory();
tempFileLocation = File.createTempFile("check", "tmp", baseDir);
if (!tempFileLocation.delete()) {
final String msg = String.format("Unable to delete temporary file '%s'.", tempFileLocation.getAbsolutePath());
setEnabled(false);
throw new InitializationException(msg);
}
if (!tempFileLocation.mkdirs()) {
final String msg = String.format("Unable to create directory '%s'.", tempFileLocation.getAbsolutePath());
setEnabled(false);
throw new InitializationException(msg);
}
} catch (IOException ex) {
setEnabled(false);
throw new InitializationException("Unable to create a temporary file", ex);
}
}

View File

@@ -35,6 +35,7 @@ import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import org.owasp.dependencycheck.exception.InitializationException;
import org.owasp.dependencycheck.utils.DownloadFailedException;
import org.owasp.dependencycheck.utils.Downloader;
import org.owasp.dependencycheck.utils.FileFilterBuilder;
@@ -42,15 +43,18 @@ import org.owasp.dependencycheck.utils.InvalidSettingException;
import org.owasp.dependencycheck.utils.Settings;
/**
* Analyzer which will attempt to locate a dependency on a Nexus service by SHA-1 digest of the dependency.
* Analyzer which will attempt to locate a dependency on a Nexus service by
* SHA-1 digest of the dependency.
*
* There are two settings which govern this behavior:
*
* <ul>
* <li>{@link org.owasp.dependencycheck.utils.Settings.KEYS#ANALYZER_NEXUS_ENABLED} determines whether this analyzer is even
* enabled. This can be overridden by setting the system property.</li>
* <li>{@link org.owasp.dependencycheck.utils.Settings.KEYS#ANALYZER_NEXUS_URL} the URL to a Nexus service to search by SHA-1.
* There is an expected <code>%s</code> in this where the SHA-1 will get entered.</li>
* <li>{@link org.owasp.dependencycheck.utils.Settings.KEYS#ANALYZER_NEXUS_ENABLED}
* determines whether this analyzer is even enabled. This can be overridden by
* setting the system property.</li>
* <li>{@link org.owasp.dependencycheck.utils.Settings.KEYS#ANALYZER_NEXUS_URL}
* the URL to a Nexus service to search by SHA-1. There is an expected
* <code>%s</code> in this where the SHA-1 will get entered.</li>
* </ul>
*
* @author colezlaw
@@ -58,7 +62,8 @@ import org.owasp.dependencycheck.utils.Settings;
public class NexusAnalyzer extends AbstractFileTypeAnalyzer {
/**
* The default URL - this will be used by the CentralAnalyzer to determine whether to enable this.
* The default URL - this will be used by the CentralAnalyzer to determine
* whether to enable this.
*/
public static final String DEFAULT_URL = "https://repository.sonatype.org/service/local/";
@@ -95,7 +100,8 @@ public class NexusAnalyzer extends AbstractFileTypeAnalyzer {
/**
* Determines if this analyzer is enabled
*
* @return <code>true</code> if the analyzer is enabled; otherwise <code>false</code>
* @return <code>true</code> if the analyzer is enabled; otherwise
* <code>false</code>
*/
private boolean checkEnabled() {
/* Enable this analyzer ONLY if the Nexus URL has been set to something
@@ -131,10 +137,10 @@ public class NexusAnalyzer extends AbstractFileTypeAnalyzer {
/**
* Initializes the analyzer once before any analysis is performed.
*
* @throws Exception if there's an error during initialization
* @throws InitializationException if there's an error during initialization
*/
@Override
public void initializeFileTypeAnalyzer() throws Exception {
public void initializeFileTypeAnalyzer() throws InitializationException {
LOGGER.debug("Initializing Nexus Analyzer");
LOGGER.debug("Nexus Analyzer enabled: {}", isEnabled());
if (isEnabled()) {
@@ -143,14 +149,12 @@ public class NexusAnalyzer extends AbstractFileTypeAnalyzer {
try {
searcher = new NexusSearch(new URL(searchUrl));
if (!searcher.preflightRequest()) {
LOGGER.warn("There was an issue getting Nexus status. Disabling analyzer.");
setEnabled(false);
throw new InitializationException("There was an issue getting Nexus status. Disabling analyzer.");
}
} catch (MalformedURLException mue) {
// I know that initialize can throw an exception, but we'll
// just disable the analyzer if the URL isn't valid
LOGGER.warn("Property {} not a valid URL. Nexus Analyzer disabled", searchUrl);
setEnabled(false);
throw new InitializationException("Malformed URL to Nexus: " + searchUrl, mue);
}
}
}
@@ -166,7 +170,8 @@ public class NexusAnalyzer extends AbstractFileTypeAnalyzer {
}
/**
* Returns the key used in the properties file to reference the analyzer's enabled property.
* Returns the key used in the properties file to reference the analyzer's
* enabled property.
*
* @return the analyzer's enabled property setting key
*/

View File

@@ -38,10 +38,11 @@ import javax.json.JsonObject;
import javax.json.JsonReader;
import javax.json.JsonString;
import javax.json.JsonValue;
import org.owasp.dependencycheck.exception.InitializationException;
/**
* Used to analyze Node Package Manager (npm) package.json files, and collect information that can be used to determine the
* associated CPE.
* Used to analyze Node Package Manager (npm) package.json files, and collect
* information that can be used to determine the associated CPE.
*
* @author Dale Visser
*/
@@ -84,7 +85,7 @@ public class NodePackageAnalyzer extends AbstractFileTypeAnalyzer {
}
@Override
protected void initializeFileTypeAnalyzer() throws Exception {
protected void initializeFileTypeAnalyzer() throws InitializationException {
// NO-OP
}
@@ -109,7 +110,8 @@ public class NodePackageAnalyzer extends AbstractFileTypeAnalyzer {
}
/**
* Returns the key used in the properties file to reference the analyzer's enabled property.
* Returns the key used in the properties file to reference the analyzer's
* enabled property.
*
* @return the analyzer's enabled property setting key
*/
@@ -155,7 +157,8 @@ public class NodePackageAnalyzer extends AbstractFileTypeAnalyzer {
}
/**
* Adds information to an evidence collection from the node json configuration.
* Adds information to an evidence collection from the node json
* configuration.
*
* @param json information from node.js
* @param collection a set of evidence about a dependency

View File

@@ -34,6 +34,7 @@ import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import org.owasp.dependencycheck.exception.InitializationException;
/**
* Analyzer which will parse a Nuspec file to gather module information.
@@ -65,10 +66,10 @@ public class NuspecAnalyzer extends AbstractFileTypeAnalyzer {
/**
* Initializes the analyzer once before any analysis is performed.
*
* @throws Exception if there's an error during initialization
* @throws InitializationException if there's an error during initialization
*/
@Override
public void initializeFileTypeAnalyzer() throws Exception {
public void initializeFileTypeAnalyzer() throws InitializationException {
}
/**
@@ -82,7 +83,8 @@ public class NuspecAnalyzer extends AbstractFileTypeAnalyzer {
}
/**
* Returns the key used in the properties file to reference the analyzer's enabled property.
* Returns the key used in the properties file to reference the analyzer's
* enabled property.
*
* @return the analyzer's enabled property setting key
*/

View File

@@ -27,6 +27,8 @@ import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.dependency.Identifier;
import org.owasp.dependencycheck.dependency.Vulnerability;
import org.owasp.dependencycheck.exception.InitializationException;
import org.slf4j.LoggerFactory;
/**
* NvdCveAnalyzer is a utility class that takes a project dependency and attempts to discern if there is an associated
@@ -35,7 +37,10 @@ import org.owasp.dependencycheck.dependency.Vulnerability;
* @author Jeremy Long
*/
public class NvdCveAnalyzer implements Analyzer {
/**
* The Logger for use throughout the class
*/
private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(NvdCveAnalyzer.class);
/**
* The maximum number of query results to return.
*/
@@ -79,7 +84,7 @@ public class NvdCveAnalyzer implements Analyzer {
/**
* Ensures that the CVE Database is closed.
*
* @throws Throwable when a throwable is thrown.
* @throws Throwable an exception raised by this method
*/
@Override
protected void finalize() throws Throwable {
@@ -94,7 +99,7 @@ public class NvdCveAnalyzer implements Analyzer {
*
* @param dependency The Dependency to analyze
* @param engine The analysis engine
* @throws AnalysisException is thrown if there is an issue analyzing the dependency
* @throws AnalysisException thrown if there is an issue analyzing the dependency
*/
@Override
public void analyze(Dependency dependency, Engine engine) throws AnalysisException {
@@ -145,10 +150,24 @@ public class NvdCveAnalyzer implements Analyzer {
/**
* Opens the database used to gather NVD CVE data.
*
* @throws Exception is thrown if there is an issue opening the index.
* @throws InitializationException is thrown if there is an issue opening the index.
*/
@Override
public void initialize() throws Exception {
this.open();
public void initialize() throws InitializationException {
try {
this.open();
} catch (SQLException ex) {
LOGGER.debug("SQL Exception initializing NvdCveAnalyzer", ex);
throw new InitializationException(ex);
} catch (IOException ex) {
LOGGER.debug("IO Exception initializing NvdCveAnalyzer", ex);
throw new InitializationException(ex);
} catch (DatabaseException ex) {
LOGGER.debug("Database Exception initializing NvdCveAnalyzer", ex);
throw new InitializationException(ex);
} catch (ClassNotFoundException ex) {
LOGGER.debug("Exception initializing NvdCveAnalyzer", ex);
throw new InitializationException(ex);
}
}
}

View File

@@ -31,6 +31,7 @@ import java.io.IOException;
import java.nio.charset.Charset;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.owasp.dependencycheck.exception.InitializationException;
/**
* Used to analyze OpenSSL source code present in the file system.
@@ -145,10 +146,10 @@ public class OpenSSLAnalyzer extends AbstractFileTypeAnalyzer {
/**
* No-op initializer implementation.
*
* @throws Exception never thrown
* @throws InitializationException never thrown
*/
@Override
protected void initializeFileTypeAnalyzer() throws Exception {
protected void initializeFileTypeAnalyzer() throws InitializationException {
// Nothing to do here.
}

View File

@@ -23,6 +23,7 @@ import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FilenameFilter;
import java.io.IOException;
import org.apache.commons.io.filefilter.NameFileFilter;
import org.apache.commons.io.filefilter.SuffixFileFilter;
import org.apache.commons.io.input.AutoCloseInputStream;
@@ -37,6 +38,7 @@ import org.slf4j.LoggerFactory;
import javax.mail.MessagingException;
import javax.mail.internet.InternetHeaders;
import org.owasp.dependencycheck.exception.InitializationException;
import org.owasp.dependencycheck.utils.ExtractionException;
import org.owasp.dependencycheck.utils.ExtractionUtil;
import org.owasp.dependencycheck.utils.FileFilterBuilder;
@@ -45,8 +47,9 @@ import org.owasp.dependencycheck.utils.Settings;
import org.owasp.dependencycheck.utils.UrlStringUtils;
/**
* Used to analyze a Wheel or egg distribution files, or their contents in unzipped form, and collect information that can be used
* to determine the associated CPE.
* Used to analyze a Wheel or egg distribution files, or their contents in
* unzipped form, and collect information that can be used to determine the
* associated CPE.
*
* @author Dale Visser
*/
@@ -70,7 +73,8 @@ public class PythonDistributionAnalyzer extends AbstractFileTypeAnalyzer {
.getLogger(PythonDistributionAnalyzer.class);
/**
* The count of directories created during analysis. This is used for creating temporary directories.
* The count of directories created during analysis. This is used for
* creating temporary directories.
*/
private static int dirCount = 0;
@@ -104,7 +108,8 @@ public class PythonDistributionAnalyzer extends AbstractFileTypeAnalyzer {
private File tempFileLocation;
/**
* Filter that detects *.dist-info files (but doesn't verify they are directories.
* Filter that detects *.dist-info files (but doesn't verify they are
* directories.
*/
private static final FilenameFilter DIST_INFO_FILTER = new SuffixFileFilter(
".dist-info");
@@ -164,7 +169,8 @@ public class PythonDistributionAnalyzer extends AbstractFileTypeAnalyzer {
}
/**
* Returns the key used in the properties file to reference the analyzer's enabled property.
* Returns the key used in the properties file to reference the analyzer's
* enabled property.
*
* @return the analyzer's enabled property setting key
*/
@@ -206,7 +212,8 @@ public class PythonDistributionAnalyzer extends AbstractFileTypeAnalyzer {
* @param dependency the archive being scanned
* @param folderFilter the filter to apply to the folder
* @param metadataFilter the filter to apply to the meta data
* @throws AnalysisException thrown when there is a problem analyzing the dependency
* @throws AnalysisException thrown when there is a problem analyzing the
* dependency
*/
private void collectMetadataFromArchiveFormat(Dependency dependency,
FilenameFilter folderFilter, FilenameFilter metadataFilter)
@@ -230,23 +237,31 @@ public class PythonDistributionAnalyzer extends AbstractFileTypeAnalyzer {
/**
* Makes sure a usable temporary directory is available.
*
* @throws Exception an AnalyzeException is thrown when the temp directory cannot be created
* @throws InitializationException an AnalyzeException is thrown when the
* temp directory cannot be created
*/
@Override
protected void initializeFileTypeAnalyzer() throws Exception {
final File baseDir = Settings.getTempDirectory();
tempFileLocation = File.createTempFile("check", "tmp", baseDir);
if (!tempFileLocation.delete()) {
final String msg = String.format(
"Unable to delete temporary file '%s'.",
tempFileLocation.getAbsolutePath());
throw new AnalysisException(msg);
}
if (!tempFileLocation.mkdirs()) {
final String msg = String.format(
"Unable to create directory '%s'.",
tempFileLocation.getAbsolutePath());
throw new AnalysisException(msg);
protected void initializeFileTypeAnalyzer() throws InitializationException {
try {
final File baseDir = Settings.getTempDirectory();
tempFileLocation = File.createTempFile("check", "tmp", baseDir);
if (!tempFileLocation.delete()) {
setEnabled(false);
final String msg = String.format(
"Unable to delete temporary file '%s'.",
tempFileLocation.getAbsolutePath());
throw new InitializationException(msg);
}
if (!tempFileLocation.mkdirs()) {
setEnabled(false);
final String msg = String.format(
"Unable to create directory '%s'.",
tempFileLocation.getAbsolutePath());
throw new InitializationException(msg);
}
} catch (IOException ex) {
setEnabled(false);
throw new InitializationException("Unable to create a temporary file", ex);
}
}
@@ -312,7 +327,8 @@ public class PythonDistributionAnalyzer extends AbstractFileTypeAnalyzer {
}
/**
* Returns a list of files that match the given filter, this does not recursively scan the directory.
* Returns a list of files that match the given filter, this does not
* recursively scan the directory.
*
* @param folder the folder to filter
* @param filter the filter to apply to the files in the directory
@@ -351,7 +367,8 @@ public class PythonDistributionAnalyzer extends AbstractFileTypeAnalyzer {
}
/**
* Retrieves the next temporary destination directory for extracting an archive.
* Retrieves the next temporary destination directory for extracting an
* archive.
*
* @return a directory
* @throws AnalysisException thrown if unable to create temporary directory

View File

@@ -37,6 +37,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.owasp.dependencycheck.exception.InitializationException;
/**
* Used to analyze a Python package, and collect information that can be used to
@@ -144,10 +145,10 @@ public class PythonPackageAnalyzer extends AbstractFileTypeAnalyzer {
/**
* No-op initializer implementation.
*
* @throws Exception never thrown
* @throws InitializationException never thrown
*/
@Override
protected void initializeFileTypeAnalyzer() throws Exception {
protected void initializeFileTypeAnalyzer() throws InitializationException {
// Nothing to do here.
}

View File

@@ -22,6 +22,7 @@ import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -40,6 +41,7 @@ import org.owasp.dependencycheck.utils.Settings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
import org.owasp.dependencycheck.exception.InitializationException;
/**
* Used to analyze Ruby Bundler Gemspec.lock files utilizing the 3rd party
@@ -50,6 +52,9 @@ import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
@Experimental
public class RubyBundleAuditAnalyzer extends AbstractFileTypeAnalyzer {
/**
* The logger.
*/
private static final Logger LOGGER = LoggerFactory.getLogger(RubyBundleAuditAnalyzer.class);
/**
@@ -126,10 +131,10 @@ public class RubyBundleAuditAnalyzer extends AbstractFileTypeAnalyzer {
* Initialize the analyzer. In this case, extract GrokAssembly.exe to a
* temporary location.
*
* @throws Exception if anything goes wrong
* @throws InitializationException if anything goes wrong
*/
@Override
public void initializeFileTypeAnalyzer() throws Exception {
public void initializeFileTypeAnalyzer() throws InitializationException {
try {
cvedb = new CveDB();
cvedb.open();
@@ -137,25 +142,36 @@ public class RubyBundleAuditAnalyzer extends AbstractFileTypeAnalyzer {
LOGGER.warn("Exception opening the database");
LOGGER.debug("error", ex);
setEnabled(false);
throw ex;
throw new InitializationException("Error connecting to the database", ex);
}
// Now, need to see if bundle-audit actually runs from this location.
Process process = null;
try {
process = launchBundleAudit(Settings.getTempDirectory());
} catch (AnalysisException ae) {
LOGGER.warn("Exception from bundle-audit process: {}. Disabling {}", ae.getCause(), ANALYZER_NAME);
setEnabled(false);
cvedb.close();
cvedb = null;
throw ae;
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);
throw new InitializationException("Unable to create temporary file, the Ruby Bundle Audit Analyzer will be disabled", ex);
}
final int exitValue = process.waitFor();
if (0 == exitValue) {
LOGGER.warn("Unexpected exit code from bundle-audit process. Disabling {}: {}", ANALYZER_NAME, exitValue);
final int exitValue;
try {
exitValue = process.waitFor();
} catch (InterruptedException ex) {
setEnabled(false);
throw new AnalysisException("Unexpected exit code from bundle-audit process.");
final String msg = String.format("Bundle-audit process was interupted. Disabling %s", ANALYZER_NAME);
throw new InitializationException(msg);
}
if (0 == exitValue) {
setEnabled(false);
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;
try {
@@ -163,18 +179,28 @@ public class RubyBundleAuditAnalyzer extends AbstractFileTypeAnalyzer {
if (!reader.ready()) {
LOGGER.warn("Bundle-audit error stream unexpectedly not ready. Disabling " + ANALYZER_NAME);
setEnabled(false);
throw new AnalysisException("Bundle-audit error stream unexpectedly not ready.");
throw new InitializationException("Bundle-audit error stream unexpectedly not ready.");
} else {
final String line = reader.readLine();
if (line == null || !line.contains("Errno::ENOENT")) {
LOGGER.warn("Unexpected bundle-audit output. Disabling {}: {}", ANALYZER_NAME, line);
setEnabled(false);
throw new AnalysisException("Unexpected bundle-audit output.");
throw new InitializationException("Unexpected bundle-audit output.");
}
}
} catch (UnsupportedEncodingException ex) {
setEnabled(false);
throw new InitializationException("Unexpected bundle-audit encoding.", ex);
} catch (IOException ex) {
setEnabled(false);
throw new InitializationException("Unable to read bundle-audit output.", ex);
} finally {
if (null != reader) {
reader.close();
try {
reader.close();
} catch (IOException ex) {
LOGGER.debug("Error closing reader", ex);
}
}
}
}

View File

@@ -108,6 +108,7 @@ public class RubyBundlerAnalyzer extends RubyGemspecAnalyzer {
final File gemsDir = new File(parentDir, GEMS);
if (gemsDir.exists()) {
final File[] matchingFiles = gemsDir.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.equals(gemName);
}

View File

@@ -32,6 +32,7 @@ import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.dependency.Confidence;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.dependency.EvidenceCollection;
import org.owasp.dependencycheck.exception.InitializationException;
import org.owasp.dependencycheck.utils.FileFilterBuilder;
import org.owasp.dependencycheck.utils.Settings;
import org.slf4j.Logger;
@@ -88,7 +89,7 @@ public class RubyGemspecAnalyzer extends AbstractFileTypeAnalyzer {
}
@Override
protected void initializeFileTypeAnalyzer() throws Exception {
protected void initializeFileTypeAnalyzer() throws InitializationException {
// NO-OP
}
@@ -211,6 +212,7 @@ public class RubyGemspecAnalyzer extends AbstractFileTypeAnalyzer {
final File parentDir = dependencyFile.getParentFile();
if (parentDir != null) {
final File[] matchingFiles = parentDir.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.contains(VERSION_FILE_NAME);
}

View File

@@ -20,7 +20,7 @@ package org.owasp.dependencycheck.analyzer;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.suppression.SuppressionRule;
import org.owasp.dependencycheck.xml.suppression.SuppressionRule;
/**
* The suppression analyzer processes an externally defined XML document that complies with the suppressions.xsd schema.

View File

@@ -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
*/
@@ -101,11 +100,11 @@ public final class CpeMemoryIndex {
/**
* The search field analyzer for the product field.
*/
private SearchFieldAnalyzer productSearchFieldAnalyzer;
private SearchFieldAnalyzer productFieldAnalyzer;
/**
* The search field analyzer for the vendor field.
*/
private SearchFieldAnalyzer vendorSearchFieldAnalyzer;
private SearchFieldAnalyzer vendorFieldAnalyzer;
/**
* Creates and loads data into an in memory index.
@@ -144,17 +143,6 @@ public final class CpeMemoryIndex {
return openState;
}
/**
* Creates the indexing analyzer for the CPE Index.
*
* @return the CPE Analyzer.
*/
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.
*
@@ -163,12 +151,12 @@ public final class CpeMemoryIndex {
private Analyzer createSearchingAnalyzer() {
final Map<String, Analyzer> fieldAnalyzers = new HashMap<String, Analyzer>();
fieldAnalyzers.put(Fields.DOCUMENT_KEY, new KeywordAnalyzer());
productSearchFieldAnalyzer = new SearchFieldAnalyzer(LuceneUtils.CURRENT_VERSION);
vendorSearchFieldAnalyzer = new SearchFieldAnalyzer(LuceneUtils.CURRENT_VERSION);
fieldAnalyzers.put(Fields.PRODUCT, productSearchFieldAnalyzer);
fieldAnalyzers.put(Fields.VENDOR, vendorSearchFieldAnalyzer);
productFieldAnalyzer = new SearchFieldAnalyzer(LuceneUtils.CURRENT_VERSION);
vendorFieldAnalyzer = new SearchFieldAnalyzer(LuceneUtils.CURRENT_VERSION);
fieldAnalyzers.put(Fields.PRODUCT, productFieldAnalyzer);
fieldAnalyzers.put(Fields.VENDOR, vendorFieldAnalyzer);
return new PerFieldAnalyzerWrapper(new FieldAnalyzer(LuceneUtils.CURRENT_VERSION), fieldAnalyzers);
return new PerFieldAnalyzerWrapper(new KeywordAnalyzer(), fieldAnalyzers);
}
/**
@@ -206,7 +194,7 @@ public final class CpeMemoryIndex {
Analyzer analyzer = null;
IndexWriter indexWriter = null;
try {
analyzer = createIndexingAnalyzer();
analyzer = createSearchingAnalyzer();
final IndexWriterConfig conf = new IndexWriterConfig(LuceneUtils.CURRENT_VERSION, analyzer);
indexWriter = new IndexWriter(index, conf);
try {
@@ -224,6 +212,7 @@ public final class CpeMemoryIndex {
v.setStringValue(pair.getLeft());
p.setStringValue(pair.getRight());
indexWriter.addDocument(doc);
resetFieldAnalyzer();
}
} catch (DatabaseException ex) {
LOGGER.debug("", ex);
@@ -254,14 +243,14 @@ public final class CpeMemoryIndex {
}
/**
* Resets the searching analyzers
* Resets the product and vendor field analyzers.
*/
private void resetSearchingAnalyzer() {
if (productSearchFieldAnalyzer != null) {
productSearchFieldAnalyzer.clear();
private void resetFieldAnalyzer() {
if (productFieldAnalyzer != null) {
productFieldAnalyzer.clear();
}
if (vendorSearchFieldAnalyzer != null) {
vendorSearchFieldAnalyzer.clear();
if (vendorFieldAnalyzer != null) {
vendorFieldAnalyzer.clear();
}
}
@@ -272,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()) {
@@ -293,7 +283,7 @@ public final class CpeMemoryIndex {
* @throws IOException thrown if there is an IOException
*/
public TopDocs search(Query query, int maxQueryResults) throws CorruptIndexException, IOException {
resetSearchingAnalyzer();
resetFieldAnalyzer();
return indexSearcher.search(query, maxQueryResults);
}

View File

@@ -29,11 +29,15 @@ import org.apache.lucene.util.Version;
/**
* <p>
* A Lucene Analyzer that utilizes the WhitespaceTokenizer, WordDelimiterFilter, LowerCaseFilter, and StopFilter. The intended
* purpose of this Analyzer is to index the CPE fields vendor and product.</p>
* A Lucene Analyzer that utilizes the WhitespaceTokenizer, WordDelimiterFilter,
* LowerCaseFilter, and StopFilter. The intended purpose of this Analyzer is to
* index the CPE fields vendor and product.</p>
*
* @author Jeremy Long
* @deprecated the field analyzer should not be used, instead use the
* SearchFieldAnalyzer so that the token analyzing filter is used.
*/
@Deprecated
public class FieldAnalyzer extends Analyzer {
/**

View File

@@ -20,7 +20,7 @@ package org.owasp.dependencycheck.data.nvdcve;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
@@ -352,11 +352,11 @@ public final class ConnectionFactory {
*/
private static void ensureSchemaVersion(Connection conn) throws DatabaseException {
ResultSet rs = null;
CallableStatement cs = null;
PreparedStatement ps = null;
try {
//TODO convert this to use DatabaseProperties
cs = conn.prepareCall("SELECT value FROM properties WHERE id = 'version'");
rs = cs.executeQuery();
ps = conn.prepareStatement("SELECT value FROM properties WHERE id = 'version'");
rs = ps.executeQuery();
if (rs.next()) {
final DependencyVersion appDbVersion = DependencyVersionUtil.parseVersion(DB_SCHEMA_VERSION);
final DependencyVersion db = DependencyVersionUtil.parseVersion(rs.getString(1));
@@ -376,7 +376,7 @@ public final class ConnectionFactory {
throw new DatabaseException("Unable to check the database schema version");
} finally {
DBUtils.closeResultSet(rs);
DBUtils.closeStatement(cs);
DBUtils.closeStatement(ps);
}
}
}

View File

@@ -19,7 +19,6 @@ package org.owasp.dependencycheck.data.nvdcve;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
@@ -69,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.
*/
@@ -813,14 +811,14 @@ public class CveDB {
* Deletes unused dictionary entries from the database.
*/
public void deleteUnusedCpe() {
CallableStatement cs = null;
PreparedStatement ps = null;
try {
cs = getConnection().prepareCall(statementBundle.getString("DELETE_UNUSED_DICT_CPE"));
cs.executeUpdate();
ps = getConnection().prepareStatement(statementBundle.getString("DELETE_UNUSED_DICT_CPE"));
ps.executeUpdate();
} catch (SQLException ex) {
LOGGER.error("Unable to delete CPE dictionary entries", ex);
} finally {
DBUtils.closeStatement(cs);
DBUtils.closeStatement(ps);
}
}
@@ -837,7 +835,7 @@ public class CveDB {
public void addCpe(String cpe, String vendor, String product) {
PreparedStatement ps = null;
try {
ps = getConnection().prepareCall(statementBundle.getString("ADD_DICT_CPE"));
ps = getConnection().prepareStatement(statementBundle.getString("ADD_DICT_CPE"));
ps.setString(1, cpe);
ps.setString(2, vendor);
ps.setString(3, product);

View File

@@ -36,6 +36,10 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Checks the gh-pages dependency-check site to determine the current released
* version number. If the released version number is greater then the running
* version number a warning is printed recommending that an upgrade be
* performed.
*
* @author Jeremy Long
*/
@@ -59,12 +63,14 @@ public class EngineVersionCheck implements CachedWebDataSource {
private CveDB cveDB = null;
/**
* The version retrieved from the database properties or web to check against.
* The version retrieved from the database properties or web to check
* against.
*/
private String updateToVersion;
/**
* Getter for updateToVersion - only used for testing. Represents the version retrieved from the database.
* Getter for updateToVersion - only used for testing. Represents the
* version retrieved from the database.
*
* @return the version to test
*/
@@ -73,7 +79,8 @@ public class EngineVersionCheck implements CachedWebDataSource {
}
/**
* Setter for updateToVersion - only used for testing. Represents the version retrieved from the database.
* Setter for updateToVersion - only used for testing. Represents the
* version retrieved from the database.
*
* @param version the version to test
*/
@@ -81,9 +88,16 @@ public class EngineVersionCheck implements CachedWebDataSource {
updateToVersion = version;
}
/**
* Downloads the current released version number and compares it to the
* running engine's version number. If the released version number is newer
* a warning is printed recommending an upgrade.
*
* @throws UpdateException thrown if the local database properties could not
* be updated
*/
@Override
public void update() throws UpdateException {
try {
if (Settings.getBoolean(Settings.KEYS.AUTO_UPDATE)) {
openDatabase();
@@ -109,20 +123,21 @@ public class EngineVersionCheck implements CachedWebDataSource {
LOGGER.debug("Unable to determine if autoupdate is enabled", ex);
} finally {
closeDatabase();
}
}
/**
* Determines if a new version of the dependency-check engine has been released.
* Determines if a new version of the dependency-check engine has been
* released.
*
* @param lastChecked the epoch time of the last version check
* @param now the current epoch time
* @param properties the database properties object
* @param currentVersion the current version of dependency-check
* @return <code>true</code> if a newer version of the database has been released; otherwise <code>false</code>
* @throws UpdateException thrown if there is an error connecting to the github documentation site or accessing the local
* database.
* @return <code>true</code> if a newer version of the database has been
* released; otherwise <code>false</code>
* @throws UpdateException thrown if there is an error connecting to the
* github documentation site or accessing the local database.
*/
protected boolean shouldUpdate(final long lastChecked, final long now, final DatabaseProperties properties,
String currentVersion) throws UpdateException {
@@ -185,7 +200,8 @@ public class EngineVersionCheck implements CachedWebDataSource {
}
/**
* Retrieves the current released version number from the github documentation site.
* Retrieves the current released version number from the github
* documentation site.
*
* @return the current released version number
*/
@@ -204,11 +220,11 @@ public class EngineVersionCheck implements CachedWebDataSource {
return releaseVersion.trim();
}
} catch (MalformedURLException ex) {
LOGGER.debug("unable to retrieve current release version of dependency-check", ex);
LOGGER.debug("Unable to retrieve current release version of dependency-check", ex);
} catch (URLConnectionFailureException ex) {
LOGGER.debug("unable to retrieve current release version of dependency-check", ex);
LOGGER.debug("Unable to retrieve current release version of dependency-check", ex);
} catch (IOException ex) {
LOGGER.debug("unable to retrieve current release version of dependency-check", ex);
LOGGER.debug("Unable to retrieve current release version of dependency-check", ex);
} finally {
if (conn != null) {
conn.disconnect();

View File

@@ -50,7 +50,7 @@ import org.slf4j.LoggerFactory;
public class NvdCveUpdater extends BaseUpdater implements CachedWebDataSource {
/**
* The logger
* The logger.
*/
private static final Logger LOGGER = LoggerFactory.getLogger(NvdCveUpdater.class);
/**
@@ -59,9 +59,8 @@ public class NvdCveUpdater extends BaseUpdater implements CachedWebDataSource {
public static final int MAX_THREAD_POOL_SIZE = Settings.getInt(Settings.KEYS.MAX_DOWNLOAD_THREAD_POOL_SIZE, 3);
/**
* <p>
* Downloads the latest NVD CVE XML file from the web and imports it into
* the current CVE Database.</p>
* the current CVE Database.
*
* @throws UpdateException is thrown if there is an error updating the
* database
@@ -84,9 +83,7 @@ public class NvdCveUpdater extends BaseUpdater implements CachedWebDataSource {
}
}
} catch (MalformedURLException ex) {
LOGGER.warn(
"NVD CVE properties files contain an invalid URL, unable to update the data to use the most current data.");
LOGGER.debug("", ex);
throw new UpdateException("NVD CVE properties files contain an invalid URL, unable to update the data to use the most current data.", ex);
} catch (DownloadFailedException ex) {
LOGGER.warn(
"Unable to download the NVD CVE data; the results may not include the most recent CPE/CVEs from the NVD.");
@@ -94,7 +91,7 @@ public class NvdCveUpdater extends BaseUpdater implements CachedWebDataSource {
LOGGER.info(
"If you are behind a proxy you may need to configure dependency-check to use the proxy.");
}
LOGGER.debug("", ex);
throw new UpdateException("Unable to download the NVD CVE data.", ex);
} finally {
closeDataStores();
}
@@ -107,9 +104,9 @@ public class NvdCveUpdater extends BaseUpdater implements CachedWebDataSource {
* checking again. A database property stores the timestamp of the last
* check.
*
* @return true to proceed with the check, or false to skip.
* @return true to proceed with the check, or false to skip
* @throws UpdateException thrown when there is an issue checking for
* updates.
* updates
*/
private boolean checkUpdate() throws UpdateException {
boolean proceed = true;
@@ -171,8 +168,7 @@ public class NvdCveUpdater extends BaseUpdater implements CachedWebDataSource {
return;
}
if (maxUpdates > 3) {
LOGGER.info(
"NVD CVE requires several updates; this could take a couple of minutes.");
LOGGER.info("NVD CVE requires several updates; this could take a couple of minutes.");
}
if (maxUpdates > 0) {
openDataStores();

View File

@@ -22,6 +22,7 @@ import java.util.ArrayList;
import java.util.List;
import org.owasp.dependencycheck.data.update.NvdCveUpdater;
import org.owasp.dependencycheck.data.update.exception.InvalidDataException;
import org.owasp.dependencycheck.utils.Settings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.Attributes;
@@ -40,7 +41,12 @@ public class CPEHandler extends DefaultHandler {
*/
private static final String CURRENT_SCHEMA_VERSION = "2.3";
/**
* The text content of the node being processed. This can be used during the end element event.
* 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:");
/**
* The text content of the node being processed. This can be used during the
* end element event.
*/
private StringBuilder nodeText = null;
/**
@@ -72,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 {
@@ -82,7 +89,7 @@ public class CPEHandler extends DefaultHandler {
final String temp = attributes.getValue("deprecated");
final String value = attributes.getValue("name");
final boolean delete = "true".equalsIgnoreCase(temp);
if (!delete && value.startsWith("cpe:/a:") && value.length() > 7) {
if (!delete && value.startsWith(CPE_STARTS_WITH) && value.length() > 7) {
try {
final Cpe cpe = new Cpe(value);
data.add(cpe);
@@ -123,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 {
@@ -133,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 {
@@ -177,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 {

View File

@@ -17,14 +17,12 @@
*/
package org.owasp.dependencycheck.data.update.exception;
import java.io.IOException;
/**
* An exception used when an error occurs reading a setting.
*
* @author Jeremy Long
*/
public class UpdateException extends IOException {
public class UpdateException extends Exception {
/**
* The serial version uid.

View File

@@ -25,6 +25,8 @@ import java.util.Map.Entry;
import java.util.TreeMap;
import org.owasp.dependencycheck.utils.DownloadFailedException;
import org.owasp.dependencycheck.utils.Downloader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Contains a collection of updateable NvdCveInfo objects. This is used to determine which files need to be downloaded and
@@ -34,6 +36,10 @@ import org.owasp.dependencycheck.utils.Downloader;
*/
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.
*/
@@ -91,6 +97,7 @@ public class UpdateableNvdCve implements Iterable<NvdCveInfo>, Iterator<NvdCveIn
item.setId(id);
item.setUrl(url);
item.setOldSchemaVersionUrl(oldUrl);
LOGGER.debug("Checking for updates from: {}", url);
item.setTimestamp(Downloader.getLastModified(new URL(url)));
collection.put(id, item);
}

View File

@@ -21,7 +21,6 @@ import java.io.Serializable;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.Iterator;
/**
* Contains the information about a vulnerability.
@@ -390,15 +389,15 @@ public class Vulnerability implements Serializable, Comparable<Vulnerability> {
final StringBuilder sb = new StringBuilder("Vulnerability ");
sb.append(this.name);
sb.append("\nReferences:\n");
for (Iterator i = this.references.iterator(); i.hasNext();) {
for (Reference reference : this.references) {
sb.append("=> ");
sb.append(i.next());
sb.append(reference);
sb.append("\n");
}
sb.append("\nSoftware:\n");
for (Iterator i = this.vulnerableSoftware.iterator(); i.hasNext();) {
for (VulnerableSoftware software : this.vulnerableSoftware) {
sb.append("=> ");
sb.append(i.next());
sb.append(software);
sb.append("\n");
}
return sb.toString();

View File

@@ -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);
}
}

View File

@@ -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 initializing analyzers.
*
* @author Jeremy Long
*/
public class InitializationException extends Exception {
/**
* The serial version uid.
*/
private static final long serialVersionUID = 1L;
/**
* Creates a new InitializationException.
*/
public InitializationException() {
super();
}
/**
* Creates a new InitializationException.
*
* @param msg a message for the exception.
*/
public InitializationException(String msg) {
super(msg);
}
/**
* Creates a new InitializationException.
*
* @param ex the cause of the exception.
*/
public InitializationException(Throwable ex) {
super(ex);
}
/**
* Creates a new InitializationException.
*
* @param msg a message for the exception.
* @param ex the cause of the exception.
*/
public InitializationException(String msg, Throwable ex) {
super(msg, ex);
}
}

View File

@@ -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);
}
}

View File

@@ -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 {

View File

@@ -0,0 +1,97 @@
/*
* 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.xml.hints;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
/**
* An XML parsing error handler.
*
* @author Jeremy Long
*/
public class HintErrorHandler implements ErrorHandler {
/**
* The logger.
*/
private static final Logger LOGGER = LoggerFactory.getLogger(HintErrorHandler.class);
/**
* Builds a prettier exception message.
*
* @param ex the SAXParseException
* @return an easier to read exception message
*/
private String getPrettyParseExceptionInfo(SAXParseException ex) {
final StringBuilder sb = new StringBuilder();
if (ex.getSystemId() != null) {
sb.append("systemId=").append(ex.getSystemId()).append(", ");
}
if (ex.getPublicId() != null) {
sb.append("publicId=").append(ex.getPublicId()).append(", ");
}
if (ex.getLineNumber() > 0) {
sb.append("Line=").append(ex.getLineNumber());
}
if (ex.getColumnNumber() > 0) {
sb.append(", Column=").append(ex.getColumnNumber());
}
sb.append(": ").append(ex.getMessage());
return sb.toString();
}
/**
* Logs warnings.
*
* @param ex the warning to log
* @throws SAXException is never thrown
*/
@Override
public void warning(SAXParseException ex) throws SAXException {
LOGGER.debug("", ex);
}
/**
* Handles errors.
*
* @param ex the error to handle
* @throws SAXException is always thrown
*/
@Override
public void error(SAXParseException ex) throws SAXException {
throw new SAXException(getPrettyParseExceptionInfo(ex));
}
/**
* Handles fatal exceptions.
*
* @param ex a fatal exception
* @throws SAXException is always
*/
@Override
public void fatalError(SAXParseException ex) throws SAXException {
throw new SAXException(getPrettyParseExceptionInfo(ex));
}
}

View File

@@ -0,0 +1,217 @@
/*
* 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.xml.hints;
import java.util.ArrayList;
import java.util.List;
import org.owasp.dependencycheck.dependency.Confidence;
import org.owasp.dependencycheck.xml.suppression.PropertyType;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
/**
* A handler to load hint rules.
*
* @author Jeremy Long
*/
public class HintHandler extends DefaultHandler {
//<editor-fold defaultstate="collapsed" desc="Element and attribute names">
/**
* Element name.
*/
private static final String HINT = "hint";
/**
* Element name.
*/
private static final String GIVEN = "given";
/**
* Element name.
*/
private static final String ADD = "add";
/**
* Element name.
*/
private static final String EVIDENCE = "evidence";
/**
* Element name.
*/
private static final String FILE_NAME = "fileName";
/**
* Element name.
*/
private static final String VENDOR_DUPLICATING_RULE = "vendorDuplicatingHint";
/**
* Attribute name.
*/
private static final String DUPLICATE = "duplicate";
/**
* Attribute name.
*/
private static final String VENDOR = "vendor";
/**
* Attribute name.
*/
private static final String CONFIDENCE = "confidence";
/**
* Attribute name.
*/
private static final String VALUE = "value";
/**
* Attribute name.
*/
private static final String NAME = "name";
/**
* Attribute name.
*/
private static final String SOURCE = "source";
/**
* Attribute name.
*/
private static final String TYPE = "type";
/**
* Attribute name.
*/
private static final String CASE_SENSITIVE = "caseSensitive";
/**
* Attribute name.
*/
private static final String REGEX = "regex";
/**
* Attribute name.
*/
private static final String CONTAINS = "contains";
//</editor-fold>
/**
* The list of hint rules.
*/
private final List<HintRule> hintRules = new ArrayList<HintRule>();
/**
* Returns the list of hint rules.
*
* @return the value of hintRules
*/
public List<HintRule> getHintRules() {
return hintRules;
}
/**
* The list of vendor duplicating hint rules.
*/
private final List<VendorDuplicatingHintRule> vendorDuplicatingHintRules = new ArrayList<VendorDuplicatingHintRule>();
/**
* Returns the list of vendor duplicating hint rules.
*
* @return the list of vendor duplicating hint rules
*/
public List<VendorDuplicatingHintRule> getVendorDuplicatingHintRules() {
return vendorDuplicatingHintRules;
}
/**
* The current rule being read.
*/
private HintRule rule;
/**
* The current state of the parent node (to differentiate between 'add' and
* 'given').
*/
private boolean inAddNode = false;
/**
* Handles the start element event.
*
* @param uri the uri of the element being processed
* @param localName the local name of the element being processed
* @param qName the qName of the element being processed
* @param attr the attributes of the element being processed
* @throws SAXException thrown if there is an exception processing
*/
@Override
public void startElement(String uri, String localName, String qName, Attributes attr) throws SAXException {
if (HINT.equals(qName)) {
rule = new HintRule();
} else if (ADD.equals(qName)) {
inAddNode = true;
} else if (GIVEN.equals(qName)) {
inAddNode = false;
} else if (EVIDENCE.equals(qName)) {
final String hintType = attr.getValue(TYPE);
if (VENDOR.equals(hintType)) {
if (inAddNode) {
rule.addAddVendor(attr.getValue(SOURCE),
attr.getValue(NAME),
attr.getValue(VALUE),
Confidence.valueOf(attr.getValue(CONFIDENCE)));
} else {
rule.addGivenVendor(attr.getValue(SOURCE),
attr.getValue(NAME),
attr.getValue(VALUE),
Confidence.valueOf(attr.getValue(CONFIDENCE)));
}
} else if (inAddNode) {
rule.addAddProduct(attr.getValue(SOURCE),
attr.getValue(NAME),
attr.getValue(VALUE),
Confidence.valueOf(attr.getValue(CONFIDENCE)));
} else {
rule.addGivenProduct(attr.getValue(SOURCE),
attr.getValue(NAME),
attr.getValue(VALUE),
Confidence.valueOf(attr.getValue(CONFIDENCE)));
}
} else if (FILE_NAME.equals(qName)) {
final PropertyType pt = new PropertyType();
pt.setValue(attr.getValue(CONTAINS));
if (attr.getLength() > 0) {
final String regex = attr.getValue(REGEX);
if (regex != null) {
pt.setRegex(Boolean.parseBoolean(regex));
}
final String caseSensitive = attr.getValue(CASE_SENSITIVE);
if (caseSensitive != null) {
pt.setCaseSensitive(Boolean.parseBoolean(caseSensitive));
}
}
rule.addFilename(pt);
} else if (VENDOR_DUPLICATING_RULE.equals(qName)) {
vendorDuplicatingHintRules.add(new VendorDuplicatingHintRule(attr.getValue(VALUE), attr.getValue(DUPLICATE)));
}
}
/**
* Handles the end element event.
*
* @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
*/
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if (HINT.equals(qName) && rule != null) {
hintRules.add(rule);
rule = null;
}
}
}

View File

@@ -0,0 +1,68 @@
/*
* 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.xml.hints;
import java.io.IOException;
/**
* An exception used when parsing a suppression rule file fails.
*
* @author Jeremy Long
*/
public class HintParseException extends IOException {
/**
* The serial version UID for serialization.
*/
private static final long serialVersionUID = 1L;
/**
* Creates a new SuppressionParseException.
*/
public HintParseException() {
super();
}
/**
* Creates a new SuppressionParseException.
*
* @param msg a message for the exception.
*/
public HintParseException(String msg) {
super(msg);
}
/**
* Creates a new SuppressionParseException.
*
* @param ex the cause of the parse exception
*/
public HintParseException(Throwable ex) {
super(ex);
}
/**
* Creates a new SuppressionParseException.
*
* @param msg a message for the exception.
* @param ex the cause of the parse exception
*/
public HintParseException(String msg, Throwable ex) {
super(msg, ex);
}
}

View File

@@ -0,0 +1,146 @@
/*
* 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.xml.hints;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
/**
* A simple validating parser for XML Hint Rules.
*
* @author Jeremy Long
*/
public class HintParser {
/**
* The logger.
*/
private static final Logger LOGGER = LoggerFactory.getLogger(HintParser.class);
/**
* JAXP Schema Language. Source:
* http://docs.oracle.com/javase/tutorial/jaxp/sax/validation.html
*/
public static final String JAXP_SCHEMA_LANGUAGE = "http://java.sun.com/xml/jaxp/properties/schemaLanguage";
/**
* W3C XML Schema. Source:
* http://docs.oracle.com/javase/tutorial/jaxp/sax/validation.html
*/
public static final String W3C_XML_SCHEMA = "http://www.w3.org/2001/XMLSchema";
/**
* JAXP Schema Source. Source:
* http://docs.oracle.com/javase/tutorial/jaxp/sax/validation.html
*/
public static final String JAXP_SCHEMA_SOURCE = "http://java.sun.com/xml/jaxp/properties/schemaSource";
/**
* The schema for the hint XML files.
*/
private static final String HINT_SCHEMA = "schema/dependency-hint.1.0.xsd";
/**
* Parses the given XML file and returns a list of the hints contained.
*
* @param file an XML file containing hints
* @return a list of hint rules
* @throws HintParseException thrown if the XML file cannot be parsed
*/
public Hints parseHints(File file) throws HintParseException {
FileInputStream fis = null;
try {
fis = new FileInputStream(file);
return parseHints(fis);
} catch (IOException ex) {
LOGGER.debug("", ex);
throw new HintParseException(ex);
} catch (SAXException ex) {
throw new HintParseException(ex);
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException ex) {
LOGGER.debug("Unable to close stream", ex);
}
}
}
}
/**
* Parses the given XML stream and returns a list of the hint rules
* contained.
*
* @param inputStream an InputStream containing hint rules
* @return a list of hint rules
* @throws HintParseException thrown if the XML cannot be parsed
* @throws SAXException thrown if the XML cannot be parsed
*/
public Hints parseHints(InputStream inputStream) throws HintParseException, SAXException {
try {
final InputStream schemaStream = this.getClass().getClassLoader().getResourceAsStream(HINT_SCHEMA);
final HintHandler handler = new HintHandler();
final SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setNamespaceAware(true);
factory.setValidating(true);
final SAXParser saxParser = factory.newSAXParser();
saxParser.setProperty(HintParser.JAXP_SCHEMA_LANGUAGE, HintParser.W3C_XML_SCHEMA);
saxParser.setProperty(HintParser.JAXP_SCHEMA_SOURCE, new InputSource(schemaStream));
final XMLReader xmlReader = saxParser.getXMLReader();
xmlReader.setErrorHandler(new HintErrorHandler());
xmlReader.setContentHandler(handler);
final Reader reader = new InputStreamReader(inputStream, "UTF-8");
final InputSource in = new InputSource(reader);
xmlReader.parse(in);
final Hints hints = new Hints();
hints.setHintRules(handler.getHintRules());
hints.setVendorDuplicatingHintRules(handler.getVendorDuplicatingHintRules());
return hints;
} catch (ParserConfigurationException ex) {
LOGGER.debug("", ex);
throw new HintParseException(ex);
} catch (SAXException ex) {
if (ex.getMessage().contains("Cannot find the declaration of element 'hints'.")) {
throw ex;
} else {
LOGGER.debug("", ex);
throw new HintParseException(ex);
}
} catch (FileNotFoundException ex) {
LOGGER.debug("", ex);
throw new HintParseException(ex);
} catch (IOException ex) {
LOGGER.debug("", ex);
throw new HintParseException(ex);
}
}
}

View File

@@ -0,0 +1,160 @@
/*
* 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.xml.hints;
import java.util.ArrayList;
import java.util.List;
import org.owasp.dependencycheck.dependency.Confidence;
import org.owasp.dependencycheck.dependency.Evidence;
import org.owasp.dependencycheck.xml.suppression.PropertyType;
/**
* A collection of product and vendor evidence to match; if any evidence is
* matched the addVendor and addProduct evidence should be added to the
* dependency.
*
* @author Jeremy Long
*/
public class HintRule {
/**
* The list of file names to match.
*/
private final List<PropertyType> filenames = new ArrayList<PropertyType>();
/**
* Adds the filename evidence to the collection.
*
* @param filename the filename to add
*/
public void addFilename(PropertyType filename) {
this.filenames.add(filename);
}
/**
* Returns the list of filename evidence to match against.
*
* @return the list of filename evidence to match against
*/
public List<PropertyType> getFilenames() {
return filenames;
}
/**
* The list of product evidence that is being matched.
*/
private final List<Evidence> givenProduct = new ArrayList<Evidence>();
/**
* Adds a given product to the list of evidence to matched.
*
* @param source the source of the evidence
* @param name the name of the evidence
* @param value the value of the evidence
* @param confidence the confidence of the evidence
*/
public void addGivenProduct(String source, String name, String value, Confidence confidence) {
givenProduct.add(new Evidence(source, name, value, confidence));
}
/**
* Get the value of givenProduct.
*
* @return the value of givenProduct
*/
public List<Evidence> getGivenProduct() {
return givenProduct;
}
/**
* The list of vendor evidence that is being matched.
*/
private final List<Evidence> givenVendor = new ArrayList<Evidence>();
/**
* Adds a given vendors to the list of evidence to matched.
*
* @param source the source of the evidence
* @param name the name of the evidence
* @param value the value of the evidence
* @param confidence the confidence of the evidence
*/
public void addGivenVendor(String source, String name, String value, Confidence confidence) {
givenVendor.add(new Evidence(source, name, value, confidence));
}
/**
* Get the value of givenVendor.
*
* @return the value of givenVendor
*/
public List<Evidence> getGivenVendor() {
return givenVendor;
}
/**
* The list of product evidence to add.
*/
private final List<Evidence> addProduct = new ArrayList<Evidence>();
/**
* Adds a given product to the list of evidence to add when matched.
*
* @param source the source of the evidence
* @param name the name of the evidence
* @param value the value of the evidence
* @param confidence the confidence of the evidence
*/
public void addAddProduct(String source, String name, String value, Confidence confidence) {
addProduct.add(new Evidence(source, name, value, confidence));
}
/**
* Get the value of addProduct.
*
* @return the value of addProduct
*/
public List<Evidence> getAddProduct() {
return addProduct;
}
/**
* The list of vendor hints to add.
*/
private final List<Evidence> addVendor = new ArrayList<Evidence>();
/**
* Adds a given vendor to the list of evidence to add when matched.
*
* @param source the source of the evidence
* @param name the name of the evidence
* @param value the value of the evidence
* @param confidence the confidence of the evidence
*/
public void addAddVendor(String source, String name, String value, Confidence confidence) {
addVendor.add(new Evidence(source, name, value, confidence));
}
/**
* Get the value of addVendor.
*
* @return the value of addVendor
*/
public List<Evidence> getAddVendor() {
return addVendor;
}
}

View File

@@ -0,0 +1,74 @@
/*
* 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.xml.hints;
import java.util.List;
/**
* A collection of hint rules.
*
* @author Jeremy Long
*/
public class Hints {
/**
* The list of hint rules.
*/
private List<HintRule> hintRules;
/**
* Get the value of hintRules.
*
* @return the value of hintRules
*/
public List<HintRule> getHintRules() {
return hintRules;
}
/**
* Set the value of hintRules.
*
* @param hintRules new value of hintRules
*/
public void setHintRules(List<HintRule> hintRules) {
this.hintRules = hintRules;
}
/**
* The duplicating hint rules.
*/
private List<VendorDuplicatingHintRule> vendorDuplicatingHintRules;
/**
* Get the value of vendorDuplicatingHintRules.
*
* @return the value of vendorDuplicatingHintRules
*/
public List<VendorDuplicatingHintRule> getVendorDuplicatingHintRules() {
return vendorDuplicatingHintRules;
}
/**
* Set the value of vendorDuplicatingHintRules.
*
* @param vendorDuplicatingHintRules new value of vendorDuplicatingHintRules
*/
public void setVendorDuplicatingHintRules(List<VendorDuplicatingHintRule> vendorDuplicatingHintRules) {
this.vendorDuplicatingHintRules = vendorDuplicatingHintRules;
}
}

View File

@@ -0,0 +1,85 @@
/*
* 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.xml.hints;
/**
* Used to duplicate vendor evidence within a collection. The intent is if any evidence
* is found in a collection that matches the value given the evidence will be
* duplicated and the value replaced with the value indicated.
*
* @author Jeremy Long
*/
public class VendorDuplicatingHintRule {
/**
* Constructs a new duplicating rule.
*
* @param value the value to duplicate the evidence if found
* @param duplicate the value to replace within the duplicated evidence
*/
public VendorDuplicatingHintRule(String value, String duplicate) {
this.value = value;
this.duplicate = duplicate;
}
/**
* The evidence value to duplicate if found.
*/
private String value;
/**
* Get the value of value.
*
* @return the value of value
*/
public String getValue() {
return value;
}
/**
* Set the value of value.
*
* @param value new value of value
*/
public void setValue(String value) {
this.value = value;
}
/**
* The value to replace when duplicating the evidence.
*/
private String duplicate;
/**
* Get the value of duplicate.
*
* @return the value of duplicate
*/
public String getDuplicate() {
return duplicate;
}
/**
* Set the value of duplicate.
*
* @param duplicate new value of duplicate
*/
public void setDuplicate(String duplicate) {
this.duplicate = duplicate;
}
}

View File

@@ -0,0 +1,4 @@
/**
* Contains classes used to parse the hints file to add evidence to dependencies.
*/
package org.owasp.dependencycheck.xml.hints;

View File

@@ -15,7 +15,7 @@
*
* Copyright (c) 2013 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.suppression;
package org.owasp.dependencycheck.xml.suppression;
import java.util.regex.Pattern;

View File

@@ -15,7 +15,7 @@
*
* Copyright (c) 2013 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.suppression;
package org.owasp.dependencycheck.xml.suppression;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

View File

@@ -15,7 +15,7 @@
*
* Copyright (c) 2013 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.suppression;
package org.owasp.dependencycheck.xml.suppression;
import java.util.ArrayList;
import java.util.List;

View File

@@ -15,7 +15,7 @@
*
* Copyright (c) 2013 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.suppression;
package org.owasp.dependencycheck.xml.suppression;
import java.io.IOException;

View File

@@ -15,7 +15,7 @@
*
* Copyright (c) 2013 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.suppression;
package org.owasp.dependencycheck.xml.suppression;
import java.io.File;
import java.io.FileInputStream;
@@ -61,14 +61,22 @@ public class SuppressionParser {
* http://docs.oracle.com/javase/tutorial/jaxp/sax/validation.html
*/
public static final String JAXP_SCHEMA_SOURCE = "http://java.sun.com/xml/jaxp/properties/schemaSource";
/**
* The suppression schema file location.
*/
private static final String SUPPRESSION_SCHEMA = "schema/dependency-suppression.1.1.xsd";
/**
* The old suppression schema file location.
*/
private static final String OLD_SUPPRESSION_SCHEMA = "schema/suppression.xsd";
/**
* Parses the given xml file and returns a list of the suppression rules
* Parses the given XML file and returns a list of the suppression rules
* contained.
*
* @param file an xml file containing suppression rules
* @param file an XML file containing suppression rules
* @return a list of suppression rules
* @throws SuppressionParseException thrown if the xml file cannot be parsed
* @throws SuppressionParseException thrown if the XML file cannot be parsed
*/
public List<SuppressionRule> parseSuppressionRules(File file) throws SuppressionParseException {
FileInputStream fis = null;
@@ -104,17 +112,17 @@ public class SuppressionParser {
}
/**
* Parses the given xml stream and returns a list of the suppression rules
* Parses the given XML stream and returns a list of the suppression rules
* contained.
*
* @param inputStream an InputStream containing suppression rues
* @param inputStream an InputStream containing suppression rules
* @return a list of suppression rules
* @throws SuppressionParseException thrown if the xml cannot be parsed
* @throws SAXException thrown if the xml cannot be parsed
* @throws SuppressionParseException thrown if the XML cannot be parsed
* @throws SAXException thrown if the XML cannot be parsed
*/
public List<SuppressionRule> parseSuppressionRules(InputStream inputStream) throws SuppressionParseException, SAXException {
try {
final InputStream schemaStream = this.getClass().getClassLoader().getResourceAsStream("schema/dependency-suppression.1.1.xsd");
final InputStream schemaStream = this.getClass().getClassLoader().getResourceAsStream(SUPPRESSION_SCHEMA);
final SuppressionHandler handler = new SuppressionHandler();
final SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setNamespaceAware(true);
@@ -153,16 +161,16 @@ public class SuppressionParser {
}
/**
* Parses the given xml stream and returns a list of the suppression rules
* Parses the given XML stream and returns a list of the suppression rules
* contained.
*
* @param inputStream an InputStream containing suppression rues
* @return a list of suppression rules
* @throws SuppressionParseException if the xml cannot be parsed
* @throws SuppressionParseException if the XML cannot be parsed
*/
private List<SuppressionRule> parseOldSuppressionRules(InputStream inputStream) throws SuppressionParseException {
try {
final InputStream schemaStream = this.getClass().getClassLoader().getResourceAsStream("schema/suppression.xsd");
final InputStream schemaStream = this.getClass().getClassLoader().getResourceAsStream(OLD_SUPPRESSION_SCHEMA);
final SuppressionHandler handler = new SuppressionHandler();
final SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setNamespaceAware(true);
@@ -176,7 +184,6 @@ public class SuppressionParser {
final Reader reader = new InputStreamReader(inputStream, "UTF-8");
final InputSource in = new InputSource(reader);
//in.setEncoding("UTF-8");
xmlReader.parse(in);

View File

@@ -15,7 +15,7 @@
*
* Copyright (c) 2013 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.suppression;
package org.owasp.dependencycheck.xml.suppression;
import java.util.ArrayList;
import java.util.Iterator;

View File

@@ -1,4 +1,4 @@
/**
* Contains classes used to suppress findings.
*/
package org.owasp.dependencycheck.suppression;
package org.owasp.dependencycheck.xml.suppression;

View File

@@ -0,0 +1,75 @@
<?xml version="1.0" encoding="UTF-8"?>
<hints xmlns="https://jeremylong.github.io/DependencyCheck/dependency-hint.1.0.xsd">
<hint>
<given>
<evidence type="product" source="Manifest" name="Implementation-Title" value="Spring Framework" confidence="HIGH"/>
<evidence type="product" source="Manifest" name="Implementation-Title" value="org.springframework.core" confidence="HIGH"/>
<evidence type="product" source="Manifest" name="Implementation-Title" value="spring-core" confidence="HIGH"/>
</given>
<add>
<evidence type="product" source="hint analyzer" name="product" value="springsource_spring_framework" confidence="HIGH"/>
<evidence type="vendor" source="hint analyzer" name="vendor" value="SpringSource" confidence="HIGH"/>
<evidence type="vendor" source="hint analyzer" name="vendor" value="vmware" confidence="HIGH"/>
<evidence type="vendor" source="hint analyzer" name="vendor" value="pivotal" confidence="HIGH"/>
</add>
</hint>
<hint>
<given>
<evidence type="product" source="jar" name="package name" value="springframework" confidence="LOW"/>
<fileName contains="spring"/>
</given>
<add>
<evidence type="product" source="hint analyzer" name="product" value="springsource_spring_framework" confidence="HIGH"/>
<evidence type="vendor" source="hint analyzer" name="vendor" value="SpringSource" confidence="HIGH"/>
<evidence type="vendor" source="hint analyzer" name="vendor" value="vmware" confidence="HIGH"/>
<evidence type="vendor" source="hint analyzer" name="vendor" value="pivotal" confidence="HIGH"/>
</add>
</hint>
<hint>
<given>
<evidence type="product" source="jar" name="package name" value="springframework" confidence="LOW"/>
</given>
<add>
<evidence type="product" source="hint analyzer" name="product" value="springsource_spring_framework" confidence="HIGH"/>
<evidence type="vendor" source="hint analyzer" name="vendor" value="vmware" confidence="HIGH"/>
<evidence type="vendor" source="hint analyzer" name="vendor" value="pivotal" confidence="HIGH"/>
</add>
</hint>
<hint>
<given>
<evidence type="product" source="Manifest" name="Bundle-Name" value="Spring Security Core" confidence="MEDIUM"/>
<evidence type="product" source="pom" name="artifactid" value="spring-security-core" confidence="HIGH"/>
</given>
<add>
<evidence type="product" source="hint analyzer" name="product" value="springsource_spring_framework" confidence="HIGH"/>
<evidence type="vendor" source="hint analyzer" name="vendor" value="SpringSource" confidence="HIGH"/>
<evidence type="vendor" source="hint analyzer" name="vendor" value="vmware" confidence="HIGH"/>
</add>
</hint>
<hint>
<given>
<evidence type="vendor" source="composer.lock" name="vendor" value="symfony" confidence="HIGHEST"/>
</given>
<add>
<evidence type="vendor" source="hint analyzer" name="vendor" value="sensiolabs" confidence="HIGHEST"/>
</add>
</hint>
<hint>
<given>
<evidence type="vendor" source="composer.lock" name="vendor" value="zendframework" confidence="HIGHEST"/>
</given>
<add>
<evidence type="vendor" source="hint analyzer" name="vendor" value="zend" confidence="HIGHEST"/>
</add>
</hint>
<hint>
<given>
<evidence type="product" source="composer.lock" name="product" value="zendframework" confidence="HIGHEST"/>
</given>
<add>
<evidence type="vendor" source="hint analyzer" name="vendor" value="zend_framework" confidence="HIGHEST"/>
</add>
</hint>
<vendorDuplicatingHint value="sun" duplicate="oracle"/>
<vendorDuplicatingHint value="oracle" duplicate="sun"/>
</hints>

View File

@@ -56,6 +56,13 @@
<cpe>cpe:/a:oracle:glassfish</cpe>
<cpe>cpe:/a:oracle:oracle_client</cpe>
</suppress>
<suppress base="true">
<notes><![CDATA[
Supresses false positives on jersey-apache-client4
]]></notes>
<gav regex="true">com\.sun\.jersey\.contribs:jersey-apache-client.*</gav>
<cpe>cpe:/a:apache:httpclient</cpe>
</suppress>
<suppress base="true">
<notes><![CDATA[
Suppresses false positives on glassfish

View File

@@ -59,6 +59,7 @@ cve.url-1.2.base=https://nvd.nist.gov/download/nvdcve-%d.xml.gz
#cve.url-1.2.base=http://nvd.nist.gov/download/nvdcve-%d.xml
cve.url-2.0.base=https://nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-%d.xml.gz
#cve.url-2.0.base=http://static.nvd.nist.gov/feeds/xml/cve/nvdcve-2.0-%d.xml
cve.cpe.startswith.filter=cpe:/a:
cpe.validfordays=30
cpe.url=http://static.nvd.nist.gov/feeds/xml/cpe/dictionary/official-cpe-dictionary_v2.3.xml.gz

View File

@@ -0,0 +1,68 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema id="hints"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified"
targetNamespace="https://jeremylong.github.io/DependencyCheck/dependency-hint.1.0.xsd"
xmlns:dc="https://jeremylong.github.io/DependencyCheck/dependency-hint.1.0.xsd">
<xs:simpleType name="type">
<xs:restriction base="xs:string">
<xs:enumeration value="vendor"/>
<xs:enumeration value="product"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="confidence">
<xs:restriction base="xs:string">
<xs:enumeration value="HIGHEST"/>
<xs:enumeration value="HIGH"/>
<xs:enumeration value="MEDIUM"/>
<xs:enumeration value="LOW"/>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="evidence">
<xs:attribute name="type" use="required" type="dc:type"/>
<xs:attribute name="source" use="required" type="xs:string"/>
<xs:attribute name="name" use="required" type="xs:string"/>
<xs:attribute name="value" use="required" type="xs:string"/>
<xs:attribute name="confidence" use="required" type="dc:confidence"/>
</xs:complexType>
<xs:complexType name="fileName">
<xs:attribute name="contains" use="required" type="xs:string"/>
<xs:attribute name="regex" use="optional" type="xs:boolean" default="false"/>
<xs:attribute name="caseSensitive" use="optional" type="xs:boolean" default="false"/>
</xs:complexType>
<xs:complexType name="given">
<xs:choice minOccurs="1" maxOccurs="unbounded">
<xs:element name="evidence" type="dc:evidence"/>
<xs:element name="fileName" type="dc:fileName"/>
</xs:choice>
</xs:complexType>
<xs:complexType name="add">
<xs:sequence minOccurs="1" maxOccurs="unbounded">
<xs:element name="evidence" type="dc:evidence"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="hint">
<xs:sequence minOccurs="1" maxOccurs="1">
<xs:element name="given" type="dc:given"/>
<xs:element name="add" type="dc:add"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="duplicatingHint">
<xs:attribute name="value" use="required" type="xs:string"/>
<xs:attribute name="duplicate" use="required" type="xs:string"/>
</xs:complexType>
<xs:element name="hints">
<xs:complexType>
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:element name="hint" type="dc:hint"/>
</xs:sequence>
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:element name="vendorDuplicatingHint" type="dc:duplicatingHint"/>
</xs:sequence>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>

View File

@@ -541,7 +541,7 @@ arising out of or in connection with the use of this tool, the analysis performe
<ul class="indent">
<li><i>dependency-check version</i>: $version</li>
<li><i>Report Generated On</i>: $scanDate</li>
<li><i>Dependencies Scanned</i>:&nbsp;$depCount</li>
<li><i>Dependencies Scanned</i>:&nbsp;$depCount ($dependencies.size() unique)</li>
<li><i>Vulnerable Dependencies</i>:&nbsp;$vulnDepCount</li>
<li><i>Vulnerabilities Found</i>:&nbsp;$vulnCount</li>
<li><i>Vulnerabilities Suppressed</i>:&nbsp;$vulnSuppressedCount</li>
@@ -660,13 +660,13 @@ arising out of or in connection with the use of this tool, the analysis performe
<b>MD5:</b>&nbsp;$enc.html($dependency.Md5sum)<br/>
<b>SHA1:</b>&nbsp;$enc.html($dependency.Sha1sum)
#if ($dependency.projectReferences.size()==1)
<br/><b>Referenced In Project:</b>
<br/><b>Referenced In Project/Scope:</b>
#foreach($ref in $dependency.projectReferences)
$enc.html($ref)
#end
#end
#if ($dependency.projectReferences.size()>1)
<br/><b>Referenced In Projects:</b><ul>
<br/><b>Referenced In Projects/Scopes:</b><ul>
#foreach($ref in $dependency.projectReferences)
<li>$enc.html($ref)</li>
#end

View File

@@ -17,13 +17,19 @@
*/
package org.owasp.dependencycheck;
import org.junit.After;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import static org.junit.Assert.assertTrue;
import org.junit.Before;
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;
/**
@@ -35,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);
@@ -46,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();

View File

@@ -23,8 +23,7 @@ import org.owasp.dependencycheck.BaseTest;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.suppression.SuppressionParseException;
import org.owasp.dependencycheck.suppression.SuppressionRule;
import org.owasp.dependencycheck.xml.suppression.SuppressionRule;
import org.owasp.dependencycheck.utils.Settings;
import org.slf4j.LoggerFactory;
@@ -35,6 +34,7 @@ import java.util.Set;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import org.owasp.dependencycheck.exception.InitializationException;
/**
* @author Jeremy Long
@@ -49,7 +49,8 @@ public class AbstractSuppressionAnalyzerTest extends BaseTest {
}
/**
* Test of getSupportedExtensions method, of class AbstractSuppressionAnalyzer.
* Test of getSupportedExtensions method, of class
* AbstractSuppressionAnalyzer.
*/
@Test
public void testGetSupportedExtensions() {
@@ -58,7 +59,8 @@ public class AbstractSuppressionAnalyzerTest extends BaseTest {
}
/**
* Test of getRules method, of class AbstractSuppressionAnalyzer for suppression file declared as URL.
* Test of getRules method, of class AbstractSuppressionAnalyzer for
* suppression file declared as URL.
*/
@Test
public void testGetRulesFromSuppressionFileFromURL() throws Exception {
@@ -70,7 +72,8 @@ public class AbstractSuppressionAnalyzerTest extends BaseTest {
}
/**
* Test of getRules method, of class AbstractSuppressionAnalyzer for suppression file declared as URL.
* Test of getRules method, of class AbstractSuppressionAnalyzer for
* suppression file declared as URL.
*/
@Test
public void testGetRulesFromSuppressionFileInClasspath() throws Exception {
@@ -81,7 +84,7 @@ public class AbstractSuppressionAnalyzerTest extends BaseTest {
assertTrue(expCount <= currentSize);
}
@Test(expected = SuppressionParseException.class)
@Test(expected = InitializationException.class)
public void testFailureToLocateSuppressionFileAnywhere() throws Exception {
Settings.setString(Settings.KEYS.SUPPRESSION_FILE, "doesnotexist.xml");
instance.initialize();

View File

@@ -17,7 +17,6 @@
*/
package org.owasp.dependencycheck.analyzer;
import java.util.Iterator;
import java.util.List;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

View File

@@ -116,7 +116,6 @@ public class ArchiveAnalyzerIntegrationTest extends BaseDBTestCase {
try {
instance.initialize();
File file = BaseTest.getResourceAsFile(this, "daytrader-ear-2.1.7.ear");
//File file = new File(this.getClass().getClassLoader().getResource("daytrader-ear-2.1.7.ear").getPath());
Dependency dependency = new Dependency(file);
Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, false);
Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED, false);
@@ -136,6 +135,36 @@ public class ArchiveAnalyzerIntegrationTest extends BaseDBTestCase {
}
}
/**
* Test of analyze method, of class ArchiveAnalyzer, with an executable jar.
*/
@Test
public void testAnalyzeExecutableJar() throws Exception {
ArchiveAnalyzer instance = new ArchiveAnalyzer();
//trick the analyzer into thinking it is active.
instance.accept(new File("test.ear"));
try {
instance.initialize();
File file = BaseTest.getResourceAsFile(this, "bootable-0.1.0.jar");
Dependency dependency = new Dependency(file);
Settings.setBoolean(Settings.KEYS.AUTO_UPDATE, false);
Settings.setBoolean(Settings.KEYS.ANALYZER_NEXUS_ENABLED, false);
Settings.setBoolean(Settings.KEYS.ANALYZER_CENTRAL_ENABLED, false);
Engine engine = new Engine();
int initial_size = engine.getDependencies().size();
instance.analyze(dependency, engine);
int ending_size = engine.getDependencies().size();
engine.cleanup();
assertTrue(initial_size < ending_size);
} finally {
instance.close();
}
}
/**
* Test of analyze method, of class ArchiveAnalyzer.
*/

View File

@@ -16,22 +16,17 @@
package org.owasp.dependencycheck.analyzer;
import java.io.File;
import java.io.FileFilter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.*;
import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeNotNull;
import org.owasp.dependencycheck.BaseTest;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.utils.Settings;
/**

View File

@@ -31,6 +31,7 @@ import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.dependency.Confidence;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.dependency.Evidence;
import org.owasp.dependencycheck.exception.InitializationException;
import org.owasp.dependencycheck.utils.Settings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -64,7 +65,7 @@ public class AssemblyAnalyzerTest extends BaseTest {
if (e.getMessage().contains("Could not execute .NET AssemblyAnalyzer")) {
LOGGER.warn("Exception setting up AssemblyAnalyzer. Tests will be incomplete");
} else {
LOGGER.warn("Exception setting up AssemblyAnalyzer. Tests will be incomplete", e);
LOGGER.warn("Exception setting up AssemblyAnalyzer. Tests will be incomplete");
}
Assume.assumeNoException("Is mono installed? TESTS WILL BE INCOMPLETE", e);
}
@@ -157,8 +158,8 @@ public class AssemblyAnalyzerTest extends BaseTest {
AssemblyAnalyzer aanalyzer = new AssemblyAnalyzer();
aanalyzer.accept(new File("test.dll")); // trick into "thinking it is active"
aanalyzer.initialize();
fail("Expected an AnalysisException");
} catch (AnalysisException ae) {
fail("Expected an InitializationException");
} catch (InitializationException ae) {
assertEquals("An error occurred with the .NET AssemblyAnalyzer", ae.getMessage());
} finally {
System.setProperty(LOG_KEY, oldProp);

View File

@@ -29,6 +29,7 @@ import static org.junit.Assert.assertTrue;
import org.junit.Test;
import org.owasp.dependencycheck.BaseTest;
import org.owasp.dependencycheck.BaseDBTestCase;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.data.cpe.IndexEntry;
import org.owasp.dependencycheck.dependency.Confidence;
import org.owasp.dependencycheck.dependency.Dependency;
@@ -82,23 +83,33 @@ public class CPEAnalyzerIntegrationTest extends BaseDBTestCase {
*/
@Test
public void testDetermineCPE_full() throws Exception {
CPEAnalyzer instance = new CPEAnalyzer();
instance.open();
FileNameAnalyzer fnAnalyzer = new FileNameAnalyzer();
JarAnalyzer jarAnalyzer = new JarAnalyzer();
HintAnalyzer hAnalyzer = new HintAnalyzer();
FalsePositiveAnalyzer fp = new FalsePositiveAnalyzer();
//update needs to be performed so that xtream can be tested
Engine e = new Engine();
e.doUpdates();
CPEAnalyzer cpeAnalyzer = new CPEAnalyzer();
try {
//callDetermineCPE_full("struts2-core-2.3.16.3.jar", "cpe:/a:apache:struts:2.3.16.3", instance, fnAnalyzer, jarAnalyzer, hAnalyzer, fp);
callDetermineCPE_full("hazelcast-2.5.jar", null, instance, fnAnalyzer, jarAnalyzer, hAnalyzer, fp);
callDetermineCPE_full("spring-context-support-2.5.5.jar", "cpe:/a:springsource:spring_framework:2.5.5", instance, fnAnalyzer, jarAnalyzer, hAnalyzer, fp);
callDetermineCPE_full("spring-core-3.0.0.RELEASE.jar", "cpe:/a:vmware:springsource_spring_framework:3.0.0", instance, fnAnalyzer, jarAnalyzer, hAnalyzer, fp);
callDetermineCPE_full("org.mortbay.jetty.jar", "cpe:/a:mortbay_jetty:jetty:4.2.27", instance, fnAnalyzer, jarAnalyzer, hAnalyzer, fp);
callDetermineCPE_full("jaxb-xercesImpl-1.5.jar", null, instance, fnAnalyzer, jarAnalyzer, hAnalyzer, fp);
callDetermineCPE_full("ehcache-core-2.2.0.jar", null, instance, fnAnalyzer, jarAnalyzer, hAnalyzer, fp);
cpeAnalyzer.initialize();
FileNameAnalyzer fnAnalyzer = new FileNameAnalyzer();
fnAnalyzer.initialize();
JarAnalyzer jarAnalyzer = new JarAnalyzer();
jarAnalyzer.accept(new File("test.jar"));//trick analyzer into "thinking it is active"
jarAnalyzer.initialize();
HintAnalyzer hAnalyzer = new HintAnalyzer();
hAnalyzer.initialize();
FalsePositiveAnalyzer fp = new FalsePositiveAnalyzer();
fp.initialize();
callDetermineCPE_full("hazelcast-2.5.jar", null, cpeAnalyzer, fnAnalyzer, jarAnalyzer, hAnalyzer, fp);
callDetermineCPE_full("spring-context-support-2.5.5.jar", "cpe:/a:springsource:spring_framework:2.5.5", cpeAnalyzer, fnAnalyzer, jarAnalyzer, hAnalyzer, fp);
callDetermineCPE_full("spring-core-3.0.0.RELEASE.jar", "cpe:/a:vmware:springsource_spring_framework:3.0.0", cpeAnalyzer, fnAnalyzer, jarAnalyzer, hAnalyzer, fp);
callDetermineCPE_full("org.mortbay.jetty.jar", "cpe:/a:mortbay_jetty:jetty:4.2.27", cpeAnalyzer, fnAnalyzer, jarAnalyzer, hAnalyzer, fp);
callDetermineCPE_full("jaxb-xercesImpl-1.5.jar", null, cpeAnalyzer, fnAnalyzer, jarAnalyzer, hAnalyzer, fp);
callDetermineCPE_full("ehcache-core-2.2.0.jar", null, cpeAnalyzer, fnAnalyzer, jarAnalyzer, hAnalyzer, fp);
callDetermineCPE_full("xstream-1.4.8.jar", "cpe:/a:x-stream:xstream:1.4.8", cpeAnalyzer, fnAnalyzer, jarAnalyzer, hAnalyzer, fp);
} finally {
instance.close();
cpeAnalyzer.close();
}
}
@@ -107,7 +118,7 @@ public class CPEAnalyzerIntegrationTest extends BaseDBTestCase {
*
* @throws Exception is thrown when an exception occurs
*/
public void callDetermineCPE_full(String depName, String expResult, CPEAnalyzer instance, FileNameAnalyzer fnAnalyzer, JarAnalyzer jarAnalyzer, HintAnalyzer hAnalyzer, FalsePositiveAnalyzer fp) throws Exception {
public void callDetermineCPE_full(String depName, String expResult, CPEAnalyzer cpeAnalyzer, FileNameAnalyzer fnAnalyzer, JarAnalyzer jarAnalyzer, HintAnalyzer hAnalyzer, FalsePositiveAnalyzer fp) throws Exception {
//File file = new File(this.getClass().getClassLoader().getResource(depName).getPath());
File file = BaseTest.getResourceAsFile(this, depName);
@@ -117,7 +128,7 @@ public class CPEAnalyzerIntegrationTest extends BaseDBTestCase {
fnAnalyzer.analyze(dep, null);
jarAnalyzer.analyze(dep, null);
hAnalyzer.analyze(dep, null);
instance.analyze(dep, null);
cpeAnalyzer.analyze(dep, null);
fp.analyze(dep, null);
if (expResult != null) {
@@ -146,8 +157,10 @@ public class CPEAnalyzerIntegrationTest extends BaseDBTestCase {
fnAnalyzer.analyze(struts, null);
HintAnalyzer hintAnalyzer = new HintAnalyzer();
hintAnalyzer.initialize();
JarAnalyzer jarAnalyzer = new JarAnalyzer();
jarAnalyzer.accept(new File("test.jar"));//trick analyzer into "thinking it is active"
jarAnalyzer.initialize();
jarAnalyzer.analyze(struts, null);
hintAnalyzer.analyze(struts, null);

View File

@@ -23,16 +23,11 @@ import org.junit.Test;
import org.owasp.dependencycheck.BaseTest;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
import org.owasp.dependencycheck.dependency.Confidence;
import org.owasp.dependencycheck.dependency.Dependency;
import org.owasp.dependencycheck.dependency.Evidence;
import java.io.File;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import org.owasp.dependencycheck.BaseDBTestCase;
@@ -53,6 +48,7 @@ public class ComposerLockAnalyzerTest extends BaseDBTestCase {
*
* @throws Exception thrown if there is a problem
*/
@Override
@Before
public void setUp() throws Exception {
super.setUp();

View File

@@ -20,7 +20,7 @@ import java.util.Set;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import org.junit.Before;
import org.junit.Test;
import org.owasp.dependencycheck.BaseTest;
import org.owasp.dependencycheck.Engine;

View File

@@ -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;
@@ -63,6 +65,7 @@ public class RubyBundleAuditAnalyzerTest extends BaseDBTestCase {
*
* @throws Exception thrown if there is a problem
*/
@Override
@Before
public void setUp() throws Exception {
super.setUp();
@@ -146,7 +149,7 @@ public class RubyBundleAuditAnalyzerTest extends BaseDBTestCase {
assertEquals(vulnerability.getCvssScore(), 5.0f, 0.0);
} catch (Exception e) {
LOGGER.warn("Exception setting up RubyBundleAuditAnalyzer. Make sure Ruby gem bundle-audit is installed. You may also need to set property \"analyzer.bundle.audit.path\".", e);
LOGGER.warn("Exception setting up RubyBundleAuditAnalyzer. Make sure Ruby gem bundle-audit is installed. You may also need to set property \"analyzer.bundle.audit.path\".");
Assume.assumeNoException("Exception setting up RubyBundleAuditAnalyzer; bundle audit may not be installed, or property \"analyzer.bundle.audit.path\" may not be set.", e);
}
}
@@ -175,6 +178,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 +190,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.");

View File

@@ -17,11 +17,8 @@
*/
package org.owasp.dependencycheck.data.cwe;
import org.junit.After;
import org.junit.AfterClass;
import static org.junit.Assert.assertEquals;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.owasp.dependencycheck.BaseTest;

View File

@@ -36,12 +36,10 @@ import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopScoreDocCollector;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.RAMDirectory;
import org.junit.After;
import org.junit.AfterClass;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.owasp.dependencycheck.BaseTest;
@@ -63,7 +61,12 @@ public class FieldAnalyzerTest extends BaseTest {
String field2 = "vendor";
String text2 = "springsource";
createIndex(analyzer, index, field1, text1, field2, text2);
IndexWriter w = createIndex(analyzer, index);
addDoc(w, field1, text1, field2, text2);
text1 = "x-stream";
text2 = "xstream";
addDoc(w, field1, text1, field2, text2);
w.close();
//Analyzer searchingAnalyzer = new SearchFieldAnalyzer(LuceneUtils.CURRENT_VERSION);
String querystr = "product:\"(Spring Framework Core)\" vendor:(SpringSource)";
@@ -77,7 +80,6 @@ public class FieldAnalyzerTest extends BaseTest {
QueryParser parser = new QueryParser(LuceneUtils.CURRENT_VERSION, field1, wrapper);
Query q = parser.parse(querystr);
//System.out.println(q.toString());
int hitsPerPage = 10;
@@ -88,20 +90,27 @@ public class FieldAnalyzerTest extends BaseTest {
ScoreDoc[] hits = collector.topDocs().scoreDocs;
assertEquals("Did not find 1 document?", 1, hits.length);
assertEquals("springframework", searcher.doc(hits[0].doc).get(field1));
assertEquals("springsource", searcher.doc(hits[0].doc).get(field2));
searchAnalyzerProduct.clear(); //ensure we don't have anything left over from the previous search.
searchAnalyzerVendor.clear();
querystr = "product:(Apache Struts) vendor:(Apache)";
Query q2 = parser.parse(querystr);
//System.out.println(q2.toString());
assertFalse("second parsing contains previousWord from the TokenPairConcatenatingFilter", q2.toString().contains("core"));
querystr = "product:( x-stream^5 ) AND vendor:( thoughtworks.xstream )";
Query q3 = parser.parse(querystr);
collector = TopScoreDocCollector.create(hitsPerPage, true);
searcher.search(q3, collector);
hits = collector.topDocs().scoreDocs;
assertEquals("x-stream", searcher.doc(hits[0].doc).get(field1));
assertEquals("xstream", searcher.doc(hits[0].doc).get(field2));
}
private void createIndex(Analyzer analyzer, Directory index, String field1, String text1, String field2, String text2) throws IOException {
private IndexWriter createIndex(Analyzer analyzer, Directory index) throws IOException {
IndexWriterConfig config = new IndexWriterConfig(LuceneUtils.CURRENT_VERSION, analyzer);
IndexWriter w = new IndexWriter(index, config);
addDoc(w, field1, text1, field2, text2);
w.close();
return new IndexWriter(index, config);
}
private static void addDoc(IndexWriter w, String field1, String text1, String field2, String text2) throws IOException {

View File

@@ -17,11 +17,8 @@
*/
package org.owasp.dependencycheck.data.lucene;
import org.junit.After;
import org.junit.AfterClass;
import static org.junit.Assert.assertEquals;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.owasp.dependencycheck.BaseTest;

View File

@@ -20,17 +20,12 @@ package org.owasp.dependencycheck.data.lucene;
import java.io.IOException;
import java.io.StringReader;
import org.apache.lucene.analysis.BaseTokenStreamTestCase;
import static org.apache.lucene.analysis.BaseTokenStreamTestCase.assertTokenStreamContents;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.Tokenizer;
import org.apache.lucene.analysis.core.WhitespaceTokenizer;
import org.junit.After;
import org.junit.AfterClass;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
/**

View File

@@ -17,10 +17,7 @@ package org.owasp.dependencycheck.data.nvdcve;
import java.sql.Connection;
import java.sql.SQLException;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.*;
import org.owasp.dependencycheck.BaseDBTestCase;

View File

@@ -19,16 +19,13 @@ package org.owasp.dependencycheck.data.nvdcve;
import java.util.List;
import java.util.Set;
import org.junit.After;
import org.junit.AfterClass;
import static org.junit.Assert.assertTrue;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.owasp.dependencycheck.BaseTest;
import org.owasp.dependencycheck.dependency.Vulnerability;
import org.owasp.dependencycheck.dependency.VulnerableSoftware;
import org.owasp.dependencycheck.utils.Settings;
/**
*

View File

@@ -20,12 +20,10 @@ package org.owasp.dependencycheck.data.nvdcve;
import java.io.File;
import java.sql.Driver;
import java.sql.DriverManager;
import org.junit.After;
import org.junit.AfterClass;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.owasp.dependencycheck.BaseTest;

View File

@@ -20,13 +20,11 @@ package org.owasp.dependencycheck.data.update.nvd;
import java.io.File;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import org.junit.After;
import org.junit.AfterClass;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.owasp.dependencycheck.BaseTest;
import org.owasp.dependencycheck.data.nvdcve.CveDB;

View File

@@ -23,11 +23,9 @@ import java.util.List;
import java.util.Map;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.junit.After;
import org.junit.AfterClass;
import static org.junit.Assert.assertTrue;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.owasp.dependencycheck.BaseTest;
import org.owasp.dependencycheck.dependency.VulnerableSoftware;

View File

@@ -23,11 +23,9 @@ import java.util.List;
import java.util.Map;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.junit.After;
import org.junit.AfterClass;
import static org.junit.Assert.assertTrue;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.owasp.dependencycheck.BaseTest;
import org.owasp.dependencycheck.dependency.VulnerableSoftware;

View File

@@ -18,15 +18,12 @@
package org.owasp.dependencycheck.dependency;
import java.io.File;
import java.util.List;
import java.util.Set;
import org.junit.After;
import org.junit.AfterClass;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.owasp.dependencycheck.BaseTest;
import org.owasp.dependencycheck.data.nexus.MavenArtifact;

View File

@@ -18,13 +18,10 @@
package org.owasp.dependencycheck.dependency;
import java.util.Set;
import org.junit.After;
import org.junit.AfterClass;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertFalse;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.owasp.dependencycheck.BaseTest;

View File

@@ -17,13 +17,10 @@
*/
package org.owasp.dependencycheck.dependency;
import org.junit.After;
import org.junit.AfterClass;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertFalse;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.owasp.dependencycheck.BaseTest;

View File

@@ -24,7 +24,7 @@ import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;
import org.junit.Before;
import org.junit.Test;
import org.owasp.dependencycheck.BaseDBTestCase;
import org.owasp.dependencycheck.BaseTest;

View File

@@ -16,11 +16,9 @@
package org.owasp.dependencycheck.utils;
import java.util.Calendar;
import org.junit.After;
import org.junit.AfterClass;
import static org.junit.Assert.assertEquals;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.owasp.dependencycheck.BaseTest;

View File

@@ -17,12 +17,9 @@
*/
package org.owasp.dependencycheck.utils;
import org.junit.After;
import org.junit.AfterClass;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.owasp.dependencycheck.BaseTest;

View File

@@ -0,0 +1,77 @@
/*
* 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.xml.hints;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.util.List;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.junit.Test;
import static org.junit.Assert.*;
import org.owasp.dependencycheck.BaseTest;
import org.owasp.dependencycheck.xml.suppression.SuppressionErrorHandler;
import org.owasp.dependencycheck.xml.suppression.SuppressionHandler;
import org.owasp.dependencycheck.xml.suppression.SuppressionParser;
import org.owasp.dependencycheck.xml.suppression.SuppressionRule;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.SAXNotSupportedException;
import org.xml.sax.XMLReader;
/**
*
* @author Jeremy Long
*/
public class HintHandlerTest extends BaseTest {
@Test
public void testHandler() throws ParserConfigurationException, SAXNotRecognizedException, SAXNotSupportedException, SAXException, FileNotFoundException, UnsupportedEncodingException, IOException {
File file = BaseTest.getResourceAsFile(this, "hints.xml");
File schema = BaseTest.getResourceAsFile(this, "schema/dependency-hint.1.0.xsd");
HintHandler handler = new HintHandler();
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setNamespaceAware(true);
factory.setValidating(true);
SAXParser saxParser = factory.newSAXParser();
saxParser.setProperty(HintParser.JAXP_SCHEMA_LANGUAGE, HintParser.W3C_XML_SCHEMA);
saxParser.setProperty(HintParser.JAXP_SCHEMA_SOURCE, schema);
XMLReader xmlReader = saxParser.getXMLReader();
xmlReader.setErrorHandler(new HintErrorHandler());
xmlReader.setContentHandler(handler);
InputStream inputStream = new FileInputStream(file);
Reader reader = new InputStreamReader(inputStream, "UTF-8");
InputSource in = new InputSource(reader);
xmlReader.parse(in);
List<HintRule> result = handler.getHintRules();
assertEquals("two hint rules should have been loaded",2,result.size());
}
}

View File

@@ -0,0 +1,73 @@
/*
* 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.xml.hints;
import java.io.File;
import java.io.InputStream;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import org.owasp.dependencycheck.BaseTest;
/**
*
* @author Jeremy Long
*/
public class HintParserTest extends BaseTest {
/**
* Test of parseHints method, of class HintParser.
*/
@Test
public void testParseHints_File() throws Exception {
File file = BaseTest.getResourceAsFile(this, "hints.xml");
HintParser instance = new HintParser();
Hints results = instance.parseHints(file);
assertEquals("Two duplicating hints should have been read", 2, results.getVendorDuplicatingHintRules().size());
assertEquals("Two hint rules should have been read", 2, results.getHintRules().size());
}
/**
* Test of parseHints method, of class HintParser.
*/
@Test
public void testParseHints_InputStream() throws Exception {
InputStream ins = BaseTest.getResourceAsStream(this, "hints.xml");
HintParser instance = new HintParser();
Hints results = instance.parseHints(ins);
assertEquals("Two duplicating hints should have been read", 2, results.getVendorDuplicatingHintRules().size());
assertEquals("Two hint rules should have been read", 2, results.getHintRules().size());
assertEquals("One add product should have been read", 1, results.getHintRules().get(0).getAddProduct().size());
assertEquals("One add vendor should have been read", 1, results.getHintRules().get(0).getAddVendor().size());
assertEquals("Two file name should have been read", 2, results.getHintRules().get(1).getFilenames().size());
assertEquals("add product name not found", "add product name", results.getHintRules().get(0).getAddProduct().get(0).getName());
assertEquals("add vendor name not found", "add vendor name", results.getHintRules().get(0).getAddVendor().get(0).getName());
assertEquals("given product name not found", "given product name", results.getHintRules().get(0).getGivenProduct().get(0).getName());
assertEquals("given vendor name not found", "given vendor name", results.getHintRules().get(0).getGivenVendor().get(0).getName());
assertEquals("spring file name not found", "spring", results.getHintRules().get(1).getFilenames().get(0).getValue());
assertEquals("file name 1 should not be case sensitive", false, results.getHintRules().get(1).getFilenames().get(0).isCaseSensitive());
assertEquals("file name 1 should not be a regex", false, results.getHintRules().get(1).getFilenames().get(0).isRegex());
assertEquals("file name 2 should be case sensitive", true, results.getHintRules().get(1).getFilenames().get(1).isCaseSensitive());
assertEquals("file name 2 should be a regex", true, results.getHintRules().get(1).getFilenames().get(1).isRegex());
assertEquals("sun duplicating vendor", "sun", results.getVendorDuplicatingHintRules().get(0).getValue());
assertEquals("sun duplicates vendor oracle", "oracle", results.getVendorDuplicatingHintRules().get(0).getDuplicate());
}
}

Some files were not shown because too many files have changed in this diff Show More