mirror of
https://github.com/ysoftdevs/DependencyCheck.git
synced 2026-03-31 14:13:29 +02:00
bug fixes/enhancements
This commit is contained in:
6
README
6
README
@@ -4,9 +4,11 @@ Common Product Enumeration (CPE) identifier for a given project dependency.
|
|||||||
If found, it will generate a report linking to the associated CVE entries.
|
If found, it will generate a report linking to the associated CVE entries.
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
Still under development: mvn package site
|
$ mvn package
|
||||||
|
$ cd target
|
||||||
|
$ java -jar dependencycheck-0.1.jar -h
|
||||||
|
$ java -jar DependencyCheck-0.1.jar -a Testing -out . -scan ./test-classes/org.mortbay.jetty.jar -scan struts2-core-2.1.2.jar -scan ./lib
|
||||||
|
|
||||||
java -jar dependencycheck-0.1.jar -h
|
|
||||||
|
|
||||||
TODO:
|
TODO:
|
||||||
Add CVE download/indexing and CPE lookup.
|
Add CVE download/indexing and CPE lookup.
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ package org.codesecure.dependencycheck.data.cpe;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.StringTokenizer;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
import org.apache.lucene.analysis.Analyzer;
|
import org.apache.lucene.analysis.Analyzer;
|
||||||
@@ -37,7 +39,9 @@ import org.apache.lucene.store.Directory;
|
|||||||
import org.apache.lucene.util.Version;
|
import org.apache.lucene.util.Version;
|
||||||
import org.codesecure.dependencycheck.data.LuceneUtils;
|
import org.codesecure.dependencycheck.data.LuceneUtils;
|
||||||
import org.codesecure.dependencycheck.scanner.Dependency;
|
import org.codesecure.dependencycheck.scanner.Dependency;
|
||||||
|
import org.codesecure.dependencycheck.scanner.Evidence;
|
||||||
import org.codesecure.dependencycheck.scanner.Evidence.Confidence;
|
import org.codesecure.dependencycheck.scanner.Evidence.Confidence;
|
||||||
|
import org.codesecure.dependencycheck.scanner.EvidenceCollection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CPEQuery is a utility class that takes a project dependency and attempts
|
* CPEQuery is a utility class that takes a project dependency and attempts
|
||||||
@@ -60,7 +64,7 @@ public class CPEQuery {
|
|||||||
* A string representation of a regular expression defining characters
|
* A string representation of a regular expression defining characters
|
||||||
* utilized within the CPE Names.
|
* utilized within the CPE Names.
|
||||||
*/
|
*/
|
||||||
static final String CLEANSE_CHARACTER_RX = "[^A-Za-z0-9 _-]";
|
static final String CLEANSE_CHARACTER_RX = "[^A-Za-z0-9 ._-]";
|
||||||
/* A string representation of a regular expression used to remove all but
|
/* A string representation of a regular expression used to remove all but
|
||||||
* alpha characters.
|
* alpha characters.
|
||||||
*/
|
*/
|
||||||
@@ -166,22 +170,25 @@ public class CPEQuery {
|
|||||||
* @param dependency the dependency to search for CPE entries on.
|
* @param dependency the dependency to search for CPE entries on.
|
||||||
* @throws CorruptIndexException is thrown when the Lucene index is corrupt.
|
* @throws CorruptIndexException is thrown when the Lucene index is corrupt.
|
||||||
* @throws IOException is thrown when an IOException occurs.
|
* @throws IOException is thrown when an IOException occurs.
|
||||||
* @throws ParseException is thrown when the Lucene query cannot be parsed.
|
* @throws ParseException is thrown when the Lucene query cannot be parsed.
|
||||||
*/
|
*/
|
||||||
public void determineCPE(Dependency dependency) throws CorruptIndexException, IOException, ParseException {
|
public void determineCPE(Dependency dependency) throws CorruptIndexException, IOException, ParseException {
|
||||||
Confidence vendorConf = Confidence.HIGH;
|
Confidence vendorConf = Confidence.HIGH;
|
||||||
Confidence titleConf = Confidence.HIGH;
|
Confidence titleConf = Confidence.HIGH;
|
||||||
Confidence versionConf = Confidence.HIGH;
|
Confidence versionConf = Confidence.HIGH;
|
||||||
|
|
||||||
String vendors = dependency.getVendorEvidence().toString(vendorConf);
|
String vendors = addEvidenceWithoutDuplicateTerms("", dependency.getVendorEvidence(), vendorConf);
|
||||||
|
//dependency.getVendorEvidence().toString(vendorConf);
|
||||||
// if ("".equals(vendors)) {
|
// if ("".equals(vendors)) {
|
||||||
// vendors = STRING_THAT_WILL_NEVER_BE_IN_THE_INDEX;
|
// vendors = STRING_THAT_WILL_NEVER_BE_IN_THE_INDEX;
|
||||||
// }
|
// }
|
||||||
String titles = dependency.getTitleEvidence().toString(titleConf);
|
String titles = addEvidenceWithoutDuplicateTerms("", dependency.getTitleEvidence(), titleConf);
|
||||||
|
///dependency.getTitleEvidence().toString(titleConf);
|
||||||
// if ("".equals(titles)) {
|
// if ("".equals(titles)) {
|
||||||
// titles = STRING_THAT_WILL_NEVER_BE_IN_THE_INDEX;
|
// titles = STRING_THAT_WILL_NEVER_BE_IN_THE_INDEX;
|
||||||
// }
|
// }
|
||||||
String versions = dependency.getVersionEvidence().toString(versionConf);
|
String versions = addEvidenceWithoutDuplicateTerms("", dependency.getVersionEvidence(), versionConf);
|
||||||
|
//dependency.getVersionEvidence().toString(versionConf);
|
||||||
// if ("".equals(versions)) {
|
// if ("".equals(versions)) {
|
||||||
// versions = STRING_THAT_WILL_NEVER_BE_IN_THE_INDEX;
|
// versions = STRING_THAT_WILL_NEVER_BE_IN_THE_INDEX;
|
||||||
// }
|
// }
|
||||||
@@ -205,7 +212,8 @@ public class CPEQuery {
|
|||||||
if (round == 0) {
|
if (round == 0) {
|
||||||
vendorConf = reduceConfidence(vendorConf);
|
vendorConf = reduceConfidence(vendorConf);
|
||||||
if (dependency.getVendorEvidence().contains(vendorConf)) {
|
if (dependency.getVendorEvidence().contains(vendorConf)) {
|
||||||
vendors += " " + dependency.getVendorEvidence().toString(vendorConf);
|
//vendors += " " + dependency.getVendorEvidence().toString(vendorConf);
|
||||||
|
vendors = addEvidenceWithoutDuplicateTerms(vendors, dependency.getVendorEvidence(), vendorConf);
|
||||||
} else {
|
} else {
|
||||||
cnt += 1;
|
cnt += 1;
|
||||||
round += 1;
|
round += 1;
|
||||||
@@ -214,7 +222,8 @@ public class CPEQuery {
|
|||||||
if (round == 1) {
|
if (round == 1) {
|
||||||
titleConf = reduceConfidence(titleConf);
|
titleConf = reduceConfidence(titleConf);
|
||||||
if (dependency.getTitleEvidence().contains(titleConf)) {
|
if (dependency.getTitleEvidence().contains(titleConf)) {
|
||||||
titles += " " + dependency.getTitleEvidence().toString(titleConf);
|
//titles += " " + dependency.getTitleEvidence().toString(titleConf);
|
||||||
|
titles = addEvidenceWithoutDuplicateTerms(titles, dependency.getTitleEvidence(), titleConf);
|
||||||
} else {
|
} else {
|
||||||
cnt += 1;
|
cnt += 1;
|
||||||
round += 1;
|
round += 1;
|
||||||
@@ -223,7 +232,8 @@ public class CPEQuery {
|
|||||||
if (round == 2) {
|
if (round == 2) {
|
||||||
versionConf = reduceConfidence(versionConf);
|
versionConf = reduceConfidence(versionConf);
|
||||||
if (dependency.getVersionEvidence().contains(versionConf)) {
|
if (dependency.getVersionEvidence().contains(versionConf)) {
|
||||||
versions += " " + dependency.getVersionEvidence().toString(versionConf);
|
//versions += " " + dependency.getVersionEvidence().toString(versionConf);
|
||||||
|
versions = addEvidenceWithoutDuplicateTerms(versions, dependency.getVersionEvidence(), versionConf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -232,6 +242,33 @@ public class CPEQuery {
|
|||||||
} while (!found && (++cnt) < 9);
|
} while (!found && (++cnt) < 9);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the text created by concatonating the text and the values from the
|
||||||
|
* EvidenceCollection (filtered for a specific confidence). This attempts to
|
||||||
|
* prevent duplicate terms from being added.<br/<br/>
|
||||||
|
* Note, if the evidence is longer then 200 characters it will be truncated.
|
||||||
|
*
|
||||||
|
* @param text the base text.
|
||||||
|
* @param ec an EvidenceCollection
|
||||||
|
* @param confidenceFilter a Confidence level to filter the evidence by.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private String addEvidenceWithoutDuplicateTerms(final String text, final EvidenceCollection ec, Confidence confidenceFilter) {
|
||||||
|
String txt = (text == null) ? "" : text;
|
||||||
|
StringBuilder sb = new StringBuilder(txt.length() + (20 * ec.size()));
|
||||||
|
for (Evidence e : ec.iterator(confidenceFilter)) {
|
||||||
|
String value = e.getValue();
|
||||||
|
if (sb.indexOf(value)<0) {
|
||||||
|
if (value.length()>200) {
|
||||||
|
sb.append(value.substring(0,200));
|
||||||
|
} else {
|
||||||
|
sb.append(value).append(' ');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reduces the given confidence by one level. This returns LOW if the confidence
|
* Reduces the given confidence by one level. This returns LOW if the confidence
|
||||||
* passed in is not HIGH.
|
* passed in is not HIGH.
|
||||||
@@ -282,7 +319,7 @@ public class CPEQuery {
|
|||||||
* @throws ParseException when the generated query is not valid.
|
* @throws ParseException when the generated query is not valid.
|
||||||
*/
|
*/
|
||||||
protected List<Entry> searchCPE(String vendor, String product, String version,
|
protected List<Entry> searchCPE(String vendor, String product, String version,
|
||||||
List<String> vendorWeightings, List<String> productWeightings)
|
Set<String> vendorWeightings, Set<String> productWeightings)
|
||||||
throws CorruptIndexException, IOException, ParseException {
|
throws CorruptIndexException, IOException, ParseException {
|
||||||
ArrayList<Entry> ret = new ArrayList<Entry>(MAX_QUERY_RESULTS);
|
ArrayList<Entry> ret = new ArrayList<Entry>(MAX_QUERY_RESULTS);
|
||||||
|
|
||||||
@@ -319,7 +356,7 @@ public class CPEQuery {
|
|||||||
* @return the Lucene query.
|
* @return the Lucene query.
|
||||||
*/
|
*/
|
||||||
protected String buildSearch(String vendor, String product, String version,
|
protected String buildSearch(String vendor, String product, String version,
|
||||||
List<String> vendorWeighting, List<String> produdctWeightings) {
|
Set<String> vendorWeighting, Set<String> produdctWeightings) {
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder(vendor.length() + product.length()
|
StringBuilder sb = new StringBuilder(vendor.length() + product.length()
|
||||||
+ version.length() + Fields.PRODUCT.length() + Fields.VERSION.length()
|
+ version.length() + Fields.PRODUCT.length() + Fields.VERSION.length()
|
||||||
@@ -364,7 +401,7 @@ public class CPEQuery {
|
|||||||
* importance when searching.
|
* importance when searching.
|
||||||
* @return if the append was successful.
|
* @return if the append was successful.
|
||||||
*/
|
*/
|
||||||
private boolean appendWeightedSearch(StringBuilder sb, String field, String searchText, List<String> weightedText) {
|
private boolean appendWeightedSearch(StringBuilder sb, String field, String searchText, Set<String> weightedText) {
|
||||||
//TODO add a mutator or special analyzer that combines words next to each other and adds them as a key.
|
//TODO add a mutator or special analyzer that combines words next to each other and adds them as a key.
|
||||||
sb.append(" ").append(field).append(":( ");
|
sb.append(" ").append(field).append(":( ");
|
||||||
|
|
||||||
@@ -377,8 +414,9 @@ public class CPEQuery {
|
|||||||
if (weightedText == null || weightedText.isEmpty()) {
|
if (weightedText == null || weightedText.isEmpty()) {
|
||||||
LuceneUtils.appendEscapedLuceneQuery(sb, cleanText);
|
LuceneUtils.appendEscapedLuceneQuery(sb, cleanText);
|
||||||
} else {
|
} else {
|
||||||
String[] text = cleanText.split("\\s");
|
StringTokenizer tokens = new StringTokenizer(cleanText);
|
||||||
for (String word : text) {
|
while (tokens.hasMoreElements()) {
|
||||||
|
String word = tokens.nextToken();
|
||||||
String temp = null;
|
String temp = null;
|
||||||
for (String weighted : weightedText) {
|
for (String weighted : weightedText) {
|
||||||
String weightedStr = cleanseText(weighted);
|
String weightedStr = cleanseText(weighted);
|
||||||
|
|||||||
@@ -25,12 +25,14 @@ import java.io.FileOutputStream;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.io.OutputStreamWriter;
|
import java.io.OutputStreamWriter;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
import org.apache.lucene.analysis.Analyzer;
|
import org.apache.lucene.analysis.Analyzer;
|
||||||
import org.apache.lucene.analysis.KeywordAnalyzer;
|
import org.apache.lucene.analysis.KeywordAnalyzer;
|
||||||
import org.apache.lucene.analysis.PerFieldAnalyzerWrapper;
|
import org.apache.lucene.analysis.PerFieldAnalyzerWrapper;
|
||||||
@@ -44,8 +46,10 @@ import org.apache.lucene.util.Version;
|
|||||||
import org.codesecure.dependencycheck.utils.Downloader;
|
import org.codesecure.dependencycheck.utils.Downloader;
|
||||||
import org.codesecure.dependencycheck.utils.Settings;
|
import org.codesecure.dependencycheck.utils.Settings;
|
||||||
import org.codesecure.dependencycheck.data.cpe.xml.Importer;
|
import org.codesecure.dependencycheck.data.cpe.xml.Importer;
|
||||||
|
import org.codesecure.dependencycheck.utils.DownloadFailedException;
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
import org.joda.time.Days;
|
import org.joda.time.Days;
|
||||||
|
import org.xml.sax.SAXException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Index class is used to utilize and maintain the CPE Index.
|
* The Index class is used to utilize and maintain the CPE Index.
|
||||||
@@ -130,9 +134,12 @@ public class Index {
|
|||||||
* Downloads the latest CPE XML file from the web and imports it into
|
* Downloads the latest CPE XML file from the web and imports it into
|
||||||
* the current CPE Index.
|
* the current CPE Index.
|
||||||
*
|
*
|
||||||
* @throws Exception is thrown if an exception occurs.
|
* @throws MalformedURLException is thrown if the URL for the CPE is malformed.
|
||||||
|
* @throws ParserConfigurationException is thrown if the parser is misconfigured.
|
||||||
|
* @throws SAXException is thrown if there is an error parsing the CPE XML.
|
||||||
|
* @throws IOException is thrown if a temporary file could not be created.
|
||||||
*/
|
*/
|
||||||
public void updateIndexFromWeb() throws Exception {
|
public void updateIndexFromWeb() throws MalformedURLException, ParserConfigurationException, SAXException, IOException {
|
||||||
if (updateNeeded()) {
|
if (updateNeeded()) {
|
||||||
URL url = new URL(Settings.getString(Settings.KEYS.CPE_URL));
|
URL url = new URL(Settings.getString(Settings.KEYS.CPE_URL));
|
||||||
File outputPath = null;
|
File outputPath = null;
|
||||||
@@ -141,7 +148,8 @@ public class Index {
|
|||||||
Downloader.fetchFile(url, outputPath);
|
Downloader.fetchFile(url, outputPath);
|
||||||
Importer.importXML(outputPath.toString());
|
Importer.importXML(outputPath.toString());
|
||||||
writeLastUpdatedPropertyFile();
|
writeLastUpdatedPropertyFile();
|
||||||
} catch (Exception ex) {
|
|
||||||
|
} catch (DownloadFailedException ex) {
|
||||||
Logger.getLogger(Index.class.getName()).log(Level.SEVERE, null, ex);
|
Logger.getLogger(Index.class.getName()).log(Level.SEVERE, null, ex);
|
||||||
} finally {
|
} finally {
|
||||||
boolean deleted = false;
|
boolean deleted = false;
|
||||||
@@ -209,9 +217,9 @@ public class Index {
|
|||||||
prop.load(is);
|
prop.load(is);
|
||||||
lastUpdated = prop.getProperty(this.LAST_UPDATED);
|
lastUpdated = prop.getProperty(this.LAST_UPDATED);
|
||||||
} catch (FileNotFoundException ex) {
|
} catch (FileNotFoundException ex) {
|
||||||
Logger.getLogger(Index.class.getName()).log(Level.SEVERE, null, ex);
|
Logger.getLogger(Index.class.getName()).log(Level.FINEST, null, ex);
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
Logger.getLogger(Index.class.getName()).log(Level.SEVERE, null, ex);
|
Logger.getLogger(Index.class.getName()).log(Level.FINEST, null, ex);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
long lastupdate = Long.parseLong(lastUpdated);
|
long lastupdate = Long.parseLong(lastUpdated);
|
||||||
|
|||||||
@@ -68,6 +68,9 @@ public class Importer {
|
|||||||
*/
|
*/
|
||||||
public static void importXML(String path) throws ParserConfigurationException, SAXException, IOException {
|
public static void importXML(String path) throws ParserConfigurationException, SAXException, IOException {
|
||||||
File f = new File(path);
|
File f = new File(path);
|
||||||
|
if (!f.exists()) {
|
||||||
|
f.mkdirs();
|
||||||
|
}
|
||||||
Importer.importXML(f);
|
Importer.importXML(f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ public class Evidence {
|
|||||||
* The confidence that the evidence is "high" quality.
|
* The confidence that the evidence is "high" quality.
|
||||||
*/
|
*/
|
||||||
public enum Confidence {
|
public enum Confidence {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* High confidence evidence.
|
* High confidence evidence.
|
||||||
*/
|
*/
|
||||||
@@ -174,4 +175,47 @@ public class Evidence {
|
|||||||
public void setConfidence(Confidence confidence) {
|
public void setConfidence(Confidence confidence) {
|
||||||
this.confidence = confidence;
|
this.confidence = confidence;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements the hashCode for Evidence.
|
||||||
|
* @return hash code.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int hash = 3;
|
||||||
|
hash = 67 * hash + (this.name != null ? this.name.hashCode() : 0);
|
||||||
|
hash = 67 * hash + (this.source != null ? this.source.hashCode() : 0);
|
||||||
|
hash = 67 * hash + (this.value != null ? this.value.hashCode() : 0);
|
||||||
|
hash = 67 * hash + (this.confidence != null ? this.confidence.hashCode() : 0);
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements equals for Evidence.
|
||||||
|
* @param that an object to check the equality of.
|
||||||
|
* @return whether the two objects are equal.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object that) {
|
||||||
|
if (this == that) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!(that instanceof Evidence)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Evidence e = (Evidence) that;
|
||||||
|
|
||||||
|
return testEquality(name, e.name) && testEquality(source, e.source) && testEquality(value, e.value)
|
||||||
|
&& (confidence == null ? e.confidence == null : confidence == e.confidence);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple equality test for use within the equals method. This does a case insensitive compare.
|
||||||
|
* @param l a string to compare.
|
||||||
|
* @param r another string to compare.
|
||||||
|
* @return whether the two strings are the same.
|
||||||
|
*/
|
||||||
|
private boolean testEquality(String l, String r) {
|
||||||
|
return l == null ? r == null : l.equalsIgnoreCase(r);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,9 +18,9 @@ package org.codesecure.dependencycheck.scanner;
|
|||||||
* Copyright (c) 2012 Jeremy Long. All Rights Reserved.
|
* Copyright (c) 2012 Jeremy Long. All Rights Reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.Set;
|
||||||
import org.codesecure.dependencycheck.utils.Filter;
|
import org.codesecure.dependencycheck.utils.Filter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -85,15 +85,15 @@ public class EvidenceCollection implements Iterable<Evidence> {
|
|||||||
return EvidenceCollection.LOW_CONFIDENCE.filter(this.list);
|
return EvidenceCollection.LOW_CONFIDENCE.filter(this.list);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private List<Evidence> list = null;
|
private Set<Evidence> list = null;
|
||||||
private List<String> weightedStrings = null;
|
private Set<String> weightedStrings = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new EvidenceCollection.
|
* Creates a new EvidenceCollection.
|
||||||
*/
|
*/
|
||||||
public EvidenceCollection() {
|
public EvidenceCollection() {
|
||||||
list = new ArrayList<Evidence>();
|
list = new HashSet<Evidence>();
|
||||||
weightedStrings = new ArrayList<String>();
|
weightedStrings = new HashSet<String>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -133,18 +133,16 @@ public class EvidenceCollection implements Iterable<Evidence> {
|
|||||||
* @param str to add to the weighting collection.
|
* @param str to add to the weighting collection.
|
||||||
*/
|
*/
|
||||||
public void addWeighting(String str) {
|
public void addWeighting(String str) {
|
||||||
if (!weightedStrings.contains(str)) {
|
weightedStrings.add(str);
|
||||||
weightedStrings.add(str);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a list of Weightings - a list of terms that are believed to be of
|
* Returns a set of Weightings - a list of terms that are believed to be of
|
||||||
* higher confidence when also found in another location.
|
* higher confidence when also found in another location.
|
||||||
*
|
*
|
||||||
* @return List<String>
|
* @return Set<String>
|
||||||
*/
|
*/
|
||||||
public List<String> getWeighting() {
|
public Set<String> getWeighting() {
|
||||||
return weightedStrings;
|
return weightedStrings;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -208,19 +206,27 @@ public class EvidenceCollection implements Iterable<Evidence> {
|
|||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
// Removed because this wasn't working right (the function returned the right data, but
|
||||||
/**
|
// the use of the results was flawed.
|
||||||
* Returns a string of evidence 'values' for a given confidence.
|
// /**
|
||||||
* @param confidence the confidence filter applied to the toString method.
|
// * Returns a string of evidence 'values' for a given confidence.
|
||||||
* @return a string containing the evidence.
|
// * @param confidence the confidence filter applied to the toString method.
|
||||||
*/
|
// * @return a string containing the evidence.
|
||||||
public String toString(Evidence.Confidence confidence) {
|
// */
|
||||||
StringBuilder sb = new StringBuilder();
|
// public String toString(Evidence.Confidence confidence) {
|
||||||
for (Evidence e : this.iterator(confidence)) {
|
// StringBuilder sb = new StringBuilder();
|
||||||
sb.append(e.getValue()).append(' ');
|
// for (Evidence e : this.iterator(confidence)) {
|
||||||
}
|
// String str = e.getValue();
|
||||||
return sb.toString();
|
// //TODO this is a cheap hack, need to prevent the same string from hitting multiple times...
|
||||||
}
|
// // consider changing the evidencecollection.add to prevent the same "value" for a lower
|
||||||
|
// // confidence from being added? Might not work due to minor differences in the items in the manifest.
|
||||||
|
// // might need to actually use a StringTokenizer here and only add single words no in the list.
|
||||||
|
// if (sb.indexOf(str)<0) {
|
||||||
|
// sb.append(str).append(' ');
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// return sb.toString();
|
||||||
|
// }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a string of evidence 'values'.
|
* Returns a string of evidence 'values'.
|
||||||
@@ -235,4 +241,11 @@ public class EvidenceCollection implements Iterable<Evidence> {
|
|||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of elements in the EvidenceCollection.
|
||||||
|
* @return the number of elements in the collection.
|
||||||
|
*/
|
||||||
|
public int size() {
|
||||||
|
return list.size();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,9 @@ import java.io.File;
|
|||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.jar.Attributes;
|
import java.util.jar.Attributes;
|
||||||
import java.util.jar.JarFile;
|
import java.util.jar.JarFile;
|
||||||
@@ -47,6 +49,20 @@ import org.codesecure.dependencycheck.utils.Checksum;
|
|||||||
*/
|
*/
|
||||||
public class JarAnalyzer implements Analyzer {
|
public class JarAnalyzer implements Analyzer {
|
||||||
|
|
||||||
|
private static List<String> IGNORE_LIST;
|
||||||
|
|
||||||
|
public JarAnalyzer() {
|
||||||
|
IGNORE_LIST = new ArrayList<String>();
|
||||||
|
IGNORE_LIST.add("built-by");
|
||||||
|
IGNORE_LIST.add("created-by");
|
||||||
|
IGNORE_LIST.add("license");
|
||||||
|
IGNORE_LIST.add("build-jdk");
|
||||||
|
IGNORE_LIST.add("ant-version");
|
||||||
|
IGNORE_LIST.add("import-package");
|
||||||
|
IGNORE_LIST.add("export-package");
|
||||||
|
IGNORE_LIST.add("sealed");
|
||||||
|
IGNORE_LIST.add("manifest-version");
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* item in some manifest, should be considered medium confidence.
|
* item in some manifest, should be considered medium confidence.
|
||||||
*/
|
*/
|
||||||
@@ -69,6 +85,7 @@ public class JarAnalyzer implements Analyzer {
|
|||||||
* read in one character at a time.
|
* read in one character at a time.
|
||||||
*/
|
*/
|
||||||
private enum STRING_STATE {
|
private enum STRING_STATE {
|
||||||
|
|
||||||
ALPHA,
|
ALPHA,
|
||||||
NUMBER,
|
NUMBER,
|
||||||
PERIOD,
|
PERIOD,
|
||||||
@@ -364,20 +381,23 @@ public class JarAnalyzer implements Analyzer {
|
|||||||
vendorEvidence.addEvidence(source, key, value, Evidence.Confidence.MEDIUM);
|
vendorEvidence.addEvidence(source, key, value, Evidence.Confidence.MEDIUM);
|
||||||
} else {
|
} else {
|
||||||
key = key.toLowerCase();
|
key = key.toLowerCase();
|
||||||
if (key.contains("version")) {
|
|
||||||
versionEvidence.addEvidence(source, key, value, Evidence.Confidence.MEDIUM);
|
if (!IGNORE_LIST.contains(key)) {
|
||||||
} else if (key.contains("title")) {
|
if (key.contains("version")) {
|
||||||
titleEvidence.addEvidence(source, key, value, Evidence.Confidence.MEDIUM);
|
versionEvidence.addEvidence(source, key, value, Evidence.Confidence.MEDIUM);
|
||||||
} else if (key.contains("vendor")) {
|
} else if (key.contains("title")) {
|
||||||
vendorEvidence.addEvidence(source, key, value, Evidence.Confidence.MEDIUM);
|
titleEvidence.addEvidence(source, key, value, Evidence.Confidence.MEDIUM);
|
||||||
} else if (key.contains("name")) {
|
} else if (key.contains("vendor")) {
|
||||||
titleEvidence.addEvidence(source, key, value, Evidence.Confidence.MEDIUM);
|
vendorEvidence.addEvidence(source, key, value, Evidence.Confidence.MEDIUM);
|
||||||
vendorEvidence.addEvidence(source, key, value, Evidence.Confidence.MEDIUM);
|
} else if (key.contains("name")) {
|
||||||
} else {
|
titleEvidence.addEvidence(source, key, value, Evidence.Confidence.MEDIUM);
|
||||||
titleEvidence.addEvidence(source, key, value, Evidence.Confidence.LOW);
|
vendorEvidence.addEvidence(source, key, value, Evidence.Confidence.MEDIUM);
|
||||||
vendorEvidence.addEvidence(source, key, value, Evidence.Confidence.LOW);
|
} else {
|
||||||
if (value.matches(".*\\d.*")) {
|
titleEvidence.addEvidence(source, key, value, Evidence.Confidence.LOW);
|
||||||
versionEvidence.addEvidence(source, key, value, Evidence.Confidence.LOW);
|
vendorEvidence.addEvidence(source, key, value, Evidence.Confidence.LOW);
|
||||||
|
if (value.matches(".*\\d.*")) {
|
||||||
|
versionEvidence.addEvidence(source, key, value, Evidence.Confidence.LOW);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,9 +45,9 @@ public class Downloader {
|
|||||||
* Retrieves a file from a given URL and saves it to the outputPath.
|
* Retrieves a file from a given URL and saves it to the outputPath.
|
||||||
* @param url the URL of the file to download.
|
* @param url the URL of the file to download.
|
||||||
* @param outputPath the path to the save the file to.
|
* @param outputPath the path to the save the file to.
|
||||||
* @throws IOException is thrown if an IOException occurs.
|
* @throws DownloadFailedException is thrown if there is an error downloading the file.
|
||||||
*/
|
*/
|
||||||
public static void fetchFile(URL url, String outputPath) throws IOException {
|
public static void fetchFile(URL url, String outputPath) throws DownloadFailedException {
|
||||||
File f = new File(outputPath);
|
File f = new File(outputPath);
|
||||||
fetchFile(url, f);
|
fetchFile(url, f);
|
||||||
}
|
}
|
||||||
@@ -56,10 +56,14 @@ public class Downloader {
|
|||||||
* Retrieves a file from a given URL and saves it to the outputPath.
|
* Retrieves a file from a given URL and saves it to the outputPath.
|
||||||
* @param url the URL of the file to download.
|
* @param url the URL of the file to download.
|
||||||
* @param outputPath the path to the save the file to.
|
* @param outputPath the path to the save the file to.
|
||||||
* @throws IOException is thrown if an IOException occurs.
|
* @throws DownloadFailedException is thrown if there is an error downloading the file.
|
||||||
*/
|
*/
|
||||||
public static void fetchFile(URL url, File outputPath) throws IOException {
|
public static void fetchFile(URL url, File outputPath) throws DownloadFailedException {
|
||||||
url.openConnection();
|
try {
|
||||||
|
url.openConnection();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
throw new DownloadFailedException("Error downloading file.", ex);
|
||||||
|
}
|
||||||
BufferedOutputStream writer = null;
|
BufferedOutputStream writer = null;
|
||||||
try {
|
try {
|
||||||
InputStream reader = url.openStream();
|
InputStream reader = url.openStream();
|
||||||
@@ -70,13 +74,13 @@ public class Downloader {
|
|||||||
writer.write(buffer, 0, bytesRead);
|
writer.write(buffer, 0, bytesRead);
|
||||||
}
|
}
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
Logger.getLogger(Downloader.class.getName()).log(Level.SEVERE, null, ex);
|
throw new DownloadFailedException("Error saving downloaded file.", ex);
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
writer.close();
|
writer.close();
|
||||||
writer = null;
|
writer = null;
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
Logger.getLogger(Downloader.class.getName()).log(Level.WARNING,
|
Logger.getLogger(Downloader.class.getName()).log(Level.FINEST,
|
||||||
"Error closing the writter in Downloader.", ex);
|
"Error closing the writter in Downloader.", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,8 +6,9 @@ package org.codesecure.dependencycheck.data.cpe;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
import org.apache.lucene.index.CorruptIndexException;
|
import org.apache.lucene.index.CorruptIndexException;
|
||||||
import org.apache.lucene.queryParser.ParseException;
|
import org.apache.lucene.queryParser.ParseException;
|
||||||
import org.codesecure.dependencycheck.data.BaseIndexTestCase;
|
import org.codesecure.dependencycheck.data.BaseIndexTestCase;
|
||||||
@@ -52,10 +53,10 @@ public class CPEQueryTest extends BaseIndexTestCase {
|
|||||||
assertEquals(expResult, result.get(0).getName());
|
assertEquals(expResult, result.get(0).getName());
|
||||||
|
|
||||||
//TODO - yeah, not a very good test as the results are the same with or without weighting...
|
//TODO - yeah, not a very good test as the results are the same with or without weighting...
|
||||||
List<String> productWeightings = new ArrayList<String>(1);
|
Set<String> productWeightings = new HashSet<String>(1);
|
||||||
productWeightings.add("struts2");
|
productWeightings.add("struts2");
|
||||||
|
|
||||||
List<String> vendorWeightings = new ArrayList<String>(1);
|
Set<String> vendorWeightings = new HashSet<String>(1);
|
||||||
vendorWeightings.add("apache");
|
vendorWeightings.add("apache");
|
||||||
|
|
||||||
result = instance.searchCPE(vendor, product, version,productWeightings,vendorWeightings);
|
result = instance.searchCPE(vendor, product, version,productWeightings,vendorWeightings);
|
||||||
@@ -82,10 +83,10 @@ public class CPEQueryTest extends BaseIndexTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testBuildSearch() throws IOException, CorruptIndexException, ParseException {
|
public void testBuildSearch() throws IOException, CorruptIndexException, ParseException {
|
||||||
System.out.println("buildSearch");
|
System.out.println("buildSearch");
|
||||||
List<String> productWeightings = new ArrayList<String>(1);
|
Set<String> productWeightings = new HashSet<String>(1);
|
||||||
productWeightings.add("struts2");
|
productWeightings.add("struts2");
|
||||||
|
|
||||||
List<String> vendorWeightings = new ArrayList<String>(1);
|
Set<String> vendorWeightings = new HashSet<String>(1);
|
||||||
vendorWeightings.add("apache");
|
vendorWeightings.add("apache");
|
||||||
|
|
||||||
String vendor = "apache software foundation";
|
String vendor = "apache software foundation";
|
||||||
@@ -191,10 +192,10 @@ public class CPEQueryTest extends BaseIndexTestCase {
|
|||||||
instance.open();
|
instance.open();
|
||||||
|
|
||||||
//TODO - yeah, not a very good test as the results are the same with or without weighting...
|
//TODO - yeah, not a very good test as the results are the same with or without weighting...
|
||||||
List<String> productWeightings = new ArrayList<String>(1);
|
Set<String> productWeightings = new HashSet<String>(1);
|
||||||
productWeightings.add("struts2");
|
productWeightings.add("struts2");
|
||||||
|
|
||||||
List<String> vendorWeightings = new ArrayList<String>(1);
|
Set<String> vendorWeightings = new HashSet<String>(1);
|
||||||
vendorWeightings.add("apache");
|
vendorWeightings.add("apache");
|
||||||
|
|
||||||
List<Entry> result = instance.searchCPE(vendor, product, version,productWeightings,vendorWeightings);
|
List<Entry> result = instance.searchCPE(vendor, product, version,productWeightings,vendorWeightings);
|
||||||
|
|||||||
@@ -50,21 +50,22 @@ public class ScannerTest extends BaseIndexTestCase{
|
|||||||
* @throws Exception is thrown when an exception occurs.
|
* @throws Exception is thrown when an exception occurs.
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
|
//TODO remove the throws exception, this needs to be much more grainular.
|
||||||
public void testScan() throws Exception {
|
public void testScan() throws Exception {
|
||||||
System.out.println("scan");
|
System.out.println("scan");
|
||||||
String path = "./src/test/resources";
|
String path = "./src/test/resources";
|
||||||
Scanner instance = new Scanner();
|
Scanner instance = new Scanner();
|
||||||
instance.scan(path);
|
instance.scan(path);
|
||||||
assertTrue(instance.getDependencies().size()>0);
|
assertTrue(instance.getDependencies().size()>0);
|
||||||
// CPEQuery query = new CPEQuery();
|
CPEQuery query = new CPEQuery();
|
||||||
// query.open();
|
query.open();
|
||||||
// List<Dependency> dependencies = instance.getDependencies();
|
List<Dependency> dependencies = instance.getDependencies();
|
||||||
// for (Dependency d : dependencies) {
|
for (Dependency d : dependencies) {
|
||||||
// query.determineCPE(d);
|
query.determineCPE(d);
|
||||||
// }
|
}
|
||||||
// query.close();
|
query.close();
|
||||||
// ReportGenerator rg = new ReportGenerator();
|
ReportGenerator rg = new ReportGenerator();
|
||||||
// rg.generateReports("./target/", "DependencyCheck", instance.getDependencies());
|
rg.generateReports("./target/", "DependencyCheck", instance.getDependencies());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user