mirror of
https://github.com/ysoftdevs/DependencyCheck.git
synced 2026-01-14 07:43:40 +01:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2fcc325af7 | ||
|
|
5334cf7def | ||
|
|
a8a85a5947 | ||
|
|
a6faadcc74 | ||
|
|
1e7b45c00b | ||
|
|
9f21ea6a9d | ||
|
|
99c056e7f5 |
@@ -7,10 +7,10 @@ If found, it will generate a report linking to the associated CVE entries.
|
||||
Usage:
|
||||
$ mvn package
|
||||
$ cd target
|
||||
$ java -jar DependencyCheck-0.2.2.jar -h
|
||||
$ java -jar DependencyCheck-0.2.2.jar -a Testing -out . -scan ./test-classes/org.mortbay.jetty.jar -scan ./test-classes/struts2-core-2.1.2.jar -scan ./lib
|
||||
$ java -jar DependencyCheck-0.2.3.1.jar -h
|
||||
$ java -jar DependencyCheck-0.2.3.1.jar -a Testing -out . -scan ./test-classes/org.mortbay.jetty.jar -scan ./test-classes/struts2-core-2.1.2.jar -scan ./lib
|
||||
|
||||
Then load the resulting 'Testing.html' into your favorite browser.
|
||||
Then load the resulting 'DependencyCheck-Report.html' into your favorite browser.
|
||||
|
||||
Author: Jeremy Long (jeremy.long@gmail.com)
|
||||
|
||||
|
||||
39
pom.xml
39
pom.xml
@@ -23,7 +23,7 @@ along with DependencyCheck. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
<groupId>org.codesecure</groupId>
|
||||
<artifactId>DependencyCheck</artifactId>
|
||||
<version>0.2.2</version>
|
||||
<version>0.2.3.1</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>DependencyCheck</name>
|
||||
@@ -100,7 +100,7 @@ along with DependencyCheck. If not, see <http://www.gnu.org/licenses/>.
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>2.8.1</version>
|
||||
<configuration>
|
||||
<bottom>Copyright © 2012 Jeremy Long. All Rights Reserved.</bottom>
|
||||
<bottom>Copyright© 2012 Jeremy Long. All Rights Reserved.</bottom>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
@@ -206,13 +206,21 @@ along with DependencyCheck. If not, see <http://www.gnu.org/licenses/>.
|
||||
<value>${project.build.directory}/cobertura/cobertura.ser</value>
|
||||
<workingDirectory>target</workingDirectory>
|
||||
</property>
|
||||
<property>
|
||||
<!--<property>
|
||||
<name>cve</name>
|
||||
<value>${project.build.directory}/data/cve</value>
|
||||
</property>
|
||||
<property>
|
||||
<name>cpe</name>
|
||||
<value>${project.build.directory}/data/cpe</value>
|
||||
</property>-->
|
||||
<property>
|
||||
<name>cve</name>
|
||||
<value>target/data/cve</value>
|
||||
</property>
|
||||
<property>
|
||||
<name>cpe</name>
|
||||
<value>target/data/cpe</value>
|
||||
</property>
|
||||
</systemProperties>
|
||||
<excludes>
|
||||
@@ -224,6 +232,21 @@ along with DependencyCheck. If not, see <http://www.gnu.org/licenses/>.
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-failsafe-plugin</artifactId>
|
||||
<version>2.12.4</version>
|
||||
<configuration>
|
||||
<systemProperties>
|
||||
<property>
|
||||
<name>cve</name>
|
||||
<value>target/data/cve</value>
|
||||
</property>
|
||||
<property>
|
||||
<name>cpe</name>
|
||||
<value>target/data/cpe</value>
|
||||
</property>
|
||||
</systemProperties>
|
||||
<includes>
|
||||
<include>**/*IntegrationTest.java</include>
|
||||
</includes>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
@@ -338,6 +361,7 @@ along with DependencyCheck. If not, see <http://www.gnu.org/licenses/>.
|
||||
<reportSet>
|
||||
<id>integration-tests</id>
|
||||
<reports>
|
||||
<report>report-only</report>
|
||||
<report>failsafe-report-only</report>
|
||||
</reports>
|
||||
</reportSet>
|
||||
@@ -427,5 +451,14 @@ along with DependencyCheck. If not, see <http://www.gnu.org/licenses/>.
|
||||
<artifactId>hawtdb</artifactId>
|
||||
<version>1.6</version>
|
||||
</dependency>-->
|
||||
|
||||
<!-- The following dependencies are only scanned during integration testing -->
|
||||
<!--<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
<version>2.5.5</version>
|
||||
<scope>test</scope>
|
||||
</dependency>-->
|
||||
|
||||
</dependencies>
|
||||
</project>
|
||||
|
||||
@@ -74,6 +74,7 @@ public class App {
|
||||
//Preferences.systemRoot().put("java.util.logging.config.file", "log.properties");
|
||||
//System.getProperties().put("java.util.logging.config.file", "configuration/log.properties");
|
||||
File dir = new File("logs");
|
||||
|
||||
if (!dir.exists()) {
|
||||
dir.mkdir();
|
||||
}
|
||||
@@ -157,9 +158,9 @@ public class App {
|
||||
scanner.analyzeDependencies();
|
||||
List<Dependency> dependencies = scanner.getDependencies();
|
||||
|
||||
ReportGenerator report = new ReportGenerator();
|
||||
ReportGenerator report = new ReportGenerator(applicationName, dependencies, scanner.getAnalyzers());
|
||||
try {
|
||||
report.generateReports(reportDirectory, applicationName, dependencies);
|
||||
report.generateReports(reportDirectory);
|
||||
} catch (IOException ex) {
|
||||
Logger.getLogger(App.class.getName()).log(Level.SEVERE, null, ex);
|
||||
} catch (Exception ex) {
|
||||
|
||||
@@ -195,7 +195,8 @@ public class Engine {
|
||||
try {
|
||||
a.initialize();
|
||||
} catch (Exception ex) {
|
||||
Logger.getLogger(Engine.class.getName()).log(Level.SEVERE, "Exception occured initializing " + a.getName() + ".", ex);
|
||||
Logger.getLogger(Engine.class.getName()).log(Level.SEVERE,
|
||||
"Exception occured initializing " + a.getName() + ".", ex);
|
||||
try {
|
||||
a.close();
|
||||
} catch (Exception ex1) {
|
||||
@@ -254,8 +255,23 @@ public class Engine {
|
||||
try {
|
||||
source.update();
|
||||
} catch (UpdateException ex) {
|
||||
Logger.getLogger(Engine.class.getName()).log(Level.SEVERE, "Unable to update " + source.getClass().getName(), ex);
|
||||
Logger.getLogger(Engine.class.getName()).log(Level.SEVERE,
|
||||
"Unable to update " + source.getClass().getName(), ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a full list of all of the analyzers. This is useful
|
||||
* for reporting which analyzers where used.
|
||||
* @return a list of Analyzers
|
||||
*/
|
||||
public List<Analyzer> getAnalyzers() {
|
||||
List<Analyzer> ret = new ArrayList<Analyzer>();
|
||||
for (AnalysisPhase phase : AnalysisPhase.values()) {
|
||||
List<Analyzer> analyzerList = analyzers.get(phase);
|
||||
ret.addAll(analyzerList);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,6 +186,7 @@ public class JarAnalyzer extends AbstractAnalyzer {
|
||||
parseManifest(dependency);
|
||||
analyzePackageNames(dependency);
|
||||
analyzePOM(dependency);
|
||||
addPredefinedData(dependency);
|
||||
} catch (IOException ex) {
|
||||
throw new AnalysisException("Exception occured reading the JAR file.", ex);
|
||||
} catch (JAXBException ex) {
|
||||
@@ -615,4 +616,15 @@ public class JarAnalyzer extends AbstractAnalyzer {
|
||||
sb.append(text.substring(end + 1));
|
||||
return interpolateString(sb.toString(), properties); //yes yes, this should be a loop...
|
||||
}
|
||||
|
||||
private void addPredefinedData(Dependency dependency) {
|
||||
Evidence spring = new Evidence("Manifest",
|
||||
"Implementation-Title",
|
||||
"Spring Framework",
|
||||
Evidence.Confidence.HIGH);
|
||||
|
||||
if (dependency.getProductEvidence().getEvidence().contains(spring)) {
|
||||
dependency.getVendorEvidence().addEvidence("a priori", "vendor", "SpringSource", Evidence.Confidence.HIGH);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,23 +149,11 @@ public class CPEAnalyzer implements org.codesecure.dependencycheck.analyzer.Anal
|
||||
Confidence versionConf = Confidence.HIGH;
|
||||
|
||||
String vendors = addEvidenceWithoutDuplicateTerms("", dependency.getVendorEvidence(), vendorConf);
|
||||
//dependency.getVendorEvidence().toString(vendorConf);
|
||||
// if ("".equals(vendors)) {
|
||||
// vendors = STRING_THAT_WILL_NEVER_BE_IN_THE_INDEX;
|
||||
// }
|
||||
String products = addEvidenceWithoutDuplicateTerms("", dependency.getProductEvidence(), productConf);
|
||||
///dependency.getProductEvidence().toString(productConf);
|
||||
// if ("".equals(products)) {
|
||||
// products = STRING_THAT_WILL_NEVER_BE_IN_THE_INDEX;
|
||||
// }
|
||||
String versions = addEvidenceWithoutDuplicateTerms("", dependency.getVersionEvidence(), versionConf);
|
||||
//dependency.getVersionEvidence().toString(versionConf);
|
||||
// if ("".equals(versions)) {
|
||||
// versions = STRING_THAT_WILL_NEVER_BE_IN_THE_INDEX;
|
||||
// }
|
||||
|
||||
boolean found = false;
|
||||
int cnt = 0;
|
||||
int ctr = 0;
|
||||
do {
|
||||
List<Entry> entries = searchCPE(vendors, products, versions, dependency.getProductEvidence().getWeighting(),
|
||||
dependency.getVendorEvidence().getWeighting());
|
||||
@@ -186,14 +174,14 @@ public class CPEAnalyzer implements org.codesecure.dependencycheck.analyzer.Anal
|
||||
|
||||
|
||||
if (!found) {
|
||||
int round = cnt % 3;
|
||||
int round = ctr % 3;
|
||||
if (round == 0) {
|
||||
vendorConf = reduceConfidence(vendorConf);
|
||||
if (dependency.getVendorEvidence().contains(vendorConf)) {
|
||||
//vendors += " " + dependency.getVendorEvidence().toString(vendorConf);
|
||||
vendors = addEvidenceWithoutDuplicateTerms(vendors, dependency.getVendorEvidence(), vendorConf);
|
||||
} else {
|
||||
cnt += 1;
|
||||
ctr += 1;
|
||||
round += 1;
|
||||
}
|
||||
}
|
||||
@@ -203,7 +191,7 @@ public class CPEAnalyzer implements org.codesecure.dependencycheck.analyzer.Anal
|
||||
//products += " " + dependency.getProductEvidence().toString(productConf);
|
||||
products = addEvidenceWithoutDuplicateTerms(products, dependency.getProductEvidence(), productConf);
|
||||
} else {
|
||||
cnt += 1;
|
||||
ctr += 1;
|
||||
round += 1;
|
||||
}
|
||||
}
|
||||
@@ -215,7 +203,7 @@ public class CPEAnalyzer implements org.codesecure.dependencycheck.analyzer.Anal
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (!found && (++cnt) < 9);
|
||||
} while (!found && (++ctr) < 9);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -45,17 +45,12 @@ public class Entry {
|
||||
public static Entry parse(Document doc) {
|
||||
Entry entry = new Entry();
|
||||
try {
|
||||
entry.setName(doc.get(Fields.NAME));
|
||||
entry.parseName(doc.get(Fields.NAME));
|
||||
entry.setTitle(doc.get(Fields.TITLE));
|
||||
} catch (UnsupportedEncodingException ex) {
|
||||
Logger.getLogger(Entry.class.getName()).log(Level.SEVERE, null, ex);
|
||||
entry.name = doc.get(Fields.NAME);
|
||||
}
|
||||
// entry.vendor = doc.get(Fields.VENDOR);
|
||||
// entry.version = doc.get(Fields.VERSION);
|
||||
// //entry.revision = doc.get(Fields.REVISION);
|
||||
// entry.product = doc.get(Fields.TITLE);
|
||||
// entry.nvdId = doc.get(Fields.NVDID);
|
||||
return entry;
|
||||
}
|
||||
/**
|
||||
@@ -95,15 +90,12 @@ public class Entry {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of name and calls parseName to obtain the
|
||||
* vendor:product:version:revision
|
||||
* Set the value of name
|
||||
*
|
||||
* @param name new value of name
|
||||
* @throws UnsupportedEncodingException should never be thrown...
|
||||
*/
|
||||
public void setName(String name) throws UnsupportedEncodingException {
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
parseName();
|
||||
}
|
||||
/**
|
||||
* The status of the CPE Entry.
|
||||
@@ -310,15 +302,17 @@ public class Entry {
|
||||
* <p>Results in:</p> <ul> <li>Vendor: apache</li> <li>Product: struts</li>
|
||||
* <li>Version: 1.1</li> <li>Revision: rc2</li> </ul>
|
||||
*
|
||||
* @param cpeName the cpe name
|
||||
* @throws UnsupportedEncodingException should never be thrown...
|
||||
*/
|
||||
private void parseName() throws UnsupportedEncodingException {
|
||||
if (name != null && name.length() > 7) {
|
||||
String[] data = name.substring(7).split(":");
|
||||
public void parseName(String cpeName) throws UnsupportedEncodingException {
|
||||
this.name = cpeName;
|
||||
if (cpeName != null && cpeName.length() > 7) {
|
||||
String[] data = cpeName.substring(7).split(":");
|
||||
if (data.length >= 1) {
|
||||
vendor = URLDecoder.decode(data[0], "UTF-8");
|
||||
vendor = URLDecoder.decode(data[0], "UTF-8").replaceAll("[_-]", " ");
|
||||
if (data.length >= 2) {
|
||||
product = URLDecoder.decode(data[1], "UTF-8");
|
||||
product = URLDecoder.decode(data[1], "UTF-8").replaceAll("[_-]", " ");
|
||||
if (data.length >= 3) {
|
||||
version = URLDecoder.decode(data[2], "UTF-8");
|
||||
if (data.length >= 4) {
|
||||
|
||||
@@ -28,6 +28,7 @@ import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLDecoder;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
@@ -74,13 +75,39 @@ public class Index extends AbstractIndex implements CachedWebDataSource {
|
||||
* @throws IOException is thrown if an IOException occurs.
|
||||
*/
|
||||
public Directory getDirectory() throws IOException {
|
||||
String fileName = Settings.getString(Settings.KEYS.CPE_INDEX);
|
||||
File path = new File(fileName);
|
||||
File path = getDataDirectory();
|
||||
Directory dir = FSDirectory.open(path);
|
||||
|
||||
return dir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the directory that the JAR file exists in so that
|
||||
* we can ensure we always use a common data directory.
|
||||
*
|
||||
* @return the data directory for this index.
|
||||
* @throws IOException is thrown if an IOException occurs of course...
|
||||
*/
|
||||
protected File getDataDirectory() throws IOException {
|
||||
String fileName = Settings.getString(Settings.KEYS.CPE_INDEX);
|
||||
String filePath = Index.class.getProtectionDomain().getCodeSource().getLocation().getPath();
|
||||
String decodedPath = URLDecoder.decode(filePath, "UTF-8");
|
||||
File exePath = new File(decodedPath);
|
||||
if (exePath.getName().toLowerCase().endsWith(".jar")) {
|
||||
exePath = exePath.getParentFile();
|
||||
} else {
|
||||
exePath = new File(".");
|
||||
}
|
||||
File path = new File(exePath.getCanonicalFile() + File.separator + fileName);
|
||||
path = new File(path.getCanonicalPath());
|
||||
if (!path.exists()) {
|
||||
if (!path.mkdirs()) {
|
||||
throw new IOException("Unable to create CPE Data directory");
|
||||
}
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an Analyzer for the CPE Index.
|
||||
*
|
||||
@@ -91,6 +118,7 @@ public class Index extends AbstractIndex implements CachedWebDataSource {
|
||||
Map fieldAnalyzers = new HashMap();
|
||||
|
||||
fieldAnalyzers.put(Fields.VERSION, new KeywordAnalyzer());
|
||||
fieldAnalyzers.put(Fields.NAME, new KeywordAnalyzer());
|
||||
|
||||
PerFieldAnalyzerWrapper wrapper = new PerFieldAnalyzerWrapper(
|
||||
new StandardAnalyzer(Version.LUCENE_35), fieldAnalyzers);
|
||||
@@ -153,8 +181,14 @@ public class Index extends AbstractIndex implements CachedWebDataSource {
|
||||
*
|
||||
* @param timeStamp the timestamp to write.
|
||||
*/
|
||||
private void writeLastUpdatedPropertyFile(long timeStamp) {
|
||||
String dir = Settings.getString(Settings.KEYS.CPE_INDEX);
|
||||
private void writeLastUpdatedPropertyFile(long timeStamp) throws UpdateException {
|
||||
String dir;
|
||||
try {
|
||||
dir = getDataDirectory().getCanonicalPath();
|
||||
} catch (IOException ex) {
|
||||
Logger.getLogger(Index.class.getName()).log(Level.SEVERE, null, ex);
|
||||
throw new UpdateException("Unable to locate the last updated properties file.", ex);
|
||||
}
|
||||
File cpeProp = new File(dir + File.separatorChar + UPDATE_PROPERTIES_FILE);
|
||||
Properties prop = new Properties();
|
||||
prop.put(Index.LAST_UPDATED, String.valueOf(timeStamp));
|
||||
@@ -193,8 +227,10 @@ public class Index extends AbstractIndex implements CachedWebDataSource {
|
||||
* is incorrect.
|
||||
* @throws DownloadFailedException is thrown if there is an error
|
||||
* downloading the cpe.meta data file.
|
||||
* @throws UpdateException is thrown if there is an error locating the last updated
|
||||
* properties file.
|
||||
*/
|
||||
public long updateNeeded() throws MalformedURLException, DownloadFailedException {
|
||||
public long updateNeeded() throws MalformedURLException, DownloadFailedException, UpdateException {
|
||||
long retVal = 0;
|
||||
long lastUpdated = 0;
|
||||
long currentlyPublishedDate = retrieveCurrentCPETimestampFromWeb();
|
||||
@@ -202,12 +238,24 @@ public class Index extends AbstractIndex implements CachedWebDataSource {
|
||||
throw new DownloadFailedException("Unable to retrieve valid timestamp from cpe.meta file");
|
||||
}
|
||||
|
||||
String dir = Settings.getString(Settings.KEYS.CPE_INDEX);
|
||||
File f = new File(dir);
|
||||
//String dir = Settings.getString(Settings.KEYS.CPE_INDEX);
|
||||
File f;
|
||||
try {
|
||||
f = getDataDirectory(); //new File(dir);
|
||||
} catch (IOException ex) {
|
||||
Logger.getLogger(Index.class.getName()).log(Level.SEVERE, null, ex);
|
||||
throw new UpdateException("Unable to locate last updated properties file.", ex);
|
||||
}
|
||||
if (!f.exists()) {
|
||||
retVal = currentlyPublishedDate;
|
||||
} else {
|
||||
File cpeProp = new File(dir + File.separatorChar + UPDATE_PROPERTIES_FILE);
|
||||
File cpeProp;
|
||||
try {
|
||||
cpeProp = new File(f.getCanonicalPath() + File.separatorChar + UPDATE_PROPERTIES_FILE);
|
||||
} catch (IOException ex) {
|
||||
Logger.getLogger(Index.class.getName()).log(Level.SEVERE, null, ex);
|
||||
throw new UpdateException("Unable to find last updated properties file.", ex);
|
||||
}
|
||||
if (!cpeProp.exists()) {
|
||||
retVal = currentlyPublishedDate;
|
||||
} else {
|
||||
|
||||
@@ -66,7 +66,7 @@ public class CPEHandler extends DefaultHandler {
|
||||
skip = (temp != null && temp.equals("true"));
|
||||
try {
|
||||
if (!skip && name.startsWith("cpe:/a:")) {
|
||||
entry.setName(name);
|
||||
entry.parseName(name);
|
||||
} else {
|
||||
skip = true;
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@ import org.apache.lucene.index.Term;
|
||||
import org.codesecure.dependencycheck.data.cpe.Entry;
|
||||
import org.codesecure.dependencycheck.data.cpe.Fields;
|
||||
import org.codesecure.dependencycheck.data.cpe.Index;
|
||||
import org.codesecure.dependencycheck.data.lucene.LuceneUtils;
|
||||
|
||||
/**
|
||||
* The Indexer is used to convert a CPE Entry, retrieved from the CPE XML file,
|
||||
@@ -46,7 +45,8 @@ public class Indexer extends Index implements EntrySaveDelegate {
|
||||
*/
|
||||
public void saveEntry(Entry entry) throws CorruptIndexException, IOException {
|
||||
Document doc = convertEntryToDoc(entry);
|
||||
Term term = new Term(Fields.NVDID, LuceneUtils.escapeLuceneQuery(entry.getNvdId()));
|
||||
//Term term = new Term(Fields.NVDID, LuceneUtils.escapeLuceneQuery(entry.getNvdId()));
|
||||
Term term = new Term(Fields.NAME, entry.getName());
|
||||
indexWriter.updateDocument(term, doc);
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ package org.codesecure.dependencycheck.data.nvdcve;
|
||||
import java.io.*;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLDecoder;
|
||||
import java.util.*;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
@@ -66,18 +67,45 @@ public class Index extends AbstractIndex implements CachedWebDataSource {
|
||||
private static final String LAST_UPDATED_BASE = "lastupdated.";
|
||||
|
||||
/**
|
||||
* Returns the directory that holds the NVD CVE Index.
|
||||
* Returns the directory that holds the NVD CVE Index. Note, this
|
||||
* returns the path where the class or jar file exists.
|
||||
*
|
||||
* @return the Directory containing the NVD CVE Index.
|
||||
* @throws IOException is thrown if an IOException occurs.
|
||||
*/
|
||||
public Directory getDirectory() throws IOException {
|
||||
String fileName = Settings.getString(Settings.KEYS.CVE_INDEX);
|
||||
File path = new File(fileName);
|
||||
File path = getDataDirectory();
|
||||
Directory dir = FSDirectory.open(path);
|
||||
return dir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the directory that the JAR file exists in so that
|
||||
* we can ensure we always use a common data directory.
|
||||
*
|
||||
* @return the data directory for this index.
|
||||
* @throws IOException is thrown if an IOException occurs of course...
|
||||
*/
|
||||
protected File getDataDirectory() throws IOException {
|
||||
String fileName = Settings.getString(Settings.KEYS.CVE_INDEX);
|
||||
String filePath = Index.class.getProtectionDomain().getCodeSource().getLocation().getPath();
|
||||
String decodedPath = URLDecoder.decode(filePath, "UTF-8");
|
||||
File exePath = new File(decodedPath);
|
||||
if (exePath.getName().toLowerCase().endsWith(".jar")) {
|
||||
exePath = exePath.getParentFile();
|
||||
} else {
|
||||
exePath = new File(".");
|
||||
}
|
||||
File path = new File(exePath.getCanonicalFile() + File.separator + fileName);
|
||||
path = new File(path.getCanonicalPath());
|
||||
if (!path.exists()) {
|
||||
if (!path.mkdirs()) {
|
||||
throw new IOException("Unable to create NVD CVE Data directory");
|
||||
}
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an Analyzer for the NVD VULNERABLE_CPE Index.
|
||||
*
|
||||
@@ -165,8 +193,14 @@ public class Index extends AbstractIndex implements CachedWebDataSource {
|
||||
*
|
||||
* @param timeStamp the timestamp to write.
|
||||
*/
|
||||
private void writeLastUpdatedPropertyFile(Map<String, NvdCveUrl> updated) {
|
||||
String dir = Settings.getString(Settings.KEYS.CVE_INDEX);
|
||||
private void writeLastUpdatedPropertyFile(Map<String, NvdCveUrl> updated) throws UpdateException {
|
||||
String dir;
|
||||
try {
|
||||
dir = getDataDirectory().getCanonicalPath();
|
||||
} catch (IOException ex) {
|
||||
Logger.getLogger(Index.class.getName()).log(Level.SEVERE, null, ex);
|
||||
throw new UpdateException("Unable to locate last updated properties file.", ex);
|
||||
}
|
||||
File cveProp = new File(dir + File.separatorChar + UPDATE_PROPERTIES_FILE);
|
||||
Properties prop = new Properties();
|
||||
|
||||
@@ -181,8 +215,10 @@ public class Index extends AbstractIndex implements CachedWebDataSource {
|
||||
prop.store(out, dir);
|
||||
} catch (FileNotFoundException ex) {
|
||||
Logger.getLogger(Index.class.getName()).log(Level.SEVERE, null, ex);
|
||||
throw new UpdateException("Unable to find last updated properties file.", ex);
|
||||
} catch (IOException ex) {
|
||||
Logger.getLogger(Index.class.getName()).log(Level.SEVERE, null, ex);
|
||||
throw new UpdateException("Unable to update last updated properties file.", ex);
|
||||
} finally {
|
||||
try {
|
||||
os.flush();
|
||||
@@ -206,10 +242,11 @@ public class Index extends AbstractIndex implements CachedWebDataSource {
|
||||
* @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
|
||||
* @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.
|
||||
*/
|
||||
public Map<String, NvdCveUrl> updateNeeded() throws MalformedURLException, DownloadFailedException {
|
||||
public Map<String, NvdCveUrl> updateNeeded() throws MalformedURLException, DownloadFailedException, UpdateException {
|
||||
|
||||
Map<String, NvdCveUrl> currentlyPublished;
|
||||
try {
|
||||
@@ -221,7 +258,14 @@ public class Index extends AbstractIndex implements CachedWebDataSource {
|
||||
if (currentlyPublished == null) {
|
||||
throw new DownloadFailedException("Unable to retrieve valid timestamp from nvd cve downloads page");
|
||||
}
|
||||
String dir = Settings.getString(Settings.KEYS.CVE_INDEX);
|
||||
String dir;
|
||||
try {
|
||||
dir = getDataDirectory().getCanonicalPath();
|
||||
} catch (IOException ex) {
|
||||
Logger.getLogger(Index.class.getName()).log(Level.SEVERE, null, ex);
|
||||
throw new UpdateException("Unable to locate last updated properties file.", ex);
|
||||
}
|
||||
|
||||
File f = new File(dir);
|
||||
if (f.exists()) {
|
||||
File cveProp = new File(dir + File.separatorChar + UPDATE_PROPERTIES_FILE);
|
||||
|
||||
@@ -43,15 +43,17 @@ public class Importer {
|
||||
*/
|
||||
public static void importXML(File file) {
|
||||
NvdCveParser indexer = null;
|
||||
org.codesecure.dependencycheck.data.cpe.xml.Indexer cpeIndexer = null;
|
||||
try {
|
||||
|
||||
indexer = new NvdCveParser();
|
||||
|
||||
indexer.openIndexWriter();
|
||||
|
||||
//HACK - hack to ensure all CPE data is stored in the index.
|
||||
cpeIndexer = new org.codesecure.dependencycheck.data.cpe.xml.Indexer();
|
||||
cpeIndexer.openIndexWriter();
|
||||
indexer.setCPEIndexer(cpeIndexer);
|
||||
|
||||
indexer.parse(file);
|
||||
|
||||
} catch (CorruptIndexException ex) {
|
||||
Logger.getLogger(Importer.class.getName()).log(Level.SEVERE, null, ex);
|
||||
} catch (IOException ex) {
|
||||
@@ -60,6 +62,9 @@ public class Importer {
|
||||
if (indexer != null) {
|
||||
indexer.close();
|
||||
}
|
||||
if (cpeIndexer != null) {
|
||||
cpeIndexer.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
// public static void importXML(File file) throws FileNotFoundException, IOException, JAXBException,
|
||||
|
||||
@@ -23,14 +23,17 @@ import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import org.apache.lucene.document.Document;
|
||||
import org.apache.lucene.document.Field;
|
||||
import org.apache.lucene.index.CorruptIndexException;
|
||||
import org.apache.lucene.index.FieldInfo.IndexOptions;
|
||||
import org.apache.lucene.index.Term;
|
||||
import org.codesecure.dependencycheck.data.cpe.Entry;
|
||||
import org.codesecure.dependencycheck.data.nvdcve.Fields;
|
||||
import org.codesecure.dependencycheck.data.nvdcve.Index;
|
||||
|
||||
@@ -40,6 +43,19 @@ import org.codesecure.dependencycheck.data.nvdcve.Index;
|
||||
*/
|
||||
public class NvdCveParser extends Index {
|
||||
|
||||
//HACK - this has initially been placed here as a hack because not all
|
||||
// of the CPEs listed in the NVD CVE are actually in the CPE xml file
|
||||
// hosted by NIST.
|
||||
private org.codesecure.dependencycheck.data.cpe.xml.Indexer cpeIndexer = null;
|
||||
|
||||
/**
|
||||
* Adds the CPE Index to add additional CPEs found by parsing the NVD CVE.
|
||||
* @param indexer the CPE Indexer to write new CPEs into.
|
||||
*/
|
||||
public void setCPEIndexer(org.codesecure.dependencycheck.data.cpe.xml.Indexer indexer) {
|
||||
this.cpeIndexer = indexer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses an NVD CVE xml file using a buffered readerd. This
|
||||
* method maybe more fragile then using a partial-unmarshalling SAX
|
||||
@@ -164,10 +180,27 @@ public class NvdCveParser extends Index {
|
||||
* Adds a CPE to the Lucene Document
|
||||
* @param cpe a string representing a CPE
|
||||
* @param doc a lucene document
|
||||
* @throws CorruptIndexException is thrown if the CPE Index is corrupt
|
||||
* @throws IOException is thrown if there is an IO Exception while writting to the CPE Index
|
||||
*/
|
||||
private void addVulnerableCpe(String cpe, Document doc) {
|
||||
private void addVulnerableCpe(String cpe, Document doc) throws CorruptIndexException, IOException {
|
||||
Field vulnerable = new Field(Fields.VULNERABLE_CPE, cpe, Field.Store.NO, Field.Index.ANALYZED);
|
||||
vulnerable.setIndexOptions(IndexOptions.DOCS_ONLY);
|
||||
doc.add(vulnerable);
|
||||
|
||||
//HACK - this has initially been placed here as a hack because not all
|
||||
// of the CPEs listed in the NVD CVE are actually in the CPE xml file
|
||||
// hosted by NIST.
|
||||
Entry cpeEntry = new Entry();
|
||||
try {
|
||||
cpeEntry.parseName(cpe);
|
||||
cpeEntry.setNvdId("0");
|
||||
cpeEntry.setTitle(cpe);
|
||||
} catch (UnsupportedEncodingException ex) {
|
||||
Logger.getLogger(NvdCveParser.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
if (cpeIndexer != null) {
|
||||
cpeIndexer.saveEntry(cpeEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,7 +184,7 @@ public class EvidenceCollection implements Iterable<Evidence> {
|
||||
text = text.toLowerCase();
|
||||
|
||||
for (Evidence e : this.list) {
|
||||
if (e.used && e.value.contains(text)) {
|
||||
if (e.used && e.value.toLowerCase().contains(text)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,15 +18,15 @@ package org.codesecure.dependencycheck.reporting;
|
||||
* Copyright (c) 2012 Jeremy Long. All Rights Reserved.
|
||||
*/
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import org.apache.velocity.app.VelocityEngine;
|
||||
@@ -35,66 +35,110 @@ import org.apache.velocity.runtime.RuntimeConstants;
|
||||
import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;
|
||||
import org.apache.velocity.tools.ToolManager;
|
||||
import org.apache.velocity.tools.config.EasyFactoryConfiguration;
|
||||
import org.codesecure.dependencycheck.analyzer.Analyzer;
|
||||
import org.codesecure.dependencycheck.dependency.Dependency;
|
||||
|
||||
/**
|
||||
* The ReportGenerator is used to, as the name implies, generate reports. Internally
|
||||
* the generator uses the Velocity Templating Engine. The ReportGenerator exposes
|
||||
* a list of Dependencies to the template when generating the report.
|
||||
*
|
||||
* @author Jeremy Long (jeremy.long@gmail.com)
|
||||
*/
|
||||
public class ReportGenerator {
|
||||
|
||||
/**
|
||||
* The Velocity Engine.
|
||||
*/
|
||||
private VelocityEngine engine = null;
|
||||
/**
|
||||
* The Velocity Engine Context.
|
||||
*/
|
||||
private Context context = null;
|
||||
|
||||
/**
|
||||
* Constructs a new ReportGenerator.
|
||||
*
|
||||
* @param applicationName the application name being analyzed
|
||||
* @param dependencies the list of dependencies
|
||||
* @param analyzers the list of analyzers used.
|
||||
*/
|
||||
public ReportGenerator(String applicationName, List<Dependency> dependencies, List<Analyzer> analyzers) {
|
||||
engine = createVelocityEngine();
|
||||
context = createContext();
|
||||
|
||||
engine.init();
|
||||
|
||||
context.put("applicationName", applicationName);
|
||||
context.put("dependencies", dependencies);
|
||||
context.put("analyzers", analyzers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Velocity Engine.
|
||||
* @return a velocity engine.
|
||||
*/
|
||||
private VelocityEngine createVelocityEngine() {
|
||||
VelocityEngine ve = new VelocityEngine();
|
||||
ve.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath");
|
||||
ve.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName());
|
||||
return ve;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new Velocity Context initialized with escape and date tools.
|
||||
* @return a Velcotiy Context.
|
||||
*/
|
||||
private Context createContext() {
|
||||
ToolManager manager = new ToolManager();
|
||||
Context c = manager.createContext();
|
||||
EasyFactoryConfiguration config = new EasyFactoryConfiguration();
|
||||
config.addDefaultTools();
|
||||
config.toolbox("application")
|
||||
.tool("esc", "org.apache.velocity.tools.generic.EscapeTool")
|
||||
.tool("org.apache.velocity.tools.generic.DateTool");
|
||||
manager.configure(config);
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the Dependency Reports for the identified dependencies.
|
||||
*
|
||||
* @param outputDir the path where the reports should be written.
|
||||
* @param applicationName the name of the application that was scanned.
|
||||
* @param dependencies a list of dependencies to include in the report.
|
||||
* @throws IOException is thrown when the template file does not exist.
|
||||
* @throws Exception is thrown if there is an error writting out the
|
||||
* reports.
|
||||
*/
|
||||
public void generateReports(String outputDir, String applicationName, List<Dependency> dependencies) throws IOException, Exception {
|
||||
|
||||
Map<String, Object> properties = new HashMap<String, Object>();
|
||||
properties.put("dependencies", dependencies);
|
||||
properties.put("applicationName", applicationName);
|
||||
|
||||
String reportName = applicationName.replaceAll("[^a-zA-Z0-9-_ \\.]+", "");
|
||||
String filename = outputDir + File.separatorChar + reportName;
|
||||
generateReport("HtmlReport", filename + ".html", properties);
|
||||
//generateReport("XmlReport",filename + ".xml",properties);
|
||||
|
||||
public void generateReports(String outputDir) throws IOException, Exception {
|
||||
generateReport("HtmlReport", outputDir + File.separator + "DependencyCheck-Report.html");
|
||||
//generateReport("XmlReport", outputDir + File.separator + "DependencyCheck-Report.xml");
|
||||
}
|
||||
|
||||
/**
|
||||
* much of this code is from
|
||||
* http://stackoverflow.com/questions/2931516/loading-velocity-template-inside-a-jar-file
|
||||
* Generates a report from a given Velocity Template. The template name
|
||||
* provided can be the name of a template contained in the jar file, such as
|
||||
* 'XmlReport' or 'HtmlReport', or the template name can be the path to a template file.
|
||||
*
|
||||
* @param templateName the name of the template to load.
|
||||
* @param outFileName The filename and path to write the report to.
|
||||
* @param properties a map of properties to load into the velocity context.
|
||||
* @param outFileName the filename and path to write the report to.
|
||||
* @throws IOException is thrown when the template file does not exist.
|
||||
* @throws Exception is thrown when an exception occurs.
|
||||
*/
|
||||
protected void generateReport(String templateName, String outFileName,
|
||||
Map<String, Object> properties) throws IOException, Exception {
|
||||
|
||||
VelocityEngine ve = new VelocityEngine();
|
||||
ve.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath");
|
||||
ve.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName());
|
||||
|
||||
ToolManager manager = new ToolManager();
|
||||
Context context = manager.createContext();
|
||||
EasyFactoryConfiguration config = new EasyFactoryConfiguration();
|
||||
config.addDefaultTools();
|
||||
config.toolbox("application").tool("esc", "org.apache.velocity.tools.generic.EscapeTool").tool("org.apache.velocity.tools.generic.DateTool");
|
||||
|
||||
manager.configure(config);
|
||||
|
||||
ve.init();
|
||||
|
||||
final String templatePath = "templates/" + templateName + ".vsl";
|
||||
InputStream input = this.getClass().getClassLoader().getResourceAsStream(templatePath);
|
||||
public void generateReport(String templateName, String outFileName) throws IOException, Exception {
|
||||
InputStream input = null;
|
||||
String templatePath = null;
|
||||
File f = new File(templateName);
|
||||
if (f.exists() && f.isFile()) {
|
||||
try {
|
||||
templatePath = templateName;
|
||||
input = new FileInputStream(f);
|
||||
} catch (FileNotFoundException ex) {
|
||||
Logger.getLogger(ReportGenerator.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
} else {
|
||||
templatePath = "templates/" + templateName + ".vsl";
|
||||
input = this.getClass().getClassLoader().getResourceAsStream(templatePath);
|
||||
}
|
||||
if (input == null) {
|
||||
throw new IOException("Template file doesn't exist");
|
||||
}
|
||||
@@ -102,19 +146,10 @@ public class ReportGenerator {
|
||||
InputStreamReader reader = new InputStreamReader(input);
|
||||
BufferedWriter writer = null;
|
||||
|
||||
//VelocityContext context = new VelocityContext();
|
||||
|
||||
//load the data into the context
|
||||
if (properties != null) {
|
||||
for (Map.Entry<String, Object> property : properties.entrySet()) {
|
||||
context.put(property.getKey(), property.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
writer = new BufferedWriter(new FileWriter(new File(outFileName)));
|
||||
|
||||
if (!ve.evaluate(context, writer, templatePath, reader)) {
|
||||
if (!engine.evaluate(context, writer, templatePath, reader)) {
|
||||
throw new Exception("Failed to convert the template into html.");
|
||||
}
|
||||
writer.flush();
|
||||
|
||||
@@ -93,17 +93,20 @@ public final class CliParser {
|
||||
validatePathExists(getScanFiles());
|
||||
if (!line.hasOption(ArgumentName.OUT)) {
|
||||
//TODO - need a new exception type here, this isn't really a parseexception.
|
||||
throw new ParseException("Scan cannot be run without specifying a directory to write the reports to via the 'out' argument.");
|
||||
throw new ParseException("Scan cannot be run without specifying a directory "
|
||||
+ "to write the reports to via the 'out' argument.");
|
||||
} else {
|
||||
String p = line.getOptionValue(ArgumentName.OUT, "");
|
||||
File f = new File(p);
|
||||
if ("".equals(p) || !(f.exists() && f.isDirectory())) {
|
||||
//TODO - need a new exception type here, this isn't really a parseexception.
|
||||
throw new ParseException("A valid directory name must be specified for the 'out' argument.");
|
||||
throw new ParseException("A valid directory name must be specified for "
|
||||
+ "the 'out' argument.");
|
||||
}
|
||||
}
|
||||
if (!line.hasOption(ArgumentName.APPNAME)) {
|
||||
throw new ParseException("Scan cannot be run without specifying an application name via the 'app' argument.");
|
||||
throw new ParseException("Scan cannot be run without specifying an application "
|
||||
+ "name via the 'app' argument.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -160,15 +163,25 @@ public final class CliParser {
|
||||
Option noupdate = new Option(ArgumentName.DISABLE_AUTO_UPDATE_SHORT, ArgumentName.DISABLE_AUTO_UPDATE,
|
||||
false, "disables the automatic updating of the CPE data.");
|
||||
|
||||
Option appname = OptionBuilder.withArgName("name").hasArg().withLongOpt(ArgumentName.APPNAME).withDescription("the name of the application being scanned.").create(ArgumentName.APPNAME_SHORT);
|
||||
Option appname = OptionBuilder.withArgName("name").hasArg().withLongOpt(ArgumentName.APPNAME)
|
||||
.withDescription("the name of the application being scanned.")
|
||||
.create(ArgumentName.APPNAME_SHORT);
|
||||
|
||||
Option path = OptionBuilder.withArgName("path").hasArg().withLongOpt(ArgumentName.SCAN).withDescription("the path to scan - this option can be specified multiple times.").create(ArgumentName.SCAN_SHORT);
|
||||
Option path = OptionBuilder.withArgName("path").hasArg().withLongOpt(ArgumentName.SCAN)
|
||||
.withDescription("the path to scan - this option can be specified multiple times.")
|
||||
.create(ArgumentName.SCAN_SHORT);
|
||||
|
||||
Option load = OptionBuilder.withArgName("file").hasArg().withLongOpt(ArgumentName.CPE).withDescription("load the CPE xml file.").create(ArgumentName.CPE_SHORT);
|
||||
Option load = OptionBuilder.withArgName("file").hasArg().withLongOpt(ArgumentName.CPE)
|
||||
.withDescription("load the CPE xml file.")
|
||||
.create(ArgumentName.CPE_SHORT);
|
||||
|
||||
Option props = OptionBuilder.withArgName("file").hasArg().withLongOpt(ArgumentName.PROP).withDescription("a property file to load.").create(ArgumentName.PROP_SHORT);
|
||||
Option props = OptionBuilder.withArgName("file").hasArg().withLongOpt(ArgumentName.PROP)
|
||||
.withDescription("a property file to load.")
|
||||
.create(ArgumentName.PROP_SHORT);
|
||||
|
||||
Option out = OptionBuilder.withArgName("folder").hasArg().withLongOpt(ArgumentName.OUT).withDescription("the folder to write reports to.").create(ArgumentName.OUT_SHORT);
|
||||
Option out = OptionBuilder.withArgName("folder").hasArg().withLongOpt(ArgumentName.OUT)
|
||||
.withDescription("the folder to write reports to.")
|
||||
.create(ArgumentName.OUT_SHORT);
|
||||
|
||||
//TODO add the ability to load a properties file to override the defaults...
|
||||
|
||||
@@ -237,7 +250,8 @@ public final class CliParser {
|
||||
+ "using the -p <file> argument or by passing them in as system properties." + nl
|
||||
+ nl + " " + Settings.KEYS.PROXY_URL + "\t\t the proxy URL to use when downloading resources."
|
||||
+ nl + " " + Settings.KEYS.PROXY_PORT + "\t\t the proxy port to use when downloading resources."
|
||||
+ nl + " " + Settings.KEYS.CONNECTION_TIMEOUT + "\t the cconnection timeout (in milliseconds) to use" + nl + "\t\t\t when downloading resources.";
|
||||
+ nl + " " + Settings.KEYS.CONNECTION_TIMEOUT + "\t the cconnection timeout (in milliseconds) to use"
|
||||
+ nl + "\t\t\t when downloading resources.";
|
||||
}
|
||||
|
||||
formatter.printHelp(Settings.getString("application.name", "DependencyCheck"),
|
||||
@@ -312,7 +326,7 @@ public final class CliParser {
|
||||
* @return if auto-update is allowed.
|
||||
*/
|
||||
public boolean isAutoUpdate() {
|
||||
return (line != null) ? !line.hasOption(ArgumentName.DISABLE_AUTO_UPDATE) : false;
|
||||
return (line != null) ? !line.hasOption(ArgumentName.DISABLE_AUTO_UPDATE) : true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -20,4 +20,4 @@ java.util.logging.FileHandler.level=FINEST
|
||||
# %g - generation number for rotating logs
|
||||
# %u - unique number to avoid conflicts
|
||||
# FileHandler writes to %h/demo0.log by default.
|
||||
java.util.logging.FileHandler.pattern=./logs/DependencyCheck%g.log
|
||||
java.util.logging.FileHandler.pattern=./logs/DependencyCheck%u.log
|
||||
@@ -34,7 +34,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
$(".expandablesubsection").click(function (e) {
|
||||
$(".expandable").click(function (e) {
|
||||
e = e || window.event;
|
||||
var h = e.target || e.srcElement;
|
||||
var content = "#content" + h.id.substr(6);
|
||||
@@ -64,7 +64,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.exandable {}
|
||||
.expandablesubsection {
|
||||
cursor: pointer;
|
||||
/*background-image: url(img/plus.gif);*/
|
||||
@@ -285,8 +285,12 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
|
||||
<div class="sectioncontent">Report Generated On: $date<br/><br/>
|
||||
Dependencies Scanned: $dependencies.size()<br/><br/>
|
||||
<div class="indent">
|
||||
#foreach($dependency in $dependencies)
|
||||
<a href="#$esc.html($esc.url($dependency.FilePath))">$esc.html($dependency.FileName)</a><br/>
|
||||
#foreach($dependency in $dependencies)
|
||||
#if($dependency.getVulnerabilities().size()>0)
|
||||
<a href="#$esc.html($esc.url($dependency.FilePath))">$esc.html($dependency.FileName)</a> <b style="color:#ff0000;">•</b><br/>
|
||||
#else
|
||||
<a href="#$esc.html($esc.url($dependency.FilePath))">$esc.html($dependency.FileName)</a><br/>
|
||||
#end
|
||||
#end
|
||||
</div>
|
||||
<h2>Dependencies</h2>
|
||||
@@ -308,7 +312,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
|
||||
|
||||
#if ( $dependency.analysisExceptions.size() != 0 )
|
||||
#set($cnt=$cnt+1)
|
||||
<h4 id="header$cnt" class="subsectionheader expandablesubsection red">Exceptions Occured During Analysis</h4>
|
||||
<h4 id="header$cnt" class="subsectionheader expandable expandablesubsection red">Exceptions Occured During Analysis</h4>
|
||||
<div id="content$cnt" class="subsectioncontent standardsubsection hidden">
|
||||
<ul>
|
||||
#foreach($ex in $dependency.analysisExceptions)
|
||||
@@ -336,7 +340,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
|
||||
</div>
|
||||
#end
|
||||
#set($cnt=$cnt+1)
|
||||
<h4 id="header$cnt" class="subsectionheader expandablesubsection white">Evidence</h4>
|
||||
<h4 id="header$cnt" class="subsectionheader expandable expandablesubsection white">Evidence</h4>
|
||||
<div id="content$cnt" class="subsectioncontent standardsubsection hidden">
|
||||
<table class="lined fullwidth" border="0">
|
||||
<tr><th class="left" style="width:10%;">Source</th><th class="left" style="width:20%;">Name</th><th class="left" style="width:70%;">Value</th></tr>
|
||||
@@ -377,7 +381,7 @@ Copyright (c) 2012 Jeremy Long. All Rights Reserved.
|
||||
</div>
|
||||
#if($dependency.getVulnerabilities().size()>0)
|
||||
#set($cnt=$cnt+1)
|
||||
<h4 id="header$cnt" class="subsectionheader white">Published Vulnerabilities</h4>
|
||||
<h4 id="header$cnt" class="subsectionheader expandable collaspablesubsection white">Published Vulnerabilities</h4>
|
||||
<div id="content$cnt" class="subsectioncontent standardsubsection">
|
||||
#foreach($vuln in $dependency.getVulnerabilities())
|
||||
<p><b><a target="_blank" href="http://web.nvd.nist.gov/view/vuln/detail?vulnId=$esc.url($vuln.name)">$esc.html($vuln.name)</a></b></p>
|
||||
|
||||
@@ -6,4 +6,4 @@
|
||||
<body>
|
||||
<menu ref="reports" />
|
||||
</body>
|
||||
</project>
|
||||
</project>
|
||||
@@ -51,7 +51,8 @@ public class EngineIntegrationTest {
|
||||
instance.scan(path);
|
||||
assertTrue(instance.getDependencies().size() > 0);
|
||||
instance.analyzeDependencies();
|
||||
ReportGenerator rg = new ReportGenerator();
|
||||
rg.generateReports("./target/", "DependencyCheck", instance.getDependencies());
|
||||
ReportGenerator rg = new ReportGenerator("DependencyCheck",
|
||||
instance.getDependencies(), instance.getAnalyzers());
|
||||
rg.generateReports("./target/");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,7 +63,8 @@ public class JarAnalyzerTest {
|
||||
instance.analyze(result);
|
||||
boolean found = false;
|
||||
for (Evidence e : result.getProductEvidence()) {
|
||||
if (e.getName().equals("package-title") && e.getValue().equals("org.mortbay.http")) {
|
||||
if (e.getName().equalsIgnoreCase("package-title")
|
||||
&& e.getValue().equalsIgnoreCase("org.mortbay.http")) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
@@ -72,7 +73,8 @@ public class JarAnalyzerTest {
|
||||
|
||||
found = false;
|
||||
for (Evidence e : result.getVendorEvidence()) {
|
||||
if (e.getName().equals("implementation-url") && e.getValue().equals("http://jetty.mortbay.org")) {
|
||||
if (e.getName().equalsIgnoreCase("implementation-url")
|
||||
&& e.getValue().equalsIgnoreCase("http://jetty.mortbay.org")) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
@@ -81,7 +83,8 @@ public class JarAnalyzerTest {
|
||||
|
||||
found = false;
|
||||
for (Evidence e : result.getVersionEvidence()) {
|
||||
if (e.getName().equals("Implementation-Version") && e.getValue().equals("4.2.27")) {
|
||||
if (e.getName().equalsIgnoreCase("Implementation-Version")
|
||||
&& e.getValue().equalsIgnoreCase("4.2.27")) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -9,6 +9,8 @@ import java.io.BufferedOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.URLDecoder;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
import junit.framework.TestCase;
|
||||
@@ -30,8 +32,24 @@ public abstract class BaseIndexTestCase extends TestCase {
|
||||
ensureIndexExists();
|
||||
}
|
||||
|
||||
protected static File getDataDirectory() throws IOException {
|
||||
String fileName = Settings.getString(Settings.KEYS.CPE_INDEX);
|
||||
String filePath = Index.class.getProtectionDomain().getCodeSource().getLocation().getPath();
|
||||
String decodedPath = URLDecoder.decode(filePath, "UTF-8");
|
||||
File exePath = new File(decodedPath);
|
||||
if (exePath.getName().toLowerCase().endsWith(".jar")) {
|
||||
exePath = exePath.getParentFile();
|
||||
} else {
|
||||
exePath = new File(".");
|
||||
}
|
||||
File path = new File(exePath.getCanonicalFile() + File.separator + fileName);
|
||||
path = new File(path.getCanonicalPath());
|
||||
return path;
|
||||
}
|
||||
|
||||
public static void ensureIndexExists() throws Exception {
|
||||
String indexPath = Settings.getString(Settings.KEYS.CPE_INDEX);
|
||||
//String indexPath = Settings.getString(Settings.KEYS.CPE_INDEX);
|
||||
String indexPath = getDataDirectory().getCanonicalPath();
|
||||
java.io.File f = new File(indexPath);
|
||||
if (!f.exists()) {
|
||||
f.mkdirs();
|
||||
|
||||
@@ -13,8 +13,6 @@ import org.apache.lucene.index.CorruptIndexException;
|
||||
import org.apache.lucene.queryParser.ParseException;
|
||||
import org.codesecure.dependencycheck.dependency.Dependency;
|
||||
import org.codesecure.dependencycheck.analyzer.JarAnalyzer;
|
||||
import org.codesecure.dependencycheck.dependency.Evidence;
|
||||
import org.codesecure.dependencycheck.dependency.Evidence.Confidence;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
@@ -100,11 +98,16 @@ public class CPEAnalyzerTest extends BaseIndexTestCase {
|
||||
JarAnalyzer jarAnalyzer = new JarAnalyzer();
|
||||
Dependency depends = new Dependency(file);
|
||||
jarAnalyzer.analyze(depends);
|
||||
|
||||
|
||||
File fileSpring = new File(this.getClass().getClassLoader().getResource("spring-core-2.5.5.jar").getPath());
|
||||
Dependency spring = new Dependency(fileSpring);
|
||||
jarAnalyzer.analyze(spring);
|
||||
|
||||
CPEAnalyzer instance = new CPEAnalyzer();
|
||||
instance.open();
|
||||
String expResult = "cpe:/a:apache:struts:2.1.2";
|
||||
instance.determineCPE(depends);
|
||||
instance.determineCPE(spring);
|
||||
instance.close();
|
||||
assertTrue("Incorrect match", depends.getIdentifiers().size() == 1);
|
||||
assertTrue("Incorrect match", depends.getIdentifiers().get(0).getValue().equals(expResult));
|
||||
@@ -133,6 +136,7 @@ public class CPEAnalyzerTest extends BaseIndexTestCase {
|
||||
expResult = "cpe:/a:apache:struts:2.3.1.2";
|
||||
result = instance.searchCPE(vendor, product, version);
|
||||
assertEquals(expResult, result.get(0).getName());
|
||||
|
||||
instance.close();
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ public class EntryTest extends TestCase {
|
||||
String name = "cpe:/a:apache:struts:1.1:rc2";
|
||||
|
||||
Entry instance = new Entry();
|
||||
instance.setName(name);
|
||||
instance.parseName(name);
|
||||
|
||||
assertEquals(name,instance.getName());
|
||||
assertEquals("apache", instance.getVendor());
|
||||
|
||||
@@ -40,35 +40,6 @@ public class IndexIntegrationTest extends BaseIndexTestCase {
|
||||
public void tearDown() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of open method, of class Index.
|
||||
*/
|
||||
@Test
|
||||
public void testOpen() {
|
||||
System.out.println("open");
|
||||
Index instance = new Index();
|
||||
try {
|
||||
instance.open();
|
||||
} catch (IOException ex) {
|
||||
fail(ex.getMessage());
|
||||
}
|
||||
instance.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of getDirectory method, of class Index.
|
||||
*/
|
||||
@Test
|
||||
public void testGetDirectory() throws Exception {
|
||||
System.out.println("getDirectory");
|
||||
Index index = new Index();
|
||||
Directory result = index.getDirectory();
|
||||
|
||||
String exp = File.separatorChar + "target" + File.separatorChar + "data" + File.separatorChar + "cpe";
|
||||
// TODO review the generated test code and remove the default call to fail.
|
||||
assertTrue(result.toString().contains(exp));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of update method, of class Index.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.codesecure.dependencycheck.data.cpe;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import org.apache.lucene.store.Directory;
|
||||
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@gmail.com)
|
||||
*/
|
||||
public class IndexTest extends BaseIndexTestCase {
|
||||
|
||||
public IndexTest(String testCase) {
|
||||
super(testCase);
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpClass() throws Exception {
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void tearDownClass() throws Exception {
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of open method, of class Index.
|
||||
*/
|
||||
@Test
|
||||
public void testOpen() {
|
||||
System.out.println("open");
|
||||
Index instance = new Index();
|
||||
try {
|
||||
instance.open();
|
||||
} catch (IOException ex) {
|
||||
fail(ex.getMessage());
|
||||
}
|
||||
instance.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of getDirectory method, of class Index.
|
||||
*/
|
||||
@Test
|
||||
public void testGetDirectory() throws Exception {
|
||||
System.out.println("getDirectory");
|
||||
Index index = new Index();
|
||||
Directory result = index.getDirectory();
|
||||
|
||||
String exp = File.separatorChar + "target" + File.separatorChar + "data" + File.separatorChar + "cpe";
|
||||
// TODO review the generated test code and remove the default call to fail.
|
||||
assertTrue(result.toString().contains(exp));
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,8 @@ import java.io.BufferedOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.URLDecoder;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
import junit.framework.TestCase;
|
||||
@@ -31,8 +33,25 @@ public abstract class BaseIndexTestCase extends TestCase {
|
||||
ensureIndexExists();
|
||||
}
|
||||
|
||||
|
||||
protected static File getDataDirectory() throws IOException {
|
||||
String fileName = Settings.getString(Settings.KEYS.CVE_INDEX);
|
||||
String filePath = Index.class.getProtectionDomain().getCodeSource().getLocation().getPath();
|
||||
String decodedPath = URLDecoder.decode(filePath, "UTF-8");
|
||||
File exePath = new File(decodedPath);
|
||||
if (exePath.getName().toLowerCase().endsWith(".jar")) {
|
||||
exePath = exePath.getParentFile();
|
||||
} else {
|
||||
exePath = new File( "." );
|
||||
}
|
||||
File path = new File(exePath.getCanonicalFile() + File.separator + fileName);
|
||||
path = new File(path.getCanonicalPath());
|
||||
return path;
|
||||
}
|
||||
|
||||
public static void ensureIndexExists() throws Exception {
|
||||
String indexPath = Settings.getString(Settings.KEYS.CVE_INDEX);
|
||||
//String indexPath = Settings.getString(Settings.KEYS.CVE_INDEX);
|
||||
String indexPath = getDataDirectory().getCanonicalPath();
|
||||
java.io.File f = new File(indexPath);
|
||||
if (!f.exists()) {
|
||||
f.mkdirs();
|
||||
|
||||
@@ -4,11 +4,8 @@
|
||||
*/
|
||||
package org.codesecure.dependencycheck.data.nvdcve;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import java.util.Map;
|
||||
import org.apache.lucene.store.Directory;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import org.junit.*;
|
||||
|
||||
/**
|
||||
@@ -16,7 +13,7 @@ import org.junit.*;
|
||||
* @author Jeremy
|
||||
*/
|
||||
public class IndexIntegrationTest extends BaseIndexTestCase {
|
||||
|
||||
|
||||
public IndexIntegrationTest(String testName) {
|
||||
super(testName);
|
||||
}
|
||||
@@ -28,11 +25,11 @@ public class IndexIntegrationTest extends BaseIndexTestCase {
|
||||
@AfterClass
|
||||
public static void tearDownClass() throws Exception {
|
||||
}
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
}
|
||||
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
}
|
||||
@@ -45,19 +42,7 @@ public class IndexIntegrationTest extends BaseIndexTestCase {
|
||||
System.out.println("retrieveCurrentTimestampFromWeb");
|
||||
Index instance = new Index();
|
||||
Map<String, Index.NvdCveUrl> result = instance.retrieveCurrentTimestampsFromWeb();
|
||||
assertEquals(12, result.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of getDirectory method, of class Index.
|
||||
*/
|
||||
@Test
|
||||
public void testGetDirectory() throws Exception {
|
||||
System.out.println("getDirectory");
|
||||
Index instance = new Index();
|
||||
String exp = File.separatorChar + "target" + File.separatorChar + "data" + File.separatorChar + "cve";
|
||||
Directory result = instance.getDirectory();
|
||||
assertTrue(result.toString().contains(exp));
|
||||
assertEquals(12, result.size());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -81,5 +66,4 @@ public class IndexIntegrationTest extends BaseIndexTestCase {
|
||||
//if an exception is thrown this test fails. However, because it depends on the
|
||||
// order of the tests what this will return I am just testing for the exception.
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.codesecure.dependencycheck.data.nvdcve;
|
||||
|
||||
import java.io.File;
|
||||
import org.apache.lucene.store.Directory;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import org.junit.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Jeremy
|
||||
*/
|
||||
public class IndexTest extends BaseIndexTestCase {
|
||||
|
||||
public IndexTest(String testName) {
|
||||
super(testName);
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpClass() throws Exception {
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void tearDownClass() throws Exception {
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test of getDirectory method, of class Index.
|
||||
*/
|
||||
@Test
|
||||
public void testGetDirectory() throws Exception {
|
||||
System.out.println("getDirectory");
|
||||
Index instance = new Index();
|
||||
String exp = File.separatorChar + "target" + File.separatorChar + "data" + File.separatorChar + "cve";
|
||||
Directory result = instance.getDirectory();
|
||||
|
||||
assertTrue(result.toString().contains(exp));
|
||||
}
|
||||
}
|
||||
BIN
src/test/resources/spring-core-2.5.5.jar
Normal file
BIN
src/test/resources/spring-core-2.5.5.jar
Normal file
Binary file not shown.
Reference in New Issue
Block a user