Compare commits

..

32 Commits

Author SHA1 Message Date
Jeremy Long
21dd480616 version 1.0.3
Former-commit-id: a31596ca7d1ba553c7fb82f13451debb6de67dc2
2013-10-14 13:45:43 -04:00
Jeremy Long
b0e375ddc1 Merge branch 'master' of https://github.com/jeremylong/DependencyCheck
Former-commit-id: 3c6795992ff899b5adcd4335eeaf6d39a310db6c
2013-10-13 14:06:46 -04:00
Jeremy Long
6273ea758b added ftp:ftp as a false positive for Java projects
Former-commit-id: 3382b8413c0ba3af6370420e4e9279da66646c4d
2013-10-13 14:03:52 -04:00
Jeremy Long
e106ab5505 fixed bug 24 - short package names are no longer added as evvidence
Former-commit-id: 01bb31d35e58b624c31918f4a48fa2e5f584a8c5
2013-10-13 13:19:56 -04:00
Jeremy Long
c438283306 changed logging level to info
Former-commit-id: eb2a12f48d29e19732669a417ac1916bd7ad6db7
2013-10-13 13:18:42 -04:00
Jeremy Long
6e17064ef0 changed logging level to info
Former-commit-id: 2d38cb0766cda2874d98e54989b1a8af691e6ccc
2013-10-13 13:18:29 -04:00
Jeremy Long
575b35f685 changed saveEntry to a private method
Former-commit-id: dd65746b3a82cfb5f09a61495f767e1066e95e12
2013-10-10 18:20:59 -04:00
Jeremy Long
4929e36405 removed unused variables (pmd)
Former-commit-id: 9815590a2d3df08bb546ed24506db1682a80ff91
2013-10-09 09:22:18 -04:00
Jeremy Long
636e3ae6a7 checkstyle corrections
Former-commit-id: 48181a5325e8154dc2f5835badfd1d2d7ad2104f
2013-10-08 20:59:30 -04:00
Jeremy Long
5d5940a343 refactoring update tasks
Former-commit-id: d9b72f31b3df06106414bb3de925311f9acfc0d5
2013-10-08 15:19:22 -04:00
Jeremy Long
f4e2220684 checkstyle correction
Former-commit-id: 8c334dfc2f276e1e3c6f0c3b11e1a93b3d9b98e9
2013-10-08 15:18:32 -04:00
Jeremy Long
b490f15c10 checkstyle correction
Former-commit-id: 54539612c3fcdd4ea5952d8689c449d4adcb9386
2013-10-08 15:17:52 -04:00
Jeremy Long
3d0d9a9969 checkstyle correction
Former-commit-id: 1ef125990f732fb6918bfb44bed1a3bcb464b3d9
2013-10-08 15:17:03 -04:00
Jeremy Long
ae0e1c6b81 Improved update process, including initial lock support
Former-commit-id: 417f2186b6587f16dff8ee299618db1a08aa2756
2013-10-08 10:58:29 -04:00
Jeremy Long
c16229522a removed call to system.out
Former-commit-id: d770594c2689a5c2d424266860fe34d257fedd57
2013-10-08 10:48:35 -04:00
Jeremy Long
e88014ac5a added the creation of the DataStoreMetaInfo in the constructor
Former-commit-id: 498056ea82649be92d0451448837f4dd53ee8113
2013-10-05 07:42:08 -04:00
Jeremy Long
03425efa62 fixed bug with delete on exit deleting updated files
Former-commit-id: 16221347bc04d4dbd39be94553d990341ebf4a6a
2013-10-05 07:40:39 -04:00
Jeremy Long
d687daad90 added additional null checks
Former-commit-id: 25acb44a1e8015da7c144e136c3a6adeb3992fb6
2013-10-03 09:01:59 -04:00
Jeremy Long
c9ed7b7d2a implemented necassary test case
Former-commit-id: 10f24d2732a9b774d8c451bb224b0378d239e9fe
2013-09-27 18:30:22 -04:00
Steve Springett
7f52fe3b73 Fixed minor issue with xsd so the xml report would validate. Added unit test for xml report generation. Adding DependencyCheck.xsd to jar.
Former-commit-id: 88f8da11a79bb18f60bba3bd49e9836af50b228b
2013-09-23 17:51:22 -05:00
Jeremy Long
085cffa4cf seperated functionality to make the update procedure easier to understand
Former-commit-id: 15e86b665c007af38bf58b47097f94f7ec82bb5a
2013-09-22 21:52:31 -04:00
Jeremy Long
16afe3e23d added additional checks for false positives (apache maven and cvs:cvs)
Former-commit-id: 19e21385b498ec259d8cc758719fff59503673a5
2013-09-17 10:42:54 -04:00
Jeremy Long
80d50470b2 added additional test dependencies
Former-commit-id: 1d8e25354ac062f755a5ac8a04f15b52c523ee85
2013-09-17 10:42:23 -04:00
Jeremy Long
4775da5bf3 changed html encoding to xml encoding
Former-commit-id: c9f59935097cdac3cecb11b510549b2c1e494051
2013-09-14 10:20:40 -04:00
Jeremy Long
4df020b78e corrected a typo in the report
Former-commit-id: 8791277d4fba4bf26ac1a8bb7b5f61bbbf7d0142
2013-09-14 10:20:15 -04:00
Jeremy Long
c14308dccf updated integration test to generate all reports
Former-commit-id: 6828ba7aaeb77eeebfa84b3b39ae53f148b0d327
2013-09-14 10:19:38 -04:00
Jeremy Long
30233a9b0b changed https links to http for github pages
Former-commit-id: 0f991cf94faa5f8675b246431c76e9380de7edfc
2013-09-09 10:25:22 -04:00
Jeremy Long
37b95d5e94 updated links to bintray
Former-commit-id: 94443679abdc9ea98132c47e0ed91ca0872648be
2013-09-09 10:09:20 -04:00
Jeremy Long
e9abd8dc6e updated info
Former-commit-id: 8cd37bd5d0bcfef81616b7be896b147db1bb0607
2013-09-09 10:02:53 -04:00
Jeremy Long
fd4072023a updated info
Former-commit-id: d06e878e1f6e8d1cb510f0c0ac5ffdea6c13b48d
2013-09-09 10:01:00 -04:00
Jeremy Long
1261b33eaa updated logic to make specification-version lower quality evidence
Former-commit-id: 2577a982dcf955faa22f7829049d28ffb22ba9a8
2013-09-05 21:34:33 -04:00
Jeremy Long
2c8799dcca updated version to 1.0.3-SNAPSHOT
Former-commit-id: 1c7dd4a02d59327d2ebcbfa0f85e5b63cc8ae206
2013-09-03 21:47:53 -04:00
41 changed files with 2093 additions and 719 deletions

View File

@@ -5,8 +5,70 @@ Dependency-Check is a utility that attempts to detect publicly disclosed vulnera
Documentation and links to production binary releases can be found on the [github pages](http://jeremylong.github.io/DependencyCheck/). Additionally, more information about the architecture and ways to extend dependency-check can be found on the [wiki].
Initial Usage
Current Releases
-------------
### Jenkins Plugin
For instructions on the use of the Jenkins plugin please see the [Jenkins dependency-check page](http://wiki.jenkins-ci.org/x/CwDgAQ).
### Command Line
More detailed instructions can be found on the [dependency-check github pages](http://jeremylong.github.io/DependencyCheck/dependency-check-cli/installation.html).
The latest CLI can be downloaded from bintray's [dependency-check page](https://bintray.com/jeremy-long/owasp/dependency-check).
On *nix
```
$ ./bin/dependency-check.sh -h
$ ./bin/dependency-check.sh --app Testing --out . --scan [path to jar files to be scanned]
```
On Windows
```
> bin/dependency-check.bat -h
> bin/dependency-check.bat --app Testing --out . --scan [path to jar files to be scanned]
```
### Maven Plugin
More detailed instructions can be found on the [dependency-check-maven github pages](http://jeremylong.github.io/DependencyCheck/dependency-check-maven/installation.html).
The plugin can be configured using the following:
```xml
<project>
<build>
<plugins>
...
<plugin>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-maven</artifactId>
<version>1.0.2</version>
<executions>
<execution>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
...
</plugins>
...
</build>
...
</project>
```
### Ant Task
For instructions on the use of the Ant Task, please see the [dependency-check-ant github page](http://jeremylong.github.io/DependencyCheck/dependency-check-maven/installation.html).
Development Usage
-------------
The following instructions outline how to compile and use the current snapshot. While every intention is to maintain a stable snapshot it is recommended
that the release versions listed above be used.
Note, currently the install goal may take a long time to execute the integration tests. However, if this takes more then 30 minutes it is likely that the
download of data from the NVD is having an issue. This issue is still being researched and a solution should be published soon.
On *nix
```
$ mvn install
@@ -20,7 +82,7 @@ On Windows
> dependency-check-cli/target/release/bin/dependency-check.bat --app Testing --out . --scan ./src/test/resources
```
Then load the resulting 'DependencyCheck-Report.html' into your favorite browser.
Then load the resulting 'DependencyCheck-Report.html' into your favourite browser.
Mailing List
------------
@@ -29,6 +91,8 @@ Subscribe: [dependency-check+subscribe@googlegroups.com] [subscribe]
Post: [dependency-check@googlegroups.com] [post]
Archive: [google group](https://groups.google.com/forum/#!forum/dependency-check)
Copyright & License
-

View File

@@ -22,7 +22,7 @@ Copyright (c) 2013 - Jeremy Long. All Rights Reserved.
<parent>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-parent</artifactId>
<version>1.0.2</version>
<version>1.0.3</version>
</parent>
<artifactId>dependency-check-ant</artifactId>

View File

@@ -4,7 +4,7 @@ handlers=java.util.logging.ConsoleHandler, java.util.logging.FileHandler
# FINEST, FINER, FINE, CONFIG, INFO, WARNING and SEVERE.
# Configure the ConsoleHandler.
java.util.logging.ConsoleHandler.level=WARNING
java.util.logging.ConsoleHandler.level=INFO
#org.owasp.dependencycheck.data.nvdcve.xml

View File

@@ -1,6 +1,6 @@
Installation
====================
Download dependency-check-ant from [bintray here](http://dl.bintray.com/jeremy-long/owasp/dependency-check-ant-1.0.0.jar).
Download dependency-check-ant from [bintray here](http://dl.bintray.com/jeremy-long/owasp/dependency-check-ant-${project.version}.jar).
To install dependency-check-ant place the dependency-check-ant-${project.version}.jar into
the lib directory of your Ant instalation directory. Once installed you can add
the taskdef to you build.xml and add the task to a new or existing target.

View File

@@ -22,7 +22,7 @@ Copyright (c) 2012 - Jeremy Long. All Rights Reserved.
<parent>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-parent</artifactId>
<version>1.0.2</version>
<version>1.0.3</version>
</parent>
<artifactId>dependency-check-cli</artifactId>

View File

@@ -1,6 +1,6 @@
Installation & Usage
--------------------
Downlod the dependency-check command line tool [here](http://dl.bintray.com/jeremy-long/owasp/dependency-check-1.0.0-release.zip).
Downlod the dependency-check command line tool [here](http://dl.bintray.com/jeremy-long/owasp/dependency-check-${project.version}-release.zip).
Extract the zip file to a location on your computer and put the 'bin' directory into the
path environment variable. On \*nix systems you will likely need to make the shell
script executable:

View File

@@ -22,7 +22,7 @@ along with Dependency-Check. If not, see <http://www.gnu.org/licenses />.
<parent>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-parent</artifactId>
<version>1.0.2</version>
<version>1.0.3</version>
</parent>
<artifactId>dependency-check-core</artifactId>
@@ -44,6 +44,7 @@ along with Dependency-Check. If not, see <http://www.gnu.org/licenses />.
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/schema/*.xsd</include>
</includes>
<filtering>true</filtering>
</resource>
@@ -487,6 +488,13 @@ along with Dependency-Check. If not, see <http://www.gnu.org/licenses />.
<version>1.5</version>
</dependency>
<!-- The following dependencies are only used during testing -->
<dependency>
<groupId>org.apache.maven.scm</groupId>
<artifactId>maven-scm-provider-cvsexe</artifactId>
<version>1.8.1</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>

View File

@@ -460,7 +460,7 @@ public class CPEAnalyzer implements Analyzer {
}
}
if (tempWord != null && !list.isEmpty()) {
String tmp = list.get(list.size() - 1) + tempWord;
final String tmp = list.get(list.size() - 1) + tempWord;
list.add(tmp);
}
boolean contains = true;

View File

@@ -155,6 +155,8 @@ public class FalsePositiveAnalyzer extends AbstractAnalyzer {
final String nextVersion = nextCpe.getVersion();
if (currentVersion == null && nextVersion == null) {
//how did we get here?
Logger.getLogger(FalsePositiveAnalyzer.class
.getName()).log(Level.FINE, "currentVersion and nextVersion are both null?");
} else if (currentVersion == null && nextVersion != null) {
dependency.getIdentifiers().remove(currentId);
} else if (nextVersion == null && currentVersion != null) {
@@ -273,12 +275,16 @@ public class FalsePositiveAnalyzer extends AbstractAnalyzer {
if ((i.getValue().matches(".*c\\+\\+.*")
|| i.getValue().startsWith("cpe:/a:jquery:jquery")
|| i.getValue().startsWith("cpe:/a:prototypejs:prototype")
|| i.getValue().startsWith("cpe:/a:yahoo:yui"))
|| i.getValue().startsWith("cpe:/a:yahoo:yui")
|| i.getValue().startsWith("cpe:/a:file:file")
|| i.getValue().startsWith("cpe:/a:mozilla:mozilla")
|| i.getValue().startsWith("cpe:/a:cvs:cvs")
|| i.getValue().startsWith("cpe:/a:ftp:ftp")
|| i.getValue().startsWith("cpe:/a:ssh:ssh"))
&& dependency.getFileName().toLowerCase().endsWith(".jar")) {
itr.remove();
} else if (i.getValue().startsWith("cpe:/a:file:file")
|| i.getValue().startsWith("cpe:/a:mozilla:mozilla")
|| i.getValue().startsWith("cpe:/a:ssh:ssh")) {
} else if (i.getValue().startsWith("cpe:/a:apache:maven")
&& !dependency.getFileName().toLowerCase().matches("maven-core-[\\d\\.]+\\.jar")) {
itr.remove();
}
}

View File

@@ -515,7 +515,7 @@ public class JarAnalyzer extends AbstractAnalyzer implements Analyzer {
if (ratio > 0.5) {
//TODO remove weighting
vendor.addWeighting(entry.getKey());
if (addPackagesAsEvidence) {
if (addPackagesAsEvidence && entry.getKey().length() > 1) {
vendor.addEvidence("jar", "package", entry.getKey(), Evidence.Confidence.LOW);
}
}
@@ -524,7 +524,7 @@ public class JarAnalyzer extends AbstractAnalyzer implements Analyzer {
final float ratio = entry.getValue() / (float) classCount;
if (ratio > 0.5) {
product.addWeighting(entry.getKey());
if (addPackagesAsEvidence) {
if (addPackagesAsEvidence && entry.getKey().length() > 1) {
product.addEvidence("jar", "package", entry.getKey(), Evidence.Confidence.LOW);
}
}
@@ -580,38 +580,38 @@ public class JarAnalyzer extends AbstractAnalyzer implements Analyzer {
}
if (IGNORE_VALUES.contains(value)) {
continue;
} else if (key.equals(Attributes.Name.IMPLEMENTATION_TITLE.toString())) {
} else if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_TITLE.toString())) {
foundSomething = true;
productEvidence.addEvidence(source, key, value, Evidence.Confidence.HIGH);
addMatchingValues(classInformation, value, productEvidence);
} else if (key.equals(Attributes.Name.IMPLEMENTATION_VERSION.toString())) {
} else if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_VERSION.toString())) {
foundSomething = true;
versionEvidence.addEvidence(source, key, value, Evidence.Confidence.HIGH);
} else if (key.equals(Attributes.Name.IMPLEMENTATION_VENDOR.toString())) {
} else if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_VENDOR.toString())) {
foundSomething = true;
vendorEvidence.addEvidence(source, key, value, Evidence.Confidence.HIGH);
addMatchingValues(classInformation, value, vendorEvidence);
} else if (key.equals(Attributes.Name.IMPLEMENTATION_VENDOR_ID.toString())) {
} else if (key.equalsIgnoreCase(Attributes.Name.IMPLEMENTATION_VENDOR_ID.toString())) {
foundSomething = true;
vendorEvidence.addEvidence(source, key, value, Evidence.Confidence.MEDIUM);
addMatchingValues(classInformation, value, vendorEvidence);
} else if (key.equals(BUNDLE_DESCRIPTION)) {
} else if (key.equalsIgnoreCase(BUNDLE_DESCRIPTION)) {
foundSomething = true;
addDescription(dependency, value, "manifest", key);
//productEvidence.addEvidence(source, key, value, Evidence.Confidence.MEDIUM);
addMatchingValues(classInformation, value, productEvidence);
} else if (key.equals(BUNDLE_NAME)) {
} else if (key.equalsIgnoreCase(BUNDLE_NAME)) {
foundSomething = true;
productEvidence.addEvidence(source, key, value, Evidence.Confidence.MEDIUM);
addMatchingValues(classInformation, value, productEvidence);
} else if (key.equals(BUNDLE_VENDOR)) {
} else if (key.equalsIgnoreCase(BUNDLE_VENDOR)) {
foundSomething = true;
vendorEvidence.addEvidence(source, key, value, Evidence.Confidence.HIGH);
addMatchingValues(classInformation, value, vendorEvidence);
} else if (key.equals(BUNDLE_VERSION)) {
} else if (key.equalsIgnoreCase(BUNDLE_VERSION)) {
foundSomething = true;
versionEvidence.addEvidence(source, key, value, Evidence.Confidence.HIGH);
} else if (key.equals(Attributes.Name.MAIN_CLASS.toString())) {
} else if (key.equalsIgnoreCase(Attributes.Name.MAIN_CLASS.toString())) {
continue;
//skipping main class as if this has important information to add
// it will be added during class name analysis... if other fields
@@ -637,13 +637,22 @@ public class JarAnalyzer extends AbstractAnalyzer implements Analyzer {
foundSomething = true;
if (key.contains("version")) {
versionEvidence.addEvidence(source, key, value, Evidence.Confidence.MEDIUM);
if (key.contains("specification")) {
versionEvidence.addEvidence(source, key, value, Evidence.Confidence.LOW);
} else {
versionEvidence.addEvidence(source, key, value, Evidence.Confidence.MEDIUM);
}
} else if (key.contains("title")) {
productEvidence.addEvidence(source, key, value, Evidence.Confidence.MEDIUM);
addMatchingValues(classInformation, value, productEvidence);
} else if (key.contains("vendor")) {
vendorEvidence.addEvidence(source, key, value, Evidence.Confidence.MEDIUM);
addMatchingValues(classInformation, value, vendorEvidence);
if (key.contains("specification")) {
vendorEvidence.addEvidence(source, key, value, Evidence.Confidence.LOW);
} else {
vendorEvidence.addEvidence(source, key, value, Evidence.Confidence.MEDIUM);
addMatchingValues(classInformation, value, vendorEvidence);
}
} else if (key.contains("name")) {
productEvidence.addEvidence(source, key, value, Evidence.Confidence.MEDIUM);
vendorEvidence.addEvidence(source, key, value, Evidence.Confidence.MEDIUM);

View File

@@ -119,6 +119,24 @@ public class CpeIndexReader extends BaseIndex {
* Index
*/
public TopDocs search(String searchString, int maxQueryResults) throws ParseException, IOException {
if (searchString == null || searchString.trim().isEmpty()) {
throw new ParseException("Query is null or empty");
}
if (queryParser == null) {
if (isOpen()) {
final String msg = String.format("QueryParser is null for query: '%s'. Attempting to reopen index.",
searchString);
Logger.getLogger(CpeIndexReader.class.getName()).log(Level.WARNING, msg);
close();
open();
} else {
final String msg = String.format("QueryParser is null, but data source is open, for query: '%s'. Attempting to reopen index.",
searchString);
Logger.getLogger(CpeIndexReader.class.getName()).log(Level.WARNING, msg);
close();
open();
}
}
final Query query = queryParser.parse(searchString);
return indexSearcher.search(query, maxQueryResults);
}

View File

@@ -47,6 +47,24 @@ public final class TokenPairConcatenatingFilter extends TokenFilter {
*/
private final LinkedList<String> words;
/**
* Returns the previous word. This is needed in the test cases.
*
* @return te previous word
*/
protected String getPreviousWord() {
return previousWord;
}
/**
* Returns the words list. This is needed in the test cases.
*
* @return the words list
*/
protected LinkedList<String> getWords() {
return words;
}
/**
* Constructs a new TokenPairConcatenatingFilter.
*

View File

@@ -241,9 +241,7 @@ public class NvdCve20Handler extends DefaultHandler {
}
/**
* Saves a vulnerability to the CVE Database. This is a callback method
* called by the Sax Parser Handler
* {@link org.owasp.dependencycheck.data.nvdcve.xml.NvdCve20Handler}.
* Saves a vulnerability to the CVE Database.
*
* @param vuln the vulnerability to store in the database
* @throws DatabaseException thrown if there is an error writing to the
@@ -251,7 +249,7 @@ public class NvdCve20Handler extends DefaultHandler {
* @throws CorruptIndexException is thrown if the CPE Index is corrupt
* @throws IOException thrown if there is an IOException with the CPE Index
*/
public void saveEntry(Vulnerability vuln) throws DatabaseException, CorruptIndexException, IOException {
private void saveEntry(Vulnerability vuln) throws DatabaseException, CorruptIndexException, IOException {
if (cveDB == null) {
return;
}

View File

@@ -0,0 +1,288 @@
/*
* This file is part of dependency-check-core.
*
* Dependency-check-core is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Dependency-check-core is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* dependency-check-core. If not, see http://www.gnu.org/licenses/.
*
* Copyright (c) 2012 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.data.update;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.owasp.dependencycheck.data.UpdateException;
import org.owasp.dependencycheck.data.cpe.CpeIndexWriter;
import org.owasp.dependencycheck.data.nvdcve.CveDB;
import org.owasp.dependencycheck.utils.FileUtils;
import org.owasp.dependencycheck.utils.Settings;
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
import org.owasp.dependencycheck.data.nvdcve.NvdCve12Handler;
import org.owasp.dependencycheck.data.nvdcve.NvdCve20Handler;
import org.owasp.dependencycheck.dependency.VulnerableSoftware;
import org.owasp.dependencycheck.utils.DownloadFailedException;
import org.xml.sax.SAXException;
/**
* Class responsible for updating the CPE and NVDCVE data stores.
*
* @author Jeremy Long (jeremy.long@owasp.org)
*/
public abstract class AbstractUpdateTask implements UpdateTask {
/**
* Initializes the AbstractUpdateTask.
*
* @param properties information about the data store
* @throws MalformedURLException thrown if the configuration contains a
* malformed url
* @throws DownloadFailedException thrown if the timestamp on a file cannot
* be checked
* @throws UpdateException thrown if the update fails
*/
public AbstractUpdateTask(DataStoreMetaInfo properties) throws MalformedURLException, DownloadFailedException, UpdateException {
this.properties = properties;
this.updateable = updatesNeeded();
}
/**
* A collection of updateable NVD CVE items.
*/
private Updateable updateable;
/**
* Utility to read and write meta-data about the data.
*/
private DataStoreMetaInfo properties = null;
/**
* Returns the data store properties.
*
* @return the data store properties
*/
protected DataStoreMetaInfo getProperties() {
return properties;
}
/**
* Reference to the Cve Database.
*/
private CveDB cveDB = null;
/**
* Returns the CveDB.
*
* @return the CveDB
*/
protected CveDB getCveDB() {
return cveDB;
}
/**
* Reference to the Cpe Index.
*/
private CpeIndexWriter cpeIndex = null;
/**
* Returns the CpeIndex.
*
* @return the CpeIndex
*/
protected CpeIndexWriter getCpeIndex() {
return cpeIndex;
}
/**
* Gets whether or not an update is needed.
*
* @return true or false depending on whether an update is needed
*/
public boolean isUpdateNeeded() {
return updateable.isUpdateNeeded();
}
/**
* Gets the updateable NVD CVE Entries.
*
* @return an Updateable object containing the NVD CVE entries
*/
protected Updateable getUpdateable() {
return updateable;
}
/**
* Determines if the index needs to be updated.
*
* @return a collection of updateable resources.
* @throws MalformedURLException is thrown if the URL for the NVD CVE Meta
* data is incorrect.
* @throws DownloadFailedException is thrown if there is an error.
* downloading the NVD CVE download data file.
* @throws UpdateException Is thrown if there is an issue with the last
* updated properties file.
*/
protected abstract Updateable updatesNeeded() throws MalformedURLException, DownloadFailedException, UpdateException;
/**
* <p>Updates the data store to the latest version.</p>
*
* @throws UpdateException is thrown if there is an error updating the
* database
*/
public abstract void update() throws UpdateException;
/**
* A flag indicating whether or not the current data store should be
* deleted.
*/
private boolean deleteAndRecreate = false;
/**
* Get the value of deleteAndRecreate.
*
* @return the value of deleteAndRecreate
*/
public boolean shouldDeleteAndRecreate() {
return deleteAndRecreate;
}
/**
* Set the value of deleteAndRecreate.
*
* @param deleteAndRecreate new value of deleteAndRecreate
*/
protected void setDeleteAndRecreate(boolean deleteAndRecreate) {
this.deleteAndRecreate = deleteAndRecreate;
}
/**
* Deletes the existing data directories.
*
* @throws IOException thrown if the directory cannot be deleted
*/
protected void deleteExistingData() throws IOException {
File data = Settings.getFile(Settings.KEYS.CVE_DATA_DIRECTORY);
if (data.exists()) {
FileUtils.delete(data);
}
data = Settings.getFile(Settings.KEYS.CPE_DATA_DIRECTORY);
if (data.exists()) {
FileUtils.delete(data);
}
data = DataStoreMetaInfo.getPropertiesFile();
if (data.exists()) {
FileUtils.delete(data);
}
}
/**
* Closes the CVE and CPE data stores.
*/
protected void closeDataStores() {
if (cveDB != null) {
try {
cveDB.close();
} catch (Exception ignore) {
Logger.getLogger(AbstractUpdateTask.class.getName()).log(Level.FINEST, "Error closing the cveDB", ignore);
}
}
if (cpeIndex != null) {
try {
cpeIndex.close();
} catch (Exception ignore) {
Logger.getLogger(AbstractUpdateTask.class.getName()).log(Level.FINEST, "Error closing the cpeIndex", ignore);
}
}
}
/**
* Opens the CVE and CPE data stores.
*
* @throws UpdateException thrown if a data store cannot be opened
*/
protected void openDataStores() throws UpdateException {
//open the cve and cpe data stores
try {
cveDB = new CveDB();
cveDB.open();
cpeIndex = new CpeIndexWriter();
cpeIndex.open();
} catch (IOException ex) {
closeDataStores();
Logger.getLogger(AbstractUpdateTask.class.getName()).log(Level.FINE, "IO Error opening databases", ex);
throw new UpdateException("Error updating the CPE/CVE data, please see the log file for more details.");
} catch (SQLException ex) {
closeDataStores();
Logger.getLogger(AbstractUpdateTask.class.getName()).log(Level.FINE, "SQL Exception opening databases", ex);
throw new UpdateException("Error updating the CPE/CVE data, please see the log file for more details.");
} catch (DatabaseException ex) {
closeDataStores();
Logger.getLogger(AbstractUpdateTask.class.getName()).log(Level.FINE, "Database Exception opening databases", ex);
throw new UpdateException("Error updating the CPE/CVE data, please see the log file for more details.");
} catch (ClassNotFoundException ex) {
closeDataStores();
Logger.getLogger(AbstractUpdateTask.class.getName()).log(Level.FINE, "Class not found exception opening databases", ex);
throw new UpdateException("Error updating the CPE/CVE data, please see the log file for more details.");
}
}
/**
* Determines if the epoch date is within the range specified of the
* compareTo epoch time. This takes the (compareTo-date)/1000/60/60/24 to
* get the number of days. If the calculated days is less then the range the
* date is considered valid.
*
* @param date the date to be checked.
* @param compareTo the date to compare to.
* @param range the range in days to be considered valid.
* @return whether or not the date is within the range.
*/
protected boolean withinRange(long date, long compareTo, int range) {
final double differenceInDays = (compareTo - date) / 1000.0 / 60.0 / 60.0 / 24.0;
return differenceInDays < range;
}
/**
* Imports the NVD CVE XML File into the Lucene Index.
*
* @param file the file containing the NVD CVE XML
* @param oldVersion contains the file containing the NVD CVE XML 1.2
* @throws ParserConfigurationException is thrown if there is a parser
* configuration exception
* @throws SAXException is thrown if there is a SAXException
* @throws IOException is thrown if there is a IO Exception
* @throws SQLException is thrown if there is a SQL exception
* @throws DatabaseException is thrown if there is a database exception
* @throws ClassNotFoundException thrown if the h2 database driver cannot be
* loaded
*/
protected void importXML(File file, File oldVersion)
throws ParserConfigurationException, SAXException, IOException, SQLException, DatabaseException, ClassNotFoundException {
final SAXParserFactory factory = SAXParserFactory.newInstance();
final SAXParser saxParser = factory.newSAXParser();
final NvdCve12Handler cve12Handler = new NvdCve12Handler();
saxParser.parse(oldVersion, cve12Handler);
final Map<String, List<VulnerableSoftware>> prevVersionVulnMap = cve12Handler.getVulnerabilities();
final NvdCve20Handler cve20Handler = new NvdCve20Handler();
cve20Handler.setCveDB(cveDB);
cve20Handler.setPrevVersionVulnMap(prevVersionVulnMap);
cve20Handler.setCpeIndex(cpeIndex);
saxParser.parse(file, cve20Handler);
}
}

View File

@@ -0,0 +1,270 @@
/*
* This file is part of dependency-check-core.
*
* Dependency-check-core is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Dependency-check-core is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* dependency-check-core. If not, see http://www.gnu.org/licenses/.
*
* Copyright (c) 2012 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.data.update;
import org.owasp.dependencycheck.data.nvdcve.InvalidDataException;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Calendar;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.owasp.dependencycheck.data.UpdateException;
import org.owasp.dependencycheck.data.nvdcve.CveDB;
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.utils.InvalidSettingException;
import static org.owasp.dependencycheck.data.update.DataStoreMetaInfo.BATCH;
import static org.owasp.dependencycheck.data.update.DataStoreMetaInfo.MODIFIED;
/**
* Class responsible for updating the CPE and NVDCVE data stores.
*
* @author Jeremy Long (jeremy.long@owasp.org)
*/
public class BatchUpdateTask extends AbstractUpdateTask {
/**
* Constructs a new BatchUpdateTask.
*
* @param properties information about the data store
* @throws MalformedURLException thrown if a configured URL is malformed
* @throws DownloadFailedException thrown if a timestamp cannot be checked
* on a configured URL
* @throws UpdateException thrown if there is an exception generating the
* update task
*/
public BatchUpdateTask(DataStoreMetaInfo properties) throws MalformedURLException, DownloadFailedException, UpdateException {
super(properties);
}
/**
* A flag indicating whether or not the batch update should be performed.
*/
private boolean doBatchUpdate;
/**
* Get the value of doBatchUpdate
*
* @return the value of doBatchUpdate
*/
protected boolean isDoBatchUpdate() {
return doBatchUpdate;
}
/**
* Set the value of doBatchUpdate
*
* @param doBatchUpdate new value of doBatchUpdate
*/
protected void setDoBatchUpdate(boolean doBatchUpdate) {
this.doBatchUpdate = doBatchUpdate;
}
/**
* <p>Downloads the latest NVD CVE XML file from the web and imports it into
* the current CVE Database.</p>
*
* @throws UpdateException is thrown if there is an error updating the
* database
*/
@Override
public void update() throws UpdateException {
if (getProperties().isBatchUpdateMode() && doBatchUpdate) {
final String batchSrc = Settings.getString(Settings.KEYS.BATCH_UPDATE_URL);
File tmp = null;
try {
deleteExistingData();
final File dataDirectory = CveDB.getDataDirectory().getParentFile();
final URL batchUrl = new URL(batchSrc);
if ("file".equals(batchUrl.getProtocol())) {
try {
tmp = new File(batchUrl.toURI());
} catch (URISyntaxException ex) {
final String msg = String.format("Invalid batch update URI: %s", batchSrc);
throw new UpdateException(msg, ex);
}
} else if ("http".equals(batchUrl.getProtocol())
|| "https".equals(batchUrl.getProtocol())) {
tmp = File.createTempFile("batch_", ".zip");
Downloader.fetchFile(batchUrl, tmp);
}
//TODO add FTP?
FileUtils.extractFiles(tmp, dataDirectory);
} catch (IOException ex) {
final String msg = String.format("IO Exception Occured performing batch update using: %s", batchSrc);
throw new UpdateException(msg, ex);
} finally {
if (tmp != null && !tmp.delete()) {
tmp.deleteOnExit();
}
}
}
}
/**
* Determines if the index needs to be updated. This is done by fetching the
* NVD CVE meta data and checking the last update date. If the data needs to
* be refreshed this method will return the NvdCveUrl for the files that
* need to be updated.
*
* @return the collection of files that need to be updated
* @throws MalformedURLException is thrown if the URL for the NVD CVE Meta
* data is incorrect
* @throws DownloadFailedException is thrown if there is an error.
* downloading the NVD CVE download data file
* @throws UpdateException Is thrown if there is an issue with the last
* updated properties file
*/
@Override
public Updateable updatesNeeded() throws MalformedURLException, DownloadFailedException, UpdateException {
Updateable updates = null;
try {
updates = retrieveCurrentTimestampsFromWeb();
} catch (InvalidDataException ex) {
final String msg = "Unable to retrieve valid timestamp from nvd cve downloads page";
Logger.getLogger(BatchUpdateTask.class.getName()).log(Level.FINE, msg, ex);
throw new DownloadFailedException(msg, ex);
} catch (InvalidSettingException ex) {
Logger.getLogger(BatchUpdateTask.class.getName()).log(Level.FINE, "Invalid setting found when retrieving timestamps", ex);
throw new DownloadFailedException("Invalid settings", ex);
}
if (updates == null) {
throw new DownloadFailedException("Unable to retrieve the timestamps of the currently published NVD CVE data");
}
final DataStoreMetaInfo properties = getProperties();
if (!properties.isEmpty()) {
try {
boolean deleteAndRecreate = false;
float version;
if (properties.getProperty("version") == null) {
deleteAndRecreate = true;
} else {
try {
version = Float.parseFloat(properties.getProperty("version"));
final float currentVersion = Float.parseFloat(CveDB.DB_SCHEMA_VERSION);
if (currentVersion > version) {
deleteAndRecreate = true;
}
} catch (NumberFormatException ex) {
deleteAndRecreate = true;
}
}
final NvdCveInfo batchInfo = updates.get(BATCH);
if (properties.isBatchUpdateMode() && batchInfo != null) {
final long lastUpdated = Long.parseLong(properties.getProperty(DataStoreMetaInfo.BATCH, "0"));
if (lastUpdated != batchInfo.getTimestamp()) {
deleteAndRecreate = true;
}
}
if (deleteAndRecreate) {
setDoBatchUpdate(properties.isBatchUpdateMode());
try {
deleteExistingData();
} catch (IOException ex) {
final String msg = "Unable to delete existing data";
Logger.getLogger(BatchUpdateTask.class.getName()).log(Level.WARNING, msg);
Logger.getLogger(BatchUpdateTask.class.getName()).log(Level.FINE, null, ex);
}
return updates;
}
final long lastUpdated = Long.parseLong(properties.getProperty(DataStoreMetaInfo.LAST_UPDATED, "0"));
final Date now = new Date();
final int days = Settings.getInt(Settings.KEYS.CVE_MODIFIED_VALID_FOR_DAYS, 7);
final int start = Settings.getInt(Settings.KEYS.CVE_START_YEAR, 2002);
final int end = Calendar.getInstance().get(Calendar.YEAR);
if (lastUpdated == updates.get(MODIFIED).getTimestamp()) {
updates.clear(); //we don't need to update anything.
setDoBatchUpdate(properties.isBatchUpdateMode());
} else if (withinRange(lastUpdated, now.getTime(), days)) {
updates.get(MODIFIED).setNeedsUpdate(true);
if (properties.isBatchUpdateMode()) {
setDoBatchUpdate(false);
} else {
for (int i = start; i <= end; i++) {
updates.get(String.valueOf(i)).setNeedsUpdate(false);
}
}
} else if (properties.isBatchUpdateMode()) {
updates.get(MODIFIED).setNeedsUpdate(true);
setDoBatchUpdate(true);
} else { //we figure out which of the several XML files need to be downloaded.
updates.get(MODIFIED).setNeedsUpdate(false);
for (int i = start; i <= end; i++) {
final NvdCveInfo cve = updates.get(String.valueOf(i));
long currentTimestamp = 0;
try {
currentTimestamp = Long.parseLong(properties.getProperty(DataStoreMetaInfo.LAST_UPDATED_BASE + String.valueOf(i), "0"));
} catch (NumberFormatException ex) {
final String msg = String.format("Error parsing '%s' '%s' from nvdcve.lastupdated",
DataStoreMetaInfo.LAST_UPDATED_BASE, String.valueOf(i));
Logger.getLogger(BatchUpdateTask.class.getName()).log(Level.FINE, msg, ex);
}
if (currentTimestamp == cve.getTimestamp()) {
cve.setNeedsUpdate(false); //they default to true.
}
}
}
} catch (NumberFormatException ex) {
final String msg = "An invalid schema version or timestamp exists in the data.properties file.";
Logger.getLogger(BatchUpdateTask.class.getName()).log(Level.WARNING, msg);
Logger.getLogger(BatchUpdateTask.class.getName()).log(Level.FINE, null, ex);
setDoBatchUpdate(properties.isBatchUpdateMode());
}
}
return updates;
}
/**
* Retrieves the timestamps from the NVD CVE meta data file.
*
* @return the timestamp from the currently published nvdcve downloads page
* @throws MalformedURLException thrown if the URL for the NVD CCE Meta data
* is incorrect.
* @throws DownloadFailedException thrown if there is an error downloading
* the nvd cve meta data file
* @throws InvalidDataException thrown if there is an exception parsing the
* timestamps
* @throws InvalidSettingException thrown if the settings are invalid
*/
private Updateable retrieveCurrentTimestampsFromWeb()
throws MalformedURLException, DownloadFailedException, InvalidDataException, InvalidSettingException {
final Updateable updates = new Updateable();
updates.add(BATCH, Settings.getString(Settings.KEYS.BATCH_UPDATE_URL),
null, false);
final String url = Settings.getString(Settings.KEYS.CVE_MODIFIED_20_URL, "");
if (!url.isEmpty()) {
updates.add(MODIFIED, url,
Settings.getString(Settings.KEYS.CVE_MODIFIED_12_URL),
false);
}
return updates;
}
}

View File

@@ -18,40 +18,19 @@
*/
package org.owasp.dependencycheck.data.update;
import org.owasp.dependencycheck.data.nvdcve.NvdCve12Handler;
import org.owasp.dependencycheck.data.nvdcve.NvdCve20Handler;
import org.owasp.dependencycheck.data.nvdcve.InvalidDataException;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import javax.xml.parsers.ParserConfigurationException;
import org.xml.sax.SAXException;
import org.owasp.dependencycheck.data.CachedWebDataSource;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.sql.SQLException;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.owasp.dependencycheck.concurrency.DirectoryLockException;
import org.owasp.dependencycheck.concurrency.DirectorySpinLock;
import org.owasp.dependencycheck.concurrency.InvalidDirectoryException;
import org.owasp.dependencycheck.data.UpdateException;
import org.owasp.dependencycheck.data.cpe.CpeIndexWriter;
import org.owasp.dependencycheck.data.nvdcve.CveDB;
import org.owasp.dependencycheck.dependency.VulnerableSoftware;
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.data.nvdcve.DatabaseException;
import org.owasp.dependencycheck.utils.InvalidSettingException;
import static org.owasp.dependencycheck.data.update.DataStoreMetaInfo.BATCH;
import static org.owasp.dependencycheck.data.update.DataStoreMetaInfo.MODIFIED;
/**
* Class responsible for updating the CPE and NVDCVE data stores.
@@ -60,41 +39,6 @@ import static org.owasp.dependencycheck.data.update.DataStoreMetaInfo.MODIFIED;
*/
public class DatabaseUpdater implements CachedWebDataSource {
/**
* Utility to read and write meta-data about the data.
*/
private DataStoreMetaInfo properties = null;
/**
* Reference to the Cve Database.
*/
private CveDB cveDB = null;
/**
* Reference to the Cpe Index.
*/
private CpeIndexWriter cpeIndex = null;
/**
* A flag indicating whether or not the batch update should be performed.
*/
private boolean doBatchUpdate;
/**
* Get the value of doBatchUpdate
*
* @return the value of doBatchUpdate
*/
protected boolean isDoBatchUpdate() {
return doBatchUpdate;
}
/**
* Set the value of doBatchUpdate
*
* @param doBatchUpdate new value of doBatchUpdate
*/
protected void setDoBatchUpdate(boolean doBatchUpdate) {
this.doBatchUpdate = doBatchUpdate;
}
/**
* <p>Downloads the latest NVD CVE XML file from the web and imports it into
* the current CVE Database.</p>
@@ -104,149 +48,53 @@ public class DatabaseUpdater implements CachedWebDataSource {
*/
@Override
public void update() throws UpdateException {
doBatchUpdate = false;
properties = new DataStoreMetaInfo();
final File dataDir = Settings.getFile(Settings.KEYS.DATA_DIRECTORY);
DirectorySpinLock lock = null;
try {
final Map<String, NvdCveInfo> update = updateNeeded();
int maxUpdates = 0;
for (NvdCveInfo cve : update.values()) {
if (cve.getNeedsUpdate()) {
maxUpdates += 1;
}
}
if (maxUpdates > 3 && !properties.isBatchUpdateMode()) {
Logger.getLogger(DatabaseUpdater.class.getName()).log(Level.INFO,
"NVD CVE requires several updates; this could take a couple of minutes.");
}
if (maxUpdates > 0 && !isDoBatchUpdate()) {
openDataStores();
}
lock = new DirectorySpinLock(dataDir);
} catch (InvalidDirectoryException ex) {
throw new UpdateException("Unable to obtain lock on the data directory", ex);
} catch (DirectoryLockException ex) {
throw new UpdateException("Unable to obtain exclusive lock on the data directory", ex);
}
if (properties.isBatchUpdateMode() && isDoBatchUpdate()) {
try {
performBatchUpdate();
openDataStores();
} catch (IOException ex) {
throw new UpdateException("Unable to perform batch update", ex);
}
}
try {
lock.obtainSharedLock();
final UpdateTask task = UpdateTaskFactory.getUpdateTask();
int count = 0;
for (NvdCveInfo cve : update.values()) {
if (cve.getNeedsUpdate()) {
count += 1;
Logger.getLogger(DatabaseUpdater.class.getName()).log(Level.INFO,
"Updating NVD CVE ({0} of {1})", new Object[]{count, maxUpdates});
URL url = new URL(cve.getUrl());
File outputPath = null;
File outputPath12 = null;
if (task.isUpdateNeeded()) {
lock.release();
lock.obtainExclusiveLock();
if (task.shouldDeleteAndRecreate()) {
try {
Logger.getLogger(DatabaseUpdater.class.getName()).log(Level.INFO,
"Downloading {0}", cve.getUrl());
outputPath = File.createTempFile("cve" + cve.getId() + "_", ".xml");
Downloader.fetchFile(url, outputPath);
url = new URL(cve.getOldSchemaVersionUrl());
outputPath12 = File.createTempFile("cve_1_2_" + cve.getId() + "_", ".xml");
Downloader.fetchFile(url, outputPath12);
Logger.getLogger(DatabaseUpdater.class.getName()).log(Level.INFO,
"Processing {0}", cve.getUrl());
importXML(outputPath, outputPath12);
cveDB.commit();
cpeIndex.commit();
properties.save(cve);
Logger.getLogger(DatabaseUpdater.class.getName()).log(Level.INFO,
"Completed update {0} of {1}", new Object[]{count, maxUpdates});
} catch (FileNotFoundException ex) {
throw new UpdateException(ex);
} catch (ParserConfigurationException ex) {
throw new UpdateException(ex);
} catch (SAXException ex) {
throw new UpdateException(ex);
deleteExistingData();
} catch (IOException ex) {
throw new UpdateException(ex);
} catch (SQLException ex) {
throw new UpdateException(ex);
} catch (DatabaseException ex) {
throw new UpdateException(ex);
} catch (ClassNotFoundException ex) {
throw new UpdateException(ex);
} finally {
boolean deleted = false;
try {
if (outputPath != null && outputPath.exists()) {
deleted = outputPath.delete();
}
} finally {
if (outputPath != null && (outputPath.exists() || !deleted)) {
outputPath.deleteOnExit();
}
}
try {
deleted = false;
if (outputPath12 != null && outputPath12.exists()) {
deleted = outputPath12.delete();
}
} finally {
if (outputPath12 != null && (outputPath12.exists() || !deleted)) {
outputPath12.deleteOnExit();
}
}
Logger.getLogger(DatabaseUpdater.class.getName()).log(Level.WARNING, "Unable to delete the existing data directory");
Logger.getLogger(DatabaseUpdater.class.getName()).log(Level.FINE, null, ex);
}
}
task.update();
}
if (maxUpdates >= 1) { //ensure the modified file date gets written
properties.save(update.get(MODIFIED));
cveDB.cleanupDatabase();
}
if (update.get(BATCH) != null) {
properties.save(update.get(BATCH));
}
} catch (DirectoryLockException ex) {
Logger.getLogger(DatabaseUpdater.class.getName()).log(Level.WARNING,
"Unable to obtain lock on data directory, unable to update the data to use the most current data.");
Logger.getLogger(DatabaseUpdater.class.getName()).log(Level.FINE, null, ex);
} catch (MalformedURLException ex) {
throw new UpdateException(ex);
Logger.getLogger(DatabaseUpdater.class.getName()).log(Level.WARNING,
"NVD CVE properties files contain an invalid URL, unable to update the data to use the most current data.");
Logger.getLogger(DatabaseUpdater.class.getName()).log(Level.FINE, null, ex);
} catch (DownloadFailedException ex) {
throw new UpdateException(ex);
Logger.getLogger(DatabaseUpdater.class.getName()).log(Level.WARNING,
"Unable to download the NVD CVE data, unable to update the data to use the most current data.");
Logger.getLogger(DatabaseUpdater.class.getName()).log(Level.FINE, null, ex);
} finally {
closeDataStores();
if (lock != null) {
lock.release();
}
}
}
/**
* Imports the NVD CVE XML File into the Lucene Index.
*
* @param file the file containing the NVD CVE XML
* @param oldVersion contains the file containing the NVD CVE XML 1.2
* @throws ParserConfigurationException is thrown if there is a parser
* configuration exception
* @throws SAXException is thrown if there is a SAXException
* @throws IOException is thrown if there is a IO Exception
* @throws SQLException is thrown if there is a SQL exception
* @throws DatabaseException is thrown if there is a database exception
* @throws ClassNotFoundException thrown if the h2 database driver cannot be
* loaded
*/
private void importXML(File file, File oldVersion)
throws ParserConfigurationException, SAXException, IOException, SQLException, DatabaseException, ClassNotFoundException {
final SAXParserFactory factory = SAXParserFactory.newInstance();
final SAXParser saxParser = factory.newSAXParser();
final NvdCve12Handler cve12Handler = new NvdCve12Handler();
saxParser.parse(oldVersion, cve12Handler);
final Map<String, List<VulnerableSoftware>> prevVersionVulnMap = cve12Handler.getVulnerabilities();
final NvdCve20Handler cve20Handler = new NvdCve20Handler();
cve20Handler.setCveDB(cveDB);
cve20Handler.setPrevVersionVulnMap(prevVersionVulnMap);
cve20Handler.setCpeIndex(cpeIndex);
saxParser.parse(file, cve20Handler);
}
/**
* Deletes the existing data directories.
*
@@ -266,307 +114,4 @@ public class DatabaseUpdater implements CachedWebDataSource {
FileUtils.delete(data);
}
}
/**
* Performs the batch update based on the configured batch update URL.
*
* @throws UpdateException thrown if there is an exception during the update
* process
*/
private void performBatchUpdate() throws UpdateException {
if (properties.isBatchUpdateMode() && doBatchUpdate) {
final String batchSrc = Settings.getString(Settings.KEYS.BATCH_UPDATE_URL);
File tmp = null;
try {
deleteExistingData();
final File dataDirectory = CveDB.getDataDirectory().getParentFile();
final URL batchUrl = new URL(batchSrc);
if ("file".equals(batchUrl.getProtocol())) {
try {
tmp = new File(batchUrl.toURI());
} catch (URISyntaxException ex) {
final String msg = String.format("Invalid batch update URI: %s", batchSrc);
throw new UpdateException(msg, ex);
}
} else if ("http".equals(batchUrl.getProtocol())
|| "https".equals(batchUrl.getProtocol())) {
tmp = File.createTempFile("batch_", ".zip");
Downloader.fetchFile(batchUrl, tmp);
}
//TODO add FTP?
FileUtils.extractFiles(tmp, dataDirectory);
} catch (IOException ex) {
final String msg = String.format("IO Exception Occured performing batch update using: %s", batchSrc);
throw new UpdateException(msg, ex);
} finally {
if (tmp != null && !tmp.delete()) {
tmp.deleteOnExit();
}
}
}
}
/**
* Closes the CVE and CPE data stores.
*/
private void closeDataStores() {
if (cveDB != null) {
try {
cveDB.close();
} catch (Exception ignore) {
Logger.getLogger(DatabaseUpdater.class.getName()).log(Level.FINEST, "Error closing the cveDB", ignore);
}
}
if (cpeIndex != null) {
try {
cpeIndex.close();
} catch (Exception ignore) {
Logger.getLogger(DatabaseUpdater.class.getName()).log(Level.FINEST, "Error closing the cpeIndex", ignore);
}
}
}
/**
* Opens the CVE and CPE data stores.
*
* @throws UpdateException thrown if a data store cannot be opened
*/
private void openDataStores() throws UpdateException {
//open the cve and cpe data stores
try {
cveDB = new CveDB();
cveDB.open();
cpeIndex = new CpeIndexWriter();
cpeIndex.open();
} catch (IOException ex) {
closeDataStores();
Logger.getLogger(DatabaseUpdater.class.getName()).log(Level.FINE, "IO Error opening databases", ex);
throw new UpdateException("Error updating the CPE/CVE data, please see the log file for more details.");
} catch (SQLException ex) {
closeDataStores();
Logger.getLogger(DatabaseUpdater.class.getName()).log(Level.FINE, "SQL Exception opening databases", ex);
throw new UpdateException("Error updating the CPE/CVE data, please see the log file for more details.");
} catch (DatabaseException ex) {
closeDataStores();
Logger.getLogger(DatabaseUpdater.class.getName()).log(Level.FINE, "Database Exception opening databases", ex);
throw new UpdateException("Error updating the CPE/CVE data, please see the log file for more details.");
} catch (ClassNotFoundException ex) {
closeDataStores();
Logger.getLogger(DatabaseUpdater.class.getName()).log(Level.FINE, "Class not found exception opening databases", ex);
throw new UpdateException("Error updating the CPE/CVE data, please see the log file for more details.");
}
}
/**
* Determines if the index needs to be updated. This is done by fetching the
* NVD CVE meta data and checking the last update date. If the data needs to
* be refreshed this method will return the NvdCveUrl for the files that
* need to be updated.
*
* @return the NvdCveUrl of the files that need to be updated.
* @throws MalformedURLException is thrown if the URL for the NVD CVE Meta
* data is incorrect.
* @throws DownloadFailedException is thrown if there is an error.
* downloading the NVD CVE download data file.
* @throws UpdateException Is thrown if there is an issue with the last
* updated properties file.
*/
private Map<String, NvdCveInfo> updateNeeded() throws MalformedURLException, DownloadFailedException, UpdateException {
Map<String, NvdCveInfo> currentlyPublished;
try {
currentlyPublished = retrieveCurrentTimestampsFromWeb();
} catch (InvalidDataException ex) {
final String msg = "Unable to retrieve valid timestamp from nvd cve downloads page";
Logger.getLogger(DataStoreMetaInfo.class.getName()).log(Level.FINE, msg, ex);
throw new DownloadFailedException(msg, ex);
} catch (InvalidSettingException ex) {
Logger.getLogger(DataStoreMetaInfo.class.getName()).log(Level.FINE, "Invalid setting found when retrieving timestamps", ex);
throw new DownloadFailedException("Invalid settings", ex);
}
if (currentlyPublished == null) {
throw new DownloadFailedException("Unable to retrieve the timestamps of the currently published NVD CVE data");
}
// final File cpeDataDirectory;
// try {
// cpeDataDirectory = CveDB.getDataDirectory();
// } catch (IOException ex) {
// String msg;
// try {
// msg = String.format("Unable to create the CVE Data Directory '%s'",
// Settings.getFile(Settings.KEYS.CVE_DATA_DIRECTORY).getCanonicalPath());
// } catch (IOException ex1) {
// msg = String.format("Unable to create the CVE Data Directory, this is likely a configuration issue: '%s%s%s'",
// Settings.getString(Settings.KEYS.DATA_DIRECTORY, ""),
// File.separator,
// Settings.getString(Settings.KEYS.CVE_DATA_DIRECTORY, ""));
// }
// throw new UpdateException(msg, ex);
// }
if (!properties.isEmpty()) {
try {
boolean deleteAndRecreate = false;
float version;
if (properties.getProperty("version") == null) {
deleteAndRecreate = true;
} else {
try {
version = Float.parseFloat(properties.getProperty("version"));
final float currentVersion = Float.parseFloat(CveDB.DB_SCHEMA_VERSION);
if (currentVersion > version) {
deleteAndRecreate = true;
}
} catch (NumberFormatException ex) {
deleteAndRecreate = true;
}
}
final NvdCveInfo batchInfo = currentlyPublished.get(BATCH);
if (properties.isBatchUpdateMode() && batchInfo != null) {
final long lastUpdated = Long.parseLong(properties.getProperty(DataStoreMetaInfo.BATCH, "0"));
if (lastUpdated != batchInfo.getTimestamp()) {
deleteAndRecreate = true;
}
}
if (deleteAndRecreate) {
setDoBatchUpdate(properties.isBatchUpdateMode());
try {
deleteExistingData();
} catch (IOException ex) {
final String msg = "Unable to delete existing data";
Logger.getLogger(DatabaseUpdater.class.getName()).log(Level.WARNING, msg);
Logger.getLogger(DatabaseUpdater.class.getName()).log(Level.FINE, null, ex);
}
return currentlyPublished;
}
final long lastUpdated = Long.parseLong(properties.getProperty(DataStoreMetaInfo.LAST_UPDATED, "0"));
final Date now = new Date();
final int days = Settings.getInt(Settings.KEYS.CVE_MODIFIED_VALID_FOR_DAYS, 7);
final int start = Settings.getInt(Settings.KEYS.CVE_START_YEAR, 2002);
final int end = Calendar.getInstance().get(Calendar.YEAR);
if (lastUpdated == currentlyPublished.get(MODIFIED).getTimestamp()) {
currentlyPublished.clear(); //we don't need to update anything.
setDoBatchUpdate(properties.isBatchUpdateMode());
} else if (withinRange(lastUpdated, now.getTime(), days)) {
currentlyPublished.get(MODIFIED).setNeedsUpdate(true);
if (properties.isBatchUpdateMode()) {
setDoBatchUpdate(false);
} else {
for (int i = start; i <= end; i++) {
currentlyPublished.get(String.valueOf(i)).setNeedsUpdate(false);
}
}
} else if (properties.isBatchUpdateMode()) {
currentlyPublished.get(MODIFIED).setNeedsUpdate(true);
setDoBatchUpdate(true);
} else { //we figure out which of the several XML files need to be downloaded.
currentlyPublished.get(MODIFIED).setNeedsUpdate(false);
for (int i = start; i <= end; i++) {
final NvdCveInfo cve = currentlyPublished.get(String.valueOf(i));
long currentTimestamp = 0;
try {
currentTimestamp = Long.parseLong(properties.getProperty(DataStoreMetaInfo.LAST_UPDATED_BASE + String.valueOf(i), "0"));
} catch (NumberFormatException ex) {
final String msg = String.format("Error parsing '%s' '%s' from nvdcve.lastupdated",
DataStoreMetaInfo.LAST_UPDATED_BASE, String.valueOf(i));
Logger.getLogger(DataStoreMetaInfo.class.getName()).log(Level.FINE, msg, ex);
}
if (currentTimestamp == cve.getTimestamp()) {
cve.setNeedsUpdate(false); //they default to true.
}
}
}
} catch (NumberFormatException ex) {
final String msg = "An invalid schema version or timestamp exists in the data.properties file.";
Logger.getLogger(DataStoreMetaInfo.class.getName()).log(Level.WARNING, msg);
Logger.getLogger(DataStoreMetaInfo.class.getName()).log(Level.FINE, null, ex);
setDoBatchUpdate(properties.isBatchUpdateMode());
}
} else {
setDoBatchUpdate(properties.isBatchUpdateMode());
}
return currentlyPublished;
}
/**
* Determines if the epoch date is within the range specified of the
* compareTo epoch time. This takes the (compareTo-date)/1000/60/60/24 to
* get the number of days. If the calculated days is less then the range the
* date is considered valid.
*
* @param date the date to be checked.
* @param compareTo the date to compare to.
* @param range the range in days to be considered valid.
* @return whether or not the date is within the range.
*/
private boolean withinRange(long date, long compareTo, int range) {
final double differenceInDays = (compareTo - date) / 1000.0 / 60.0 / 60.0 / 24.0;
return differenceInDays < range;
}
/**
* Retrieves the timestamps from the NVD CVE meta data file.
*
* @return the timestamp from the currently published nvdcve downloads page
* @throws MalformedURLException thrown if the URL for the NVD CCE Meta data
* is incorrect.
* @throws DownloadFailedException thrown if there is an error downloading
* the nvd cve meta data file
* @throws InvalidDataException thrown if there is an exception parsing the
* timestamps
* @throws InvalidSettingException thrown if the settings are invalid
*/
private Map<String, NvdCveInfo> retrieveCurrentTimestampsFromWeb()
throws MalformedURLException, DownloadFailedException, InvalidDataException, InvalidSettingException {
final Map<String, NvdCveInfo> map = new TreeMap<String, NvdCveInfo>();
String retrieveUrl = Settings.getString(Settings.KEYS.CVE_MODIFIED_20_URL);
if (retrieveUrl == null && properties.isBatchUpdateMode()) {
final NvdCveInfo item = new NvdCveInfo();
retrieveUrl = Settings.getString(Settings.KEYS.BATCH_UPDATE_URL);
if (retrieveUrl == null) {
final String msg = "Invalid configuration - neither the modified or batch update URLs are specified in the configuration.";
Logger.getLogger(DataStoreMetaInfo.class.getName()).log(Level.SEVERE, msg);
throw new InvalidSettingException(msg);
}
item.setTimestamp(Downloader.getLastModified(new URL(retrieveUrl)));
item.setId(BATCH);
item.setNeedsUpdate(false);
map.put(BATCH, item);
} else {
NvdCveInfo item = new NvdCveInfo();
item.setNeedsUpdate(false); //the others default to true, to make life easier later this should default to false.
item.setId(MODIFIED);
item.setUrl(retrieveUrl);
item.setOldSchemaVersionUrl(Settings.getString(Settings.KEYS.CVE_MODIFIED_12_URL));
item.setTimestamp(Downloader.getLastModified(new URL(retrieveUrl)));
map.put(MODIFIED, item);
//only add these urls if we are not in batch mode
if (!properties.isBatchUpdateMode()) {
final int start = Settings.getInt(Settings.KEYS.CVE_START_YEAR);
final int end = Calendar.getInstance().get(Calendar.YEAR);
final String baseUrl20 = Settings.getString(Settings.KEYS.CVE_SCHEMA_2_0);
final String baseUrl12 = Settings.getString(Settings.KEYS.CVE_SCHEMA_1_2);
for (int i = start; i <= end; i++) {
retrieveUrl = String.format(baseUrl20, i);
item = new NvdCveInfo();
item.setId(Integer.toString(i));
item.setUrl(retrieveUrl);
item.setOldSchemaVersionUrl(String.format(baseUrl12, i));
item.setTimestamp(Downloader.getLastModified(new URL(retrieveUrl)));
map.put(item.getId(), item);
}
}
}
return map;
}
}

View File

@@ -0,0 +1,294 @@
/*
* This file is part of dependency-check-core.
*
* Dependency-check-core is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Dependency-check-core is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* dependency-check-core. If not, see http://www.gnu.org/licenses/.
*
* Copyright (c) 2012 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.data.update;
import org.owasp.dependencycheck.data.nvdcve.InvalidDataException;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import javax.xml.parsers.ParserConfigurationException;
import org.xml.sax.SAXException;
import java.net.MalformedURLException;
import java.net.URL;
import java.sql.SQLException;
import java.util.Calendar;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.owasp.dependencycheck.data.UpdateException;
import org.owasp.dependencycheck.data.nvdcve.CveDB;
import org.owasp.dependencycheck.utils.DownloadFailedException;
import org.owasp.dependencycheck.utils.Downloader;
import org.owasp.dependencycheck.utils.Settings;
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
import org.owasp.dependencycheck.utils.InvalidSettingException;
import static org.owasp.dependencycheck.data.update.DataStoreMetaInfo.MODIFIED;
/**
* Class responsible for updating the CPE and NVDCVE data stores.
*
* @author Jeremy Long (jeremy.long@owasp.org)
*/
public class StandardUpdateTask extends AbstractUpdateTask {
/**
* Constructs a new Standard Update Task.
*
* @param properties information about the data store
* @throws MalformedURLException thrown if a configured URL is malformed
* @throws DownloadFailedException thrown if a timestamp cannot be checked
* on a configured URL
* @throws UpdateException thrown if there is an exception generating the
* update task
*/
public StandardUpdateTask(DataStoreMetaInfo properties) throws MalformedURLException, DownloadFailedException, UpdateException {
super(properties);
}
/**
* <p>Downloads the latest NVD CVE XML file from the web and imports it into
* the current CVE Database.</p>
*
* @throws UpdateException is thrown if there is an error updating the
* database
*/
@Override
public void update() throws UpdateException {
try {
int maxUpdates = 0;
for (NvdCveInfo cve : getUpdateable()) {
if (cve.getNeedsUpdate()) {
maxUpdates += 1;
}
}
if (maxUpdates > 3) {
Logger.getLogger(StandardUpdateTask.class.getName()).log(Level.INFO,
"NVD CVE requires several updates; this could take a couple of minutes.");
}
if (maxUpdates > 0) {
openDataStores();
}
int count = 0;
for (NvdCveInfo cve : getUpdateable()) {
if (cve.getNeedsUpdate()) {
count += 1;
Logger.getLogger(StandardUpdateTask.class.getName()).log(Level.INFO,
"Updating NVD CVE ({0} of {1})", new Object[]{count, maxUpdates});
URL url = new URL(cve.getUrl());
File outputPath = null;
File outputPath12 = null;
try {
Logger.getLogger(StandardUpdateTask.class.getName()).log(Level.INFO,
"Downloading {0}", cve.getUrl());
outputPath = File.createTempFile("cve" + cve.getId() + "_", ".xml");
Downloader.fetchFile(url, outputPath);
url = new URL(cve.getOldSchemaVersionUrl());
outputPath12 = File.createTempFile("cve_1_2_" + cve.getId() + "_", ".xml");
Downloader.fetchFile(url, outputPath12);
Logger.getLogger(StandardUpdateTask.class.getName()).log(Level.INFO,
"Processing {0}", cve.getUrl());
importXML(outputPath, outputPath12);
getCveDB().commit();
getCpeIndex().commit();
getProperties().save(cve);
Logger.getLogger(StandardUpdateTask.class.getName()).log(Level.INFO,
"Completed update {0} of {1}", new Object[]{count, maxUpdates});
} catch (FileNotFoundException ex) {
throw new UpdateException(ex);
} catch (ParserConfigurationException ex) {
throw new UpdateException(ex);
} catch (SAXException ex) {
throw new UpdateException(ex);
} catch (IOException ex) {
throw new UpdateException(ex);
} catch (SQLException ex) {
throw new UpdateException(ex);
} catch (DatabaseException ex) {
throw new UpdateException(ex);
} catch (ClassNotFoundException ex) {
throw new UpdateException(ex);
} finally {
boolean deleted = false;
try {
if (outputPath != null && outputPath.exists()) {
deleted = outputPath.delete();
}
} finally {
if (outputPath != null && (outputPath.exists() || !deleted)) {
outputPath.deleteOnExit();
}
}
try {
deleted = false;
if (outputPath12 != null && outputPath12.exists()) {
deleted = outputPath12.delete();
}
} finally {
if (outputPath12 != null && (outputPath12.exists() || !deleted)) {
outputPath12.deleteOnExit();
}
}
}
}
}
if (maxUpdates >= 1) { //ensure the modified file date gets written
getProperties().save(getUpdateable().get(MODIFIED));
getCveDB().cleanupDatabase();
}
} catch (MalformedURLException ex) {
throw new UpdateException(ex);
} finally {
closeDataStores();
}
}
/**
* Determines if the index needs to be updated. This is done by fetching the
* NVD CVE meta data and checking the last update date. If the data needs to
* be refreshed this method will return the NvdCveUrl for the files that
* need to be updated.
*
* @return the collection of files that need to be updated
* @throws MalformedURLException is thrown if the URL for the NVD CVE Meta
* data is incorrect
* @throws DownloadFailedException is thrown if there is an error.
* downloading the NVD CVE download data file
* @throws UpdateException Is thrown if there is an issue with the last
* updated properties file
*/
@Override
protected Updateable updatesNeeded() throws MalformedURLException, DownloadFailedException, UpdateException {
Updateable updates = null;
try {
updates = retrieveCurrentTimestampsFromWeb();
} catch (InvalidDataException ex) {
final String msg = "Unable to retrieve valid timestamp from nvd cve downloads page";
Logger.getLogger(StandardUpdateTask.class.getName()).log(Level.FINE, msg, ex);
throw new DownloadFailedException(msg, ex);
} catch (InvalidSettingException ex) {
Logger.getLogger(StandardUpdateTask.class.getName()).log(Level.FINE, "Invalid setting found when retrieving timestamps", ex);
throw new DownloadFailedException("Invalid settings", ex);
}
if (updates == null) {
throw new DownloadFailedException("Unable to retrieve the timestamps of the currently published NVD CVE data");
}
final DataStoreMetaInfo properties = getProperties();
if (!properties.isEmpty()) {
try {
float version;
if (properties.getProperty("version") == null) {
setDeleteAndRecreate(true);
} else {
try {
version = Float.parseFloat(properties.getProperty("version"));
final float currentVersion = Float.parseFloat(CveDB.DB_SCHEMA_VERSION);
if (currentVersion > version) {
setDeleteAndRecreate(true);
}
} catch (NumberFormatException ex) {
setDeleteAndRecreate(true);
}
}
if (shouldDeleteAndRecreate()) {
return updates;
}
final long lastUpdated = Long.parseLong(properties.getProperty(DataStoreMetaInfo.LAST_UPDATED, "0"));
final Date now = new Date();
final int days = Settings.getInt(Settings.KEYS.CVE_MODIFIED_VALID_FOR_DAYS, 7);
if (lastUpdated == updates.getTimeStamp(MODIFIED)) {
updates.clear(); //we don't need to update anything.
} else if (withinRange(lastUpdated, now.getTime(), days)) {
for (NvdCveInfo entry : updates) {
if (MODIFIED.equals(entry.getId())) {
entry.setNeedsUpdate(true);
} else {
entry.setNeedsUpdate(false);
}
}
} else { //we figure out which of the several XML files need to be downloaded.
for (NvdCveInfo entry : updates) {
if (MODIFIED.equals(entry.getId())) {
entry.setNeedsUpdate(true);
} else {
long currentTimestamp = 0;
try {
currentTimestamp = Long.parseLong(properties.getProperty(DataStoreMetaInfo.LAST_UPDATED_BASE + entry.getId(), "0"));
} catch (NumberFormatException ex) {
final String msg = String.format("Error parsing '%s' '%s' from nvdcve.lastupdated",
DataStoreMetaInfo.LAST_UPDATED_BASE, entry.getId());
Logger.getLogger(StandardUpdateTask.class.getName()).log(Level.FINE, msg, ex);
}
if (currentTimestamp == entry.getTimestamp()) {
entry.setNeedsUpdate(false);
}
}
}
}
} catch (NumberFormatException ex) {
final String msg = "An invalid schema version or timestamp exists in the data.properties file.";
Logger.getLogger(StandardUpdateTask.class.getName()).log(Level.WARNING, msg);
Logger.getLogger(StandardUpdateTask.class.getName()).log(Level.FINE, null, ex);
}
}
return updates;
}
/**
* Retrieves the timestamps from the NVD CVE meta data file.
*
* @return the timestamp from the currently published nvdcve downloads page
* @throws MalformedURLException thrown if the URL for the NVD CCE Meta data
* is incorrect.
* @throws DownloadFailedException thrown if there is an error downloading
* the nvd cve meta data file
* @throws InvalidDataException thrown if there is an exception parsing the
* timestamps
* @throws InvalidSettingException thrown if the settings are invalid
*/
private Updateable retrieveCurrentTimestampsFromWeb()
throws MalformedURLException, DownloadFailedException, InvalidDataException, InvalidSettingException {
final Updateable updates = new Updateable();
updates.add(MODIFIED, Settings.getString(Settings.KEYS.CVE_MODIFIED_20_URL),
Settings.getString(Settings.KEYS.CVE_MODIFIED_12_URL),
false);
final int start = Settings.getInt(Settings.KEYS.CVE_START_YEAR);
final int end = Calendar.getInstance().get(Calendar.YEAR);
final String baseUrl20 = Settings.getString(Settings.KEYS.CVE_SCHEMA_2_0);
final String baseUrl12 = Settings.getString(Settings.KEYS.CVE_SCHEMA_1_2);
for (int i = start; i <= end; i++) {
updates.add(Integer.toString(i), String.format(baseUrl20, i),
String.format(baseUrl12, i),
true);
}
return updates;
}
}

View File

@@ -0,0 +1,51 @@
/*
* This file is part of dependency-check-core.
*
* Dependency-check-core is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Dependency-check-core is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* dependency-check-core. If not, see http://www.gnu.org/licenses/.
*
* Copyright (c) 2012 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.data.update;
import org.owasp.dependencycheck.data.UpdateException;
/**
* An interface defining an update task.
*
* @author Jeremy Long (jeremy.long@owasp.org)
*/
public interface UpdateTask {
/**
* <p>Updates the data store to the latest version.</p>
*
* @throws UpdateException is thrown if there is an error updating the
* database
*/
void update() throws UpdateException;
/**
* Get the value of deleteAndRecreate.
*
* @return the value of deleteAndRecreate
*/
boolean shouldDeleteAndRecreate();
/**
* Gets whether or not an update is needed.
*
* @return true or false depending on whether an update is needed
*/
boolean isUpdateNeeded();
}

View File

@@ -0,0 +1,60 @@
/*
* This file is part of dependency-check-core.
*
* Dependency-check-core is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Dependency-check-core is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* dependency-check-core. If not, see http://www.gnu.org/licenses/.
*
* Copyright (c) 2012 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.data.update;
import java.net.MalformedURLException;
import org.owasp.dependencycheck.data.UpdateException;
import org.owasp.dependencycheck.utils.DownloadFailedException;
/**
* An UpdateTask Factory that instantiates the correct UpdateTask based on the
* given configuration.
*
* @author Jeremy Long (jeremy.long@owasp.org)
*/
public final class UpdateTaskFactory {
/**
* private constructor for a utility class.
*/
private UpdateTaskFactory() {
//empty contrusctor for utility class
}
/**
* Constructs the appropriate update task based on configuration.
*
* @return an UpdateTask
* @throws MalformedURLException thrown if a configured URL is malformed
* @throws DownloadFailedException thrown if a timestamp cannot be checked
* on a configured URL
* @throws UpdateException thrown if there is an exception generating the
* update task
*/
public static UpdateTask getUpdateTask() throws MalformedURLException, DownloadFailedException, UpdateException {
final UpdateTask task;
final DataStoreMetaInfo properties = new DataStoreMetaInfo();
if (properties.isBatchUpdateMode()) {
task = new BatchUpdateTask(properties);
} else {
task = new StandardUpdateTask(properties);
}
return task;
}
}

View File

@@ -0,0 +1,181 @@
/*
* This file is part of dependency-check-core.
*
* Dependency-check-core is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Dependency-check-core is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* dependency-check-core. If not, see http://www.gnu.org/licenses/.
*
* Copyright (c) 2012 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.data.update;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;
import org.owasp.dependencycheck.utils.DownloadFailedException;
import org.owasp.dependencycheck.utils.Downloader;
/**
* Contains a collection of updateable NvdCveInfo objects. This is used to
* determine which files need to be downloaded and processed.
*
* @author Jeremy Long (jeremy.long@owasp.org)
*/
public class Updateable implements java.lang.Iterable<NvdCveInfo>, Iterator<NvdCveInfo> {
/**
* A collection of sources of data.
*/
private Map<String, NvdCveInfo> collection = new TreeMap<String, NvdCveInfo>();
/**
* Returns the collection of NvdCveInfo objects. This method is mainly used
* for testing.
*
* @return the collection of NvdCveInfo objects
*/
protected Map<String, NvdCveInfo> getCollection() {
return collection;
}
/**
* Gets whether or not an update is needed.
*
* @return true or false depending on whether an update is needed
*/
public boolean isUpdateNeeded() {
for (NvdCveInfo item : this) {
if (item.getNeedsUpdate()) {
return true;
}
}
return false;
}
/**
* Adds a new entry of updateable information to the contained collection.
*
* @param id the key for the item to be added
* @param url the URL to download the item
* @param oldUrl the URL for the old version of the item (the NVD CVE old
* schema still contains useful data we need).
* @throws MalformedURLException thrown if the URL provided is invalid
* @throws DownloadFailedException thrown if the download fails.
*/
public void add(String id, String url, String oldUrl) throws MalformedURLException, DownloadFailedException {
add(id, url, oldUrl, false);
}
/**
* Adds a new entry of updateable information to the contained collection.
*
* @param id the key for the item to be added
* @param url the URL to download the item
* @param oldUrl the URL for the old version of the item (the NVD CVE old
* schema still contains useful data we need).
* @param needsUpdate whether or not the data needs to be updated
* @throws MalformedURLException thrown if the URL provided is invalid
* @throws DownloadFailedException thrown if the download fails.
*/
public void add(String id, String url, String oldUrl, boolean needsUpdate) throws MalformedURLException, DownloadFailedException {
final NvdCveInfo item = new NvdCveInfo();
item.setNeedsUpdate(needsUpdate); //the others default to true, to make life easier later this should default to false.
item.setId(id);
item.setUrl(url);
item.setOldSchemaVersionUrl(oldUrl);
item.setTimestamp(Downloader.getLastModified(new URL(url)));
collection.put(id, item);
}
/**
* Clears the contained collection of NvdCveInfo entries.
*/
public void clear() {
collection.clear();
}
/**
* Returns the timestamp for the given entry.
*
* @param key the key to lookup in the collection of NvdCveInfo items
* @return the timestamp for the given entry
*/
public long getTimeStamp(String key) {
return collection.get(key).getTimestamp();
}
/**
* An internal iterator used to implement iterable.
*/
private Iterator<Entry<String, NvdCveInfo>> iterableContent = null;
/**
* <p>Returns an iterator for the NvdCveInfo contained.</p>
* <p><b>This method is not thread safe.</b></p>
*
* @return an NvdCveInfo Iterator
*/
@Override
public Iterator<NvdCveInfo> iterator() {
iterableContent = collection.entrySet().iterator();
return this;
}
/**
* <p>Returns whether or not there is another item in the collection.</p>
* <p><b>This method is not thread safe.</b></p>
*
* @return true or false depending on whether or not another item exists in
* the collection
*/
@Override
public boolean hasNext() {
return iterableContent.hasNext();
}
/**
* <p>Returns the next item in the collection.</p>
* <p><b>This method is not thread safe.</b></p>
*
* @return the next NvdCveInfo item in the collection
*/
@Override
public NvdCveInfo next() {
return iterableContent.next().getValue();
}
/**
* <p>Removes the current NvdCveInfo object from the collection.</p>
* <p><b>This method is not thread safe.</b></p>
*/
@Override
public void remove() {
iterableContent.remove();
}
/**
* Returns the specified item from the collection.
*
* @param key the key to lookup the return value
* @return the NvdCveInfo object stored using the specified key
*/
NvdCveInfo get(String key) {
return collection.get(key);
}
@Override
public String toString() {
return "Updateable{" + "size=" + collection.size() + '}';
}
}

View File

@@ -80,37 +80,14 @@ public final class FileUtils {
}
}
if (!org.apache.commons.io.FileUtils.deleteQuietly(file)) {
//if (!file.delete()) {
throw new FileNotFoundException("Failed to delete file: " + file);
} else {
file.deleteOnExit();
}
}
/**
* Deletes a file. If the File is a directory it will recursively delete the
* contents.
*
* @param file the File to delete
* @param deleteOnExit setting this to true will cause errors to be ignored
* and if there is an error deleting the file it will be setup to be deleted
* when the JVM exits.
* @throws IOException is thrown if the file could not be deleted
*/
public static void delete(File file, boolean deleteOnExit) throws IOException {
if (file.isDirectory()) {
for (File c : file.listFiles()) {
delete(c);
}
}
if (!org.apache.commons.io.FileUtils.deleteQuietly(file)) {
//if (!file.delete()) {
if (deleteOnExit) {
file.deleteOnExit();
} else {
throw new FileNotFoundException("Failed to delete file: " + file);
}
}
/* else {
//delete on exit was a bad idea. if for some reason the file can't be deleted
// this will cause a newly constructed file to be deleted and a subsequent run may fail.
// still not sure why a file fails to be deleted, but can be overwritten... odd.
file.deleteOnExit();
}*/
}
/**

View File

@@ -70,7 +70,8 @@ public final class UrlStringUtils {
* A listing of domain parts that shold not be used as evidence. Yes, this
* is an incomplete list.
*/
private static final HashSet<String> IGNORE_LIST = new HashSet<String>(Arrays.asList("www", "com", "org", "gov", "info", "name", "net", "pro", "tel", "mobi", "xxx"));
private static final HashSet<String> IGNORE_LIST = new HashSet<String>(
Arrays.asList("www", "com", "org", "gov", "info", "name", "net", "pro", "tel", "mobi", "xxx"));
/**
* <p>Takes a URL, in String format, and adds the important parts of the URL

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="analysis" xmlns="https://www.owasp.org/index.php/OWASP_Dependency_Check" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:schema id="analysis" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="https://www.owasp.org/index.php/OWASP_Dependency_Check">
<xs:element name="analysis">
<xs:complexType>
<xs:sequence minOccurs="0" maxOccurs="unbounded">

View File

@@ -459,7 +459,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
</ul>
#end
</p>
<p>Vulnerably Software:<ul>
<p>Vulnerable Software &amp; Versions:<ul>
#foreach($vs in $vuln.getVulnerableSoftware())
<li><a target="_blank" href="http://web.nvd.nist.gov/view/vuln/search-results?cpe=$esc.url($vs.name)">$esc.html($vs.name)</a> #if($vs.hasPreviousVersion()) and all previous versions.#end</li>
#end

View File

@@ -21,30 +21,30 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
*#<?xml version="1.0"?>
<analysis xmlns="https://www.owasp.org/index.php/OWASP_Dependency_Check">
<projectInfo>
<name>$esc.html($applicationName)</name>
<name>$esc.xml($applicationName)</name>
<reportDate>$date</reportDate>
<credits>This report contains data retrieved from the National Vulnerability Database: http://nvd.nist.gov</credits>
</projectInfo>
<dependencies>
#foreach($dependency in $dependencies)
<dependency>
<fileName>$esc.html($dependency.FileName)</fileName>
<filePath>$esc.html($dependency.FilePath)</filePath>
<md5>$esc.html($dependency.Md5sum)</md5>
<sha1>$esc.html($dependency.Sha1sum)</sha1>
<fileName>$esc.xml($dependency.FileName)</fileName>
<filePath>$esc.xml($dependency.FilePath)</filePath>
<md5>$esc.xml($dependency.Md5sum)</md5>
<sha1>$esc.xml($dependency.Sha1sum)</sha1>
#if ($dependency.description)
<description>$esc.html($dependency.description)</description>
<description>$esc.xml($dependency.description)</description>
#end
#if ($dependency.license)
<license>$esc.html($dependency.license)</license>
<license>$esc.xml($dependency.license)</license>
#end
#if ($dependency.getRelatedDependencies().size()>0)
<relatedDependencies>
#foreach($related in $dependency.getRelatedDependencies())
<relatedDependency>
<filePath>$esc.html($related.FilePath)</filePath>
<sha1>$esc.html($related.Sha1sum)</sha1>
<md5>$esc.html($related.Md5sum)</md5>
<filePath>$esc.xml($related.FilePath)</filePath>
<sha1>$esc.xml($related.Sha1sum)</sha1>
<md5>$esc.xml($related.Md5sum)</md5>
</relatedDependency>
#end
</relatedDependencies>
@@ -53,21 +53,21 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
<analysisExceptions>
#foreach($ex in $dependency.analysisExceptions)
<exception>
<message>$esc.html($ex.message)</message>
<message>$esc.xml($ex.message)</message>
#if ( $ex.stackTrace )
<stackTrace>
#foreach ($st in $ex.stackTrace)
<trace>$esc.html($st)</trace>
<trace>$esc.xml($st)</trace>
#end
</stackTrace>
#end
#if ( $ex.cause )
<innerException>
<message>$esc.html($ex.cause.message)</message>
<message>$esc.xml($ex.cause.message)</message>
#if ( $ex.cause.stackTrace )
<stackTrace>
#foreach ($st in $ex.cause.stackTrace)
<trace>$esc.html($st)</trace>
<trace>$esc.xml($st)</trace>
#end
</stackTrace>
#end
@@ -80,22 +80,22 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
<evidenceCollected>
#foreach($evidence in $dependency.getEvidenceUsed())
<evidence>
<source>$esc.html($evidence.getSource())</source>
<name>$esc.html($evidence.getName())</name>
<value>$esc.html($evidence.getValue().trim())</value>
<source>$esc.xml($evidence.getSource())</source>
<name>$esc.xml($evidence.getName())</name>
<value>$esc.xml($evidence.getValue().trim())</value>
</evidence>
#end
</evidenceCollected>
#if($dependency.getIdentifiers().size()>0)
<identifiers>
#foreach($id in $dependency.getIdentifiers())
<identifier type="$esc.html($id.type)">
<name>$esc.html($id.value)</name>
<identifier type="$esc.xml($id.type)">
<name>($id.value)</name>
#if( $id.url )
<url>$esc.html($id.url)</url>
<url>$esc.xml($id.url)</url>
#end
#if( $id.description )
<description>$esc.html($id.description)</description>
<description>$esc.xml($id.description)</description>
#end
</identifier>
#end
@@ -105,7 +105,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
<vulnerabilities>
#foreach($vuln in $dependency.getVulnerabilities())
<vulnerability>
<name>$esc.html($vuln.name)</name>
<name>$esc.xml($vuln.name)</name>
<cvssScore>$vuln.cvssScore</cvssScore>
#if ($vuln.cvssScore<4.0)
<severity>Low</severity>
@@ -115,21 +115,21 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
<severity>Medium</severity>
#end
#if ($vuln.cwe)
<cwe>$esc.html($vuln.cwe)</cwe>
<cwe>$esc.xml($vuln.cwe)</cwe>
#end
<description>$esc.html($vuln.description)</description>
<description>$esc.xml($vuln.description)</description>
<references>
#foreach($ref in $vuln.getReferences())
<reference>
<source>$esc.html($ref.source)</source>
<url>$esc.html($ref.url)</url>
<name>$esc.html($ref.name)</name>
<source>$esc.xml($ref.source)</source>
<url>$esc.xml($ref.url)</url>
<name>$esc.xml($ref.name)</name>
</reference>
#end
</references>
<vulnerableSoftware>
#foreach($vs in $vuln.getVulnerableSoftware())
<software#if($vs.hasPreviousVersion()) allPreviousVersion="true"#end>$esc.html($vs.name)</software>
<software#if($vs.hasPreviousVersion()) allPreviousVersion="true"#end>$esc.xml($vs.name)</software>
#end
</vulnerableSoftware>
</vulnerability>

View File

@@ -64,6 +64,6 @@ public class EngineIntegrationTest {
instance.analyzeDependencies();
ReportGenerator rg = new ReportGenerator("DependencyCheck",
instance.getDependencies(), instance.getAnalyzers());
rg.generateReports("./target/", "HTML");
rg.generateReports("./target/", "ALL");
}
}

View File

@@ -6,12 +6,18 @@ package org.owasp.dependencycheck.data.lucene;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.BaseTokenStreamTestCase;
import static org.apache.lucene.analysis.BaseTokenStreamTestCase.assertAnalyzesTo;
import static org.apache.lucene.analysis.BaseTokenStreamTestCase.assertTokenStreamContents;
import static org.apache.lucene.analysis.BaseTokenStreamTestCase.checkOneTerm;
import org.apache.lucene.analysis.MockTokenizer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.Tokenizer;
import org.apache.lucene.analysis.core.WhitespaceTokenizer;
import org.apache.lucene.analysis.tokenattributes.TypeAttributeImpl;
import org.apache.lucene.util.Version;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
@@ -25,19 +31,6 @@ import static org.junit.Assert.*;
*/
public class TokenPairConcatenatingFilterTest extends BaseTokenStreamTestCase {
private Analyzer analyzer;
public TokenPairConcatenatingFilterTest() {
analyzer = new Analyzer() {
@Override
protected Analyzer.TokenStreamComponents createComponents(String fieldName,
Reader reader) {
Tokenizer source = new MockTokenizer(reader, MockTokenizer.WHITESPACE, false);
return new Analyzer.TokenStreamComponents(source, new TokenPairConcatenatingFilter(source));
}
};
}
@BeforeClass
public static void setUpClass() {
}
@@ -60,21 +53,25 @@ public class TokenPairConcatenatingFilterTest extends BaseTokenStreamTestCase {
* test some examples
*/
public void testExamples() throws IOException {
//TODO figure outwhy I am getting "Failed: incrementtoken() called while in wrong state"
// String[] expected = new String[3];
// expected[0] = "one";
// expected[1] = "onetwo";
// expected[2] = "two";
// checkOneTerm(analyzer, "one", "one");
// assertAnalyzesTo(analyzer, "two", new String[]{"onetwo", "two"});
//checkOneTerm(analyzer, "two", "onetwo");
//checkOneTerm(analyzer, "three", "two");
Tokenizer wsTokenizer = new WhitespaceTokenizer(Version.LUCENE_43, new StringReader("one two three"));
TokenStream filter = new TokenPairConcatenatingFilter(wsTokenizer);
assertTokenStreamContents(filter,
new String[]{"one", "onetwo", "two", "twothree", "three"});
}
/**
* Test of clear method, of class TokenPairConcatenatingFilter.
*/
@Test
public void testClear() {
public void testClear() throws IOException {
TokenStream ts = new WhitespaceTokenizer(Version.LUCENE_43, new StringReader("one two three"));
TokenPairConcatenatingFilter filter = new TokenPairConcatenatingFilter(ts);
assertTokenStreamContents(filter, new String[]{"one", "onetwo", "two", "twothree", "three"});
assertNotNull(filter.getPreviousWord());
filter.clear();
assertNull(filter.getPreviousWord());
assertTrue(filter.getWords().isEmpty());
}
}

View File

@@ -0,0 +1,140 @@
/*
* This file is part of dependency-check-core.
*
* Dependency-check-core is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Dependency-check-core is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* dependency-check-core. If not, see http://www.gnu.org/licenses/.
*
* Copyright (c) 2013 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.data.update;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.text.DateFormat;
import java.util.Calendar;
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 org.owasp.dependencycheck.data.UpdateException;
import org.owasp.dependencycheck.utils.DownloadFailedException;
/**
*
* @author Jeremy Long (jeremy.long@owasp.org)
*/
public class AbstractUpdateTaskTest {
public AbstractUpdateTaskTest() {
}
@BeforeClass
public static void setUpClass() {
}
@AfterClass
public static void tearDownClass() {
}
@Before
public void setUp() {
}
@After
public void tearDown() {
}
public AbstractUpdateTask getAbstractUpdateImpl() throws Exception {
DataStoreMetaInfo props = new DataStoreMetaInfo();
AbstractUpdateTask instance = new AbstractUpdateImpl(props);
return instance;
}
/**
* Test of setDeleteAndRecreate method, of class AbstractUpdateTask.
*/
@Test
public void testSetDeleteAndRecreate() throws Exception {
boolean deleteAndRecreate = false;
boolean expResult = false;
AbstractUpdateTask instance = getAbstractUpdateImpl();
instance.setDeleteAndRecreate(deleteAndRecreate);
boolean result = instance.shouldDeleteAndRecreate();
assertEquals(expResult, result);
}
/**
* Test of deleteExistingData method, of class AbstractUpdateTask.
*/
@Test
public void testDeleteExistingData() throws Exception {
AbstractUpdateTask instance = getAbstractUpdateImpl();
Exception result = null;
try {
instance.deleteExistingData();
} catch (IOException ex) {
result = ex;
}
assertNull(result);
}
/**
* Test of openDataStores method, of class AbstractUpdateTask.
*/
@Test
public void testOpenDataStores() throws Exception {
AbstractUpdateTask instance = getAbstractUpdateImpl();
instance.openDataStores();
instance.closeDataStores();
}
/**
* Test of withinRange method, of class AbstractUpdateTask.
*/
@Test
public void testWithinRange() throws Exception {
Calendar c = Calendar.getInstance();
long current = c.getTimeInMillis();
long lastRun = c.getTimeInMillis() - (3 * (1000 * 60 * 60 * 24));
int range = 7; // 7 days
AbstractUpdateTask instance = getAbstractUpdateImpl();
boolean expResult = true;
boolean result = instance.withinRange(lastRun, current, range);
assertEquals(expResult, result);
lastRun = c.getTimeInMillis() - (8 * (1000 * 60 * 60 * 24));
expResult = false;
result = instance.withinRange(lastRun, current, range);
assertEquals(expResult, result);
}
public class AbstractUpdateImpl extends AbstractUpdateTask {
public AbstractUpdateImpl(DataStoreMetaInfo props) throws Exception {
super(props);
}
public Updateable updatesNeeded() throws MalformedURLException, DownloadFailedException, UpdateException {
return null;
}
public void update() throws UpdateException {
}
}
}

View File

@@ -14,35 +14,38 @@
* You should have received a copy of the GNU General Public License along with
* dependency-check-core. If not, see http://www.gnu.org/licenses/.
*
* Copyright (c) 2012 Jeremy Long. All Rights Reserved.
* Copyright (c) 2013 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.data.update;
import org.owasp.dependencycheck.data.update.DatabaseUpdater;
import java.io.File;
import java.net.MalformedURLException;
import org.apache.commons.io.FileUtils;
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.data.UpdateException;
import org.owasp.dependencycheck.utils.DownloadFailedException;
import org.owasp.dependencycheck.utils.Settings;
/**
*
* @author Jeremy Long (jeremy.long@owasp.org)
*/
public class DatabaseUpdater_1_Test {
public class BatchUpdateTaskTest {
public DatabaseUpdater_1_Test() {
public BatchUpdateTaskTest() {
}
@BeforeClass
public static void setUpClass() throws Exception {
public static void setUpClass() {
}
@AfterClass
public static void tearDownClass() throws Exception {
public static void tearDownClass() {
}
private String old12;
private String old20;
@@ -83,15 +86,36 @@ public class DatabaseUpdater_1_Test {
Settings.setString(Settings.KEYS.BATCH_UPDATE_URL, "");
}
public BatchUpdateTask getBatchUpdateTask() throws MalformedURLException, DownloadFailedException, UpdateException {
DataStoreMetaInfo props = new DataStoreMetaInfo();
BatchUpdateTask instance = new BatchUpdateTask(props);
return instance;
}
/**
* Test of update method (when in batch mode), of class DatabaseUpdater.
*
* @throws Exception
* Test of setDoBatchUpdate method, of class BatchUpdateTask.
*/
@Test
public void testBatchUpdate() throws Exception {
DatabaseUpdater instance = new DatabaseUpdater();
public void testSetDoBatchUpdate() throws DownloadFailedException, MalformedURLException, UpdateException {
boolean expected = false;
BatchUpdateTask instance = getBatchUpdateTask();
instance.setDoBatchUpdate(expected);
boolean results = instance.isDoBatchUpdate();
assertEquals(results, expected);
}
/**
* Test of update method, of class BatchUpdateTask.
*/
@Test
public void testUpdate() throws Exception {
BatchUpdateTask instance = getBatchUpdateTask();
//do some setup
instance.setDoBatchUpdate(true);
instance.deleteExistingData();
instance.update();
instance.update(); //no exceptions it worked?
//todo add some actual asserts to check things.
}
}

View File

@@ -0,0 +1,118 @@
/*
* This file is part of dependency-check-core.
*
* Dependency-check-core is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Dependency-check-core is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* dependency-check-core. If not, see http://www.gnu.org/licenses/.
*
* Copyright (c) 2013 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.data.update;
import java.io.File;
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.*;
/**
*
* @author Jeremy Long (jeremy.long@owasp.org)
*/
public class DataStoreMetaInfoTest {
public DataStoreMetaInfoTest() {
}
@BeforeClass
public static void setUpClass() {
}
@AfterClass
public static void tearDownClass() {
}
@Before
public void setUp() {
}
@After
public void tearDown() {
}
/**
* Test of isBatchUpdateMode method, of class DataStoreMetaInfo.
*/
@Test
public void testIsBatchUpdateMode() {
DataStoreMetaInfo instance = new DataStoreMetaInfo();
boolean expResult = false;
instance.setBatchUpdateMode(expResult);
boolean result = instance.isBatchUpdateMode();
assertEquals(expResult, result);
}
/**
* Test of isEmpty method, of class DataStoreMetaInfo.
*/
@Test
public void testIsEmpty() {
DataStoreMetaInfo instance = new DataStoreMetaInfo();
boolean expResult = false;
boolean result = instance.isEmpty();
assertEquals(expResult, result);
}
/**
* Test of save method, of class DataStoreMetaInfo.
*/
@Test
public void testSave() throws Exception {
NvdCveInfo updatedValue = new NvdCveInfo();
String key = "test";
long expected = 1337;
updatedValue.setId(key);
updatedValue.setTimestamp(expected);
DataStoreMetaInfo instance = new DataStoreMetaInfo();
instance.save(updatedValue);
//reload the properties
instance = new DataStoreMetaInfo();
long results = Long.parseLong(instance.getProperty("lastupdated." + key));
assertEquals(expected, results);
}
/**
* Test of getProperty method, of class DataStoreMetaInfo.
*/
@Test
public void testGetProperty_String_String() {
String key = "doesn't exist";
String defaultValue = "default";
DataStoreMetaInfo instance = new DataStoreMetaInfo();
String expResult = "default";
String result = instance.getProperty(key, defaultValue);
assertEquals(expResult, result);
}
/**
* Test of getPropertiesFile method, of class DataStoreMetaInfo.
*/
@Test
public void testGetPropertiesFile() {
File result = DataStoreMetaInfo.getPropertiesFile();
//wow... rigorous!
assertNotNull(result);
}
}

View File

@@ -14,19 +14,16 @@
* You should have received a copy of the GNU General Public License along with
* dependency-check-core. If not, see http://www.gnu.org/licenses/.
*
* Copyright (c) 2012 Jeremy Long. All Rights Reserved.
* Copyright (c) 2013 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.data.update;
import java.io.File;
import java.net.URL;
import org.owasp.dependencycheck.data.update.DatabaseUpdater;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.owasp.dependencycheck.utils.Settings;
import static org.junit.Assert.*;
/**
*
@@ -38,11 +35,11 @@ public class DatabaseUpdaterIntegrationTest {
}
@BeforeClass
public static void setUpClass() throws Exception {
public static void setUpClass() {
}
@AfterClass
public static void tearDownClass() throws Exception {
public static void tearDownClass() {
}
@Before
@@ -55,8 +52,6 @@ public class DatabaseUpdaterIntegrationTest {
/**
* Test of update method, of class DatabaseUpdater.
*
* @throws Exception
*/
@Test
public void testUpdate() throws Exception {

View File

@@ -1,87 +0,0 @@
/*
* This file is part of dependency-check-core.
*
* Dependency-check-core is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Dependency-check-core is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* dependency-check-core. If not, see http://www.gnu.org/licenses/.
*
* Copyright (c) 2012 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.data.update;
import org.owasp.dependencycheck.data.update.DatabaseUpdater;
import java.io.File;
import org.apache.commons.io.FileUtils;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.owasp.dependencycheck.utils.Settings;
/**
*
* @author Jeremy Long (jeremy.long@owasp.org)
*/
public class DatabaseUpdater_2_Test {
public DatabaseUpdater_2_Test() {
}
@BeforeClass
public static void setUpClass() throws Exception {
}
@AfterClass
public static void tearDownClass() throws Exception {
}
private String old12;
private String old20;
@Before
public void setUp() throws Exception {
old12 = Settings.getString(Settings.KEYS.CVE_MODIFIED_12_URL);
old20 = Settings.getString(Settings.KEYS.CVE_MODIFIED_20_URL);
Settings.removeProperty(Settings.KEYS.CVE_MODIFIED_12_URL);
Settings.removeProperty(Settings.KEYS.CVE_MODIFIED_20_URL);
File tmp = Settings.getTempDirectory();
if (!tmp.exists()) {
tmp.mkdirs();
}
File dest = new File(tmp, "data.zip");
File file = new File(this.getClass().getClassLoader().getResource("data.zip").toURI());
FileUtils.copyFile(file, dest);
String path = "file:///" + dest.getCanonicalPath();
Settings.setString(Settings.KEYS.BATCH_UPDATE_URL, path);
}
@After
public void tearDown() {
Settings.setString(Settings.KEYS.CVE_MODIFIED_12_URL, old12);
Settings.setString(Settings.KEYS.CVE_MODIFIED_20_URL, old20);
Settings.removeProperty(Settings.KEYS.BATCH_UPDATE_URL);
}
/**
* Test of update method (when in batch mode), of class DatabaseUpdater.
*
* @throws Exception
*/
@Test
public void testBatchUpdateWithoutModified() throws Exception {
DatabaseUpdater instance = new DatabaseUpdater();
instance.deleteExistingData();
instance.update();
}
}

View File

@@ -0,0 +1,113 @@
/*
* This file is part of dependency-check-core.
*
* Dependency-check-core is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Dependency-check-core is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* dependency-check-core. If not, see http://www.gnu.org/licenses/.
*
* Copyright (c) 2013 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.data.update;
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.*;
/**
* Rigorous test of setters/getters.
*
* @author Jeremy Long (jeremy.long@owasp.org)
*/
public class NvdCveInfoTest {
public NvdCveInfoTest() {
}
@BeforeClass
public static void setUpClass() {
}
@AfterClass
public static void tearDownClass() {
}
@Before
public void setUp() {
}
@After
public void tearDown() {
}
/**
* Test of setId and getId method, of class NvdCveInfo.
*/
@Test
public void testSetGetId() {
NvdCveInfo instance = new NvdCveInfo();
String expResult = "id";
instance.setId(expResult);
String result = instance.getId();
assertEquals(expResult, result);
}
/**
* Test of getUrl method, of class NvdCveInfo.
*/
@Test
public void testSetGetUrl() {
NvdCveInfo instance = new NvdCveInfo();
String expResult = "http://www.someurl.com/something";
instance.setUrl(expResult);
String result = instance.getUrl();
assertEquals(expResult, result);
}
/**
* Test of getOldSchemaVersionUrl method, of class NvdCveInfo.
*/
@Test
public void testSetGetOldSchemaVersionUrl() {
NvdCveInfo instance = new NvdCveInfo();
String expResult = "http://www.someurl.com/something";
instance.setOldSchemaVersionUrl(expResult);
String result = instance.getOldSchemaVersionUrl();
assertEquals(expResult, result);
}
/**
* Test of getTimestamp method, of class NvdCveInfo.
*/
@Test
public void testSetGetTimestamp() {
NvdCveInfo instance = new NvdCveInfo();
long expResult = 1337L;
instance.setTimestamp(expResult);
long result = instance.getTimestamp();
assertEquals(expResult, result);
}
/**
* Test of getNeedsUpdate method, of class NvdCveInfo.
*/
@Test
public void testSetGetNeedsUpdate() {
NvdCveInfo instance = new NvdCveInfo();
boolean expResult = true;
instance.setNeedsUpdate(expResult);
boolean result = instance.getNeedsUpdate();
assertEquals(expResult, result);
}
}

View File

@@ -0,0 +1,81 @@
/*
* This file is part of dependency-check-core.
*
* Dependency-check-core is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Dependency-check-core is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* dependency-check-core. If not, see http://www.gnu.org/licenses/.
*
* Copyright (c) 2013 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.data.update;
import java.net.MalformedURLException;
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.data.UpdateException;
import org.owasp.dependencycheck.utils.DownloadFailedException;
/**
*
* @author Jeremy Long (jeremy.long@owasp.org)
*/
public class StandardUpdateTaskIntegrationTest {
public StandardUpdateTaskIntegrationTest() {
}
@BeforeClass
public static void setUpClass() {
}
@AfterClass
public static void tearDownClass() {
}
@Before
public void setUp() {
}
@After
public void tearDown() {
}
public StandardUpdateTask getStandardUpdateTask() throws MalformedURLException, DownloadFailedException, UpdateException {
DataStoreMetaInfo props = new DataStoreMetaInfo();
StandardUpdateTask instance = new StandardUpdateTask(props);
return instance;
}
/**
* Test of update method, of class StandardUpdateTask.
*/
@Test
public void testUpdate() throws Exception {
StandardUpdateTask instance = getStandardUpdateTask();
instance.update();
//TODO make this an actual test
}
/**
* Test of updatesNeeded method, of class StandardUpdateTask.
*/
@Test
public void testUpdatesNeeded() throws Exception {
StandardUpdateTask instance = getStandardUpdateTask();
Updateable result = instance.updatesNeeded();
assertNotNull(result);
}
}

View File

@@ -0,0 +1,160 @@
/*
* This file is part of dependency-check-core.
*
* Dependency-check-core is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* Dependency-check-core is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* dependency-check-core. If not, see http://www.gnu.org/licenses/.
*
* Copyright (c) 2013 Jeremy Long. All Rights Reserved.
*/
package org.owasp.dependencycheck.data.update;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
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.utils.DownloadFailedException;
/**
*
* @author Jeremy Long (jeremy.long@owasp.org)
*/
public class UpdateableTest {
public UpdateableTest() {
}
@BeforeClass
public static void setUpClass() {
}
@AfterClass
public static void tearDownClass() {
}
@Before
public void setUp() {
}
@After
public void tearDown() {
}
/**
* Test of isUpdateNeeded method, of class Updateable.
*/
@Test
public void testIsUpdateNeeded() throws MalformedURLException, DownloadFailedException, IOException {
String id = "key";
//use a local file as this test will load the result and check the timestamp
File f = new File("target/test-classes/nvdcve-2.0-2012.xml");
String url = "file:///" + f.getCanonicalPath();
Updateable instance = new Updateable();
instance.add(id, url, url, false);
boolean expResult = false;
boolean result = instance.isUpdateNeeded();
assertEquals(expResult, result);
instance.add("nextId", url, url, true);
expResult = true;
result = instance.isUpdateNeeded();
assertEquals(expResult, result);
}
/**
* Test of add method, of class Updateable.
*/
@Test
public void testAdd_3args() throws Exception {
String id = "key";
File f = new File("target/test-classes/nvdcve-2.0-2012.xml");
//use a local file as this test will load the result and check the timestamp
String url = "file:///" + f.getCanonicalPath();
Updateable instance = new Updateable();
instance.add(id, url, url);
NvdCveInfo results = instance.get(id);
assertEquals(id, results.getId());
assertEquals(url, results.getUrl());
assertEquals(url, results.getOldSchemaVersionUrl());
}
/**
* Test of add method, of class Updateable.
*/
@Test
public void testAdd_4args() throws Exception {
String id = "key";
//use a local file as this test will load the result and check the timestamp
File f = new File("target/test-classes/nvdcve-2.0-2012.xml");
String url = "file:///" + f.getCanonicalPath();
Updateable instance = new Updateable();
instance.add(id, url, url, false);
boolean expResult = false;
boolean result = instance.isUpdateNeeded();
assertEquals(expResult, result);
instance.add("nextId", url, url, false);
NvdCveInfo results = instance.get(id);
assertEquals(id, results.getId());
assertEquals(url, results.getUrl());
assertEquals(url, results.getOldSchemaVersionUrl());
}
/**
* Test of clear method, of class Updateable.
*/
@Test
public void testClear() throws MalformedURLException, DownloadFailedException, IOException {
String id = "key";
//use a local file as this test will load the result and check the timestamp
File f = new File("target/test-classes/nvdcve-2.0-2012.xml");
String url = "file:///" + f.getCanonicalPath();
Updateable instance = new Updateable();
instance.add(id, url, url, false);
assertFalse(instance.getCollection().isEmpty());
instance.clear();
assertTrue(instance.getCollection().isEmpty());
}
/**
* Test of iterator method, of class Updateable.
*/
@Test
public void testIterator() throws IOException {
//use a local file as this test will load the result and check the timestamp
File f = new File("target/test-classes/nvdcve-2.0-2012.xml");
String url = "file:///" + f.getCanonicalPath();
Updateable instance = new Updateable();
instance.add("one", url, url, false);
instance.add("two", url, url, false);
instance.add("three", url, url, false);
int itemsProcessed = 0;
for (NvdCveInfo item : instance) {
if ("one".equals(item.getId())) {
instance.remove();
}
itemsProcessed += 1;
}
assertEquals(3, itemsProcessed);
assertEquals(2, instance.getCollection().size());
}
}

View File

@@ -18,6 +18,7 @@
*/
package org.owasp.dependencycheck.reporting;
import org.owasp.dependencycheck.Engine;
import org.owasp.dependencycheck.data.cpe.BaseIndexTestCase;
import org.junit.After;
import org.junit.AfterClass;
@@ -25,6 +26,14 @@ import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import javax.xml.XMLConstants;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;
import java.io.File;
import java.io.InputStream;
/**
*
* @author Jeremy Long (jeremy.long@owasp.org)
@@ -107,4 +116,41 @@ public class ReportGeneratorTest {
// instance.generateReport(templateName, writeTo, properties);
//assertTrue("need to add a real check here", false);
}
/**
* Generates an XML report containing known vulnerabilities and realistic
* data and validates the generated XML document against the XSD.
* @throws Exception
*/
@Test
public void testGenerateXMLReport() throws Exception {
String templateName = "XmlReport";
File f = new File("target/test-reports");
if (!f.exists()) {
f.mkdir();
}
String writeTo = "target/test-reports/Report.xml";
File struts = new File(this.getClass().getClassLoader().getResource("struts2-core-2.1.2.jar").getPath());
File axis = new File(this.getClass().getClassLoader().getResource("axis2-adb-1.4.1.jar").getPath());
File jetty = new File(this.getClass().getClassLoader().getResource("org.mortbay.jetty.jar").getPath());
Engine engine = new Engine();
engine.scan(struts);
engine.scan(axis);
engine.scan(jetty);
engine.analyzeDependencies();
ReportGenerator generator = new ReportGenerator("Test Report", engine.getDependencies(), engine.getAnalyzers());
generator.generateReport(templateName, writeTo);
InputStream xsdStream = ReportGenerator.class.getClassLoader().getResourceAsStream("schema/DependencyCheck.xsd");
StreamSource xsdSource = new StreamSource(xsdStream);
StreamSource xmlSource = new StreamSource(new File(writeTo));
SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = sf.newSchema(xsdSource);
Validator validator = schema.newValidator();
validator.validate(xmlSource);
}
}

View File

@@ -109,7 +109,6 @@ public class DependencyVersionTest {
*/
@Test
public void testHashCode() {
System.out.println("hashCode");
DependencyVersion instance = new DependencyVersion("3.2.1");
int expResult = 80756;
int result = instance.hashCode();

View File

@@ -6,7 +6,7 @@
<parent>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-parent</artifactId>
<version>1.0.2</version>
<version>1.0.3</version>
</parent>
<groupId>org.owasp</groupId>

View File

@@ -24,7 +24,7 @@ Copyright (c) 2013 Jeremy Long. All Rights Reserved.
<parent>
<groupId>org.owasp</groupId>
<artifactId>dependency-check-parent</artifactId>
<version>1.0.2</version>
<version>1.0.3</version>
</parent>
<artifactId>dependency-check-maven</artifactId>

View File

@@ -4,7 +4,7 @@ handlers=java.util.logging.ConsoleHandler, java.util.logging.FileHandler
# FINEST, FINER, FINE, CONFIG, INFO, WARNING and SEVERE.
# Configure the ConsoleHandler.
java.util.logging.ConsoleHandler.level=WARNING
java.util.logging.ConsoleHandler.level=INFO
#org.owasp.dependencycheck.data.nvdcve.xml

View File

@@ -22,7 +22,7 @@ along with Dependency-Check. If not, see <http://www.gnu.org/licenses />.
<groupId>org.owasp</groupId>
<artifactId>dependency-check-parent</artifactId>
<version>1.0.2</version>
<version>1.0.3</version>
<packaging>pom</packaging>
<parent>