mirror of
https://github.com/ysoftdevs/DependencyCheck.git
synced 2026-03-19 07:44:23 +01:00
prepared for CVE data by refactoring CPE code
This commit is contained in:
@@ -0,0 +1,196 @@
|
|||||||
|
package org.codesecure.dependencycheck.data;
|
||||||
|
/*
|
||||||
|
* This file is part of DependencyCheck.
|
||||||
|
*
|
||||||
|
* DependencyCheck is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* DependencyCheck is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with DependencyCheck. If not, see http://www.gnu.org/licenses/.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2012 Jeremy Long. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
import org.apache.lucene.analysis.Analyzer;
|
||||||
|
import org.apache.lucene.index.CorruptIndexException;
|
||||||
|
import org.apache.lucene.index.IndexReader;
|
||||||
|
import org.apache.lucene.index.IndexWriter;
|
||||||
|
import org.apache.lucene.index.IndexWriterConfig;
|
||||||
|
import org.apache.lucene.search.IndexSearcher;
|
||||||
|
import org.apache.lucene.store.Directory;
|
||||||
|
import org.apache.lucene.store.LockObtainFailedException;
|
||||||
|
import org.apache.lucene.util.Version;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The base Index for other index objects. Implements the open and close methods.
|
||||||
|
*
|
||||||
|
* @author Jeremy Long (jeremy.long@gmail.com)
|
||||||
|
*/
|
||||||
|
public abstract class AbstractIndex {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Lucene directory containing the index.
|
||||||
|
*/
|
||||||
|
protected Directory directory = null;
|
||||||
|
/**
|
||||||
|
* The IndexWriter for the Lucene index.
|
||||||
|
*/
|
||||||
|
protected IndexWriter indexWriter = null;
|
||||||
|
/**
|
||||||
|
* The Lucene IndexReader.
|
||||||
|
*/
|
||||||
|
private IndexReader indexReader = null;
|
||||||
|
/**
|
||||||
|
* The Lucene IndexSearcher.
|
||||||
|
*/
|
||||||
|
private IndexSearcher indexSearcher = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Lucene Analyzer.
|
||||||
|
*/
|
||||||
|
private Analyzer analyzer = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates whether or not the Lucene Index is open.
|
||||||
|
*/
|
||||||
|
private boolean indexOpen = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens the CPE Index.
|
||||||
|
* @throws IOException is thrown if an IOException occurs opening the index.
|
||||||
|
*/
|
||||||
|
public void open() throws IOException {
|
||||||
|
directory = this.getDirectory();
|
||||||
|
analyzer = this.getAnalyzer(); //new StandardAnalyzer(Version.LUCENE_35);
|
||||||
|
indexOpen = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes the CPE Index.
|
||||||
|
*/
|
||||||
|
public void close() {
|
||||||
|
if (indexWriter != null) {
|
||||||
|
try {
|
||||||
|
indexWriter.commit();
|
||||||
|
} catch (CorruptIndexException ex) {
|
||||||
|
Logger.getLogger(AbstractIndex.class.getName()).log(Level.SEVERE, null, ex);
|
||||||
|
} catch (IOException ex) {
|
||||||
|
Logger.getLogger(AbstractIndex.class.getName()).log(Level.SEVERE, null, ex);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
indexWriter.close(true);
|
||||||
|
} catch (CorruptIndexException ex) {
|
||||||
|
Logger.getLogger(AbstractIndex.class.getName()).log(Level.SEVERE, null, ex);
|
||||||
|
} catch (IOException ex) {
|
||||||
|
Logger.getLogger(AbstractIndex.class.getName()).log(Level.SEVERE, null, ex);
|
||||||
|
} finally {
|
||||||
|
indexWriter = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (indexSearcher != null) {
|
||||||
|
try {
|
||||||
|
indexSearcher.close();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
Logger.getLogger(AbstractIndex.class.getName()).log(Level.SEVERE, null, ex);
|
||||||
|
} finally {
|
||||||
|
indexSearcher = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (analyzer != null) {
|
||||||
|
analyzer.close();
|
||||||
|
analyzer = null;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
directory.close();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
Logger.getLogger(AbstractIndex.class.getName()).log(Level.SEVERE, null, ex);
|
||||||
|
} finally {
|
||||||
|
directory = null;
|
||||||
|
}
|
||||||
|
indexOpen = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the status of the data source - is the index open.
|
||||||
|
* @return true or false.
|
||||||
|
*/
|
||||||
|
public boolean isOpen() {
|
||||||
|
return indexOpen;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Opens the Lucene Index Writer.
|
||||||
|
*
|
||||||
|
* @throws CorruptIndexException is thrown if the Lucene index is corrupt.
|
||||||
|
* @throws IOException is thrown if an IOException occurs opening the index.
|
||||||
|
*/
|
||||||
|
public void openIndexWriter() throws CorruptIndexException, IOException {
|
||||||
|
if (!isOpen()) {
|
||||||
|
open();
|
||||||
|
}
|
||||||
|
IndexWriterConfig conf = new IndexWriterConfig(Version.LUCENE_35, analyzer);
|
||||||
|
indexWriter = new IndexWriter(directory, conf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the IndexWriter for the Lucene Index.
|
||||||
|
*
|
||||||
|
* @return an IndexWriter.
|
||||||
|
* @throws CorruptIndexException is thrown if the Lucene Index is corrupt.
|
||||||
|
* @throws LockObtainFailedException is thrown if there is an exception obtaining a lock on the Lucene index.
|
||||||
|
* @throws IOException is thrown if an IOException occurs opening the index.
|
||||||
|
*/
|
||||||
|
public IndexWriter getIndexWriter() throws CorruptIndexException, LockObtainFailedException, IOException {
|
||||||
|
if (indexWriter == null) {
|
||||||
|
openIndexWriter();
|
||||||
|
}
|
||||||
|
return indexWriter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void openIndexReader() throws CorruptIndexException, IOException {
|
||||||
|
if (!isOpen()) {
|
||||||
|
open();
|
||||||
|
}
|
||||||
|
indexReader = IndexReader.open(directory, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IndexSearcher getIndexSearcher() throws CorruptIndexException, IOException {
|
||||||
|
if (indexReader == null) {
|
||||||
|
openIndexReader();
|
||||||
|
}
|
||||||
|
if (indexSearcher == null) {
|
||||||
|
indexSearcher = new IndexSearcher(indexReader);
|
||||||
|
}
|
||||||
|
return indexSearcher;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Analyzer getAnalyzer() {
|
||||||
|
if (analyzer == null) {
|
||||||
|
analyzer = createAnalyzer();
|
||||||
|
}
|
||||||
|
return analyzer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the directory that contains the Lucene Index.
|
||||||
|
* @return a Lucene Directory.
|
||||||
|
* @throws IOException is thrown when an IOException occurs.
|
||||||
|
*/
|
||||||
|
public abstract Directory getDirectory() throws IOException;
|
||||||
|
/**
|
||||||
|
* Creates the Lucene Analyzer used when indexing and searching the index.
|
||||||
|
* @return a Lucene Analyzer.
|
||||||
|
*/
|
||||||
|
public abstract Analyzer createAnalyzer();
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
package org.codesecure.dependencycheck.data;
|
||||||
|
/*
|
||||||
|
* This file is part of DependencyCheck.
|
||||||
|
*
|
||||||
|
* DependencyCheck is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* DependencyCheck is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with DependencyCheck. If not, see http://www.gnu.org/licenses/.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2012 Jeremy Long. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
|
import org.xml.sax.SAXException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines an Index who's data is retrieved from the Internet. This data can
|
||||||
|
* be downloaded and the index updated.
|
||||||
|
*
|
||||||
|
* @author Jeremy Long (jeremy.long@gmail.com)
|
||||||
|
*/
|
||||||
|
public interface WebDataIndex {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if an update to the current index is needed, if it is the new
|
||||||
|
* data is downloaded from the Internet and imported into the current Lucene Index.
|
||||||
|
*
|
||||||
|
* @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 MalformedURLException, ParserConfigurationException, SAXException, IOException;
|
||||||
|
}
|
||||||
@@ -75,29 +75,17 @@ public class CPEQuery {
|
|||||||
*/
|
*/
|
||||||
static final int STRING_BUILDER_BUFFER = 20;
|
static final int STRING_BUILDER_BUFFER = 20;
|
||||||
/**
|
/**
|
||||||
* The Lucene IndexReader.
|
* The CPE Index.
|
||||||
*/
|
*/
|
||||||
private IndexReader indexReader = null;
|
protected Index cpe = null;
|
||||||
/**
|
/**
|
||||||
* The Lucene IndexSearcher.
|
* The Lucene IndexSearcher.
|
||||||
*/
|
*/
|
||||||
private IndexSearcher indexSearcher = null;
|
private IndexSearcher indexSearcher = null;
|
||||||
/**
|
|
||||||
* The Lucene directory.
|
|
||||||
*/
|
|
||||||
private Directory directory = null;
|
|
||||||
/**
|
|
||||||
* The Lucene Analyzer.
|
|
||||||
*/
|
|
||||||
private Analyzer analyzer = null;
|
|
||||||
/**
|
/**
|
||||||
* The Lucene QueryParser.
|
* The Lucene QueryParser.
|
||||||
*/
|
*/
|
||||||
private QueryParser queryParser = null;
|
private QueryParser queryParser = null;
|
||||||
/**
|
|
||||||
* Indicates whether or not the Lucene Index is open.
|
|
||||||
*/
|
|
||||||
private boolean indexOpen = false;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens the data source.
|
* Opens the data source.
|
||||||
@@ -105,41 +93,21 @@ public class CPEQuery {
|
|||||||
* @throws IOException when the Lucene directory to be querried does not exist or is corrupt.
|
* @throws IOException when the Lucene directory to be querried does not exist or is corrupt.
|
||||||
*/
|
*/
|
||||||
public void open() throws IOException {
|
public void open() throws IOException {
|
||||||
directory = Index.getDirectory();
|
cpe = new Index();
|
||||||
indexReader = IndexReader.open(directory, true);
|
cpe.open();
|
||||||
indexSearcher = new IndexSearcher(indexReader);
|
indexSearcher = cpe.getIndexSearcher();
|
||||||
analyzer = Index.createAnalyzer(); //use the same analyzer as used when indexing
|
Analyzer analyzer = cpe.getAnalyzer();
|
||||||
//TITLE is the default field because it contains venddor, product, and version all in one.
|
//TITLE is the default field because it contains venddor, product, and version all in one.
|
||||||
queryParser = new QueryParser(Version.LUCENE_35, Fields.TITLE, analyzer);
|
queryParser = new QueryParser(Version.LUCENE_35, Fields.TITLE, analyzer);
|
||||||
indexOpen = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Closes the data source.
|
* Closes the data source.
|
||||||
*/
|
*/
|
||||||
public void close() {
|
public void close() {
|
||||||
analyzer.close();
|
|
||||||
analyzer = null;
|
|
||||||
queryParser = null;
|
queryParser = null;
|
||||||
try {
|
|
||||||
indexSearcher.close();
|
|
||||||
} catch (IOException ex) {
|
|
||||||
Logger.getLogger(CPEQuery.class.getName()).log(Level.SEVERE, null, ex);
|
|
||||||
}
|
|
||||||
indexSearcher = null;
|
indexSearcher = null;
|
||||||
try {
|
cpe.close();
|
||||||
indexReader.close();
|
|
||||||
} catch (IOException ex) {
|
|
||||||
Logger.getLogger(CPEQuery.class.getName()).log(Level.SEVERE, null, ex);
|
|
||||||
}
|
|
||||||
indexReader = null;
|
|
||||||
try {
|
|
||||||
directory.close();
|
|
||||||
} catch (IOException ex) {
|
|
||||||
Logger.getLogger(CPEQuery.class.getName()).log(Level.SEVERE, null, ex);
|
|
||||||
}
|
|
||||||
directory = null;
|
|
||||||
indexOpen = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -147,7 +115,7 @@ public class CPEQuery {
|
|||||||
* @return true or false.
|
* @return true or false.
|
||||||
*/
|
*/
|
||||||
public boolean isOpen() {
|
public boolean isOpen() {
|
||||||
return indexOpen;
|
return (cpe == null) ? false : cpe.isOpen();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -157,7 +125,7 @@ public class CPEQuery {
|
|||||||
@Override
|
@Override
|
||||||
protected void finalize() throws Throwable {
|
protected void finalize() throws Throwable {
|
||||||
super.finalize();
|
super.finalize();
|
||||||
if (indexOpen) {
|
if (isOpen()) {
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -174,7 +142,7 @@ public class CPEQuery {
|
|||||||
*/
|
*/
|
||||||
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 productConf = Confidence.HIGH;
|
||||||
Confidence versionConf = Confidence.HIGH;
|
Confidence versionConf = Confidence.HIGH;
|
||||||
|
|
||||||
String vendors = addEvidenceWithoutDuplicateTerms("", dependency.getVendorEvidence(), vendorConf);
|
String vendors = addEvidenceWithoutDuplicateTerms("", dependency.getVendorEvidence(), vendorConf);
|
||||||
@@ -182,10 +150,10 @@ public class CPEQuery {
|
|||||||
// 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 = addEvidenceWithoutDuplicateTerms("", dependency.getTitleEvidence(), titleConf);
|
String products = addEvidenceWithoutDuplicateTerms("", dependency.getProductEvidence(), productConf);
|
||||||
///dependency.getTitleEvidence().toString(titleConf);
|
///dependency.getProductEvidence().toString(productConf);
|
||||||
// if ("".equals(titles)) {
|
// if ("".equals(products)) {
|
||||||
// titles = STRING_THAT_WILL_NEVER_BE_IN_THE_INDEX;
|
// products = STRING_THAT_WILL_NEVER_BE_IN_THE_INDEX;
|
||||||
// }
|
// }
|
||||||
String versions = addEvidenceWithoutDuplicateTerms("", dependency.getVersionEvidence(), versionConf);
|
String versions = addEvidenceWithoutDuplicateTerms("", dependency.getVersionEvidence(), versionConf);
|
||||||
//dependency.getVersionEvidence().toString(versionConf);
|
//dependency.getVersionEvidence().toString(versionConf);
|
||||||
@@ -196,7 +164,7 @@ public class CPEQuery {
|
|||||||
boolean found = false;
|
boolean found = false;
|
||||||
int cnt = 0;
|
int cnt = 0;
|
||||||
do {
|
do {
|
||||||
List<Entry> entries = searchCPE(vendors, titles, versions, dependency.getTitleEvidence().getWeighting(),
|
List<Entry> entries = searchCPE(vendors, products, versions, dependency.getProductEvidence().getWeighting(),
|
||||||
dependency.getVendorEvidence().getWeighting());
|
dependency.getVendorEvidence().getWeighting());
|
||||||
|
|
||||||
if (entries.size() > 0) {
|
if (entries.size() > 0) {
|
||||||
@@ -220,10 +188,10 @@ public class CPEQuery {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (round == 1) {
|
if (round == 1) {
|
||||||
titleConf = reduceConfidence(titleConf);
|
productConf = reduceConfidence(productConf);
|
||||||
if (dependency.getTitleEvidence().contains(titleConf)) {
|
if (dependency.getProductEvidence().contains(productConf)) {
|
||||||
//titles += " " + dependency.getTitleEvidence().toString(titleConf);
|
//products += " " + dependency.getProductEvidence().toString(productConf);
|
||||||
titles = addEvidenceWithoutDuplicateTerms(titles, dependency.getTitleEvidence(), titleConf);
|
products = addEvidenceWithoutDuplicateTerms(products, dependency.getProductEvidence(), productConf);
|
||||||
} else {
|
} else {
|
||||||
cnt += 1;
|
cnt += 1;
|
||||||
round += 1;
|
round += 1;
|
||||||
@@ -289,7 +257,7 @@ public class CPEQuery {
|
|||||||
* with the supplied vendor, product, and version.
|
* with the supplied vendor, product, and version.
|
||||||
*
|
*
|
||||||
* @param vendor the text used to search the vendor field.
|
* @param vendor the text used to search the vendor field.
|
||||||
* @param product the text used to search the title field.
|
* @param product the text used to search the product field.
|
||||||
* @param version the text used to search the version field.
|
* @param version the text used to search the version field.
|
||||||
* @return a list of possible CPE values.
|
* @return a list of possible CPE values.
|
||||||
* @throws CorruptIndexException when the Lucene index is corrupt.
|
* @throws CorruptIndexException when the Lucene index is corrupt.
|
||||||
@@ -309,10 +277,10 @@ public class CPEQuery {
|
|||||||
* this data is used to add weighting factors to the search.</p>
|
* this data is used to add weighting factors to the search.</p>
|
||||||
*
|
*
|
||||||
* @param vendor the text used to search the vendor field.
|
* @param vendor the text used to search the vendor field.
|
||||||
* @param product the text used to search the title field.
|
* @param product the text used to search the product field.
|
||||||
* @param version the text used to search the version field.
|
* @param version the text used to search the version field.
|
||||||
* @param vendorWeightings a list of strings to use to add weighting factors to the vendor field.
|
* @param vendorWeightings a list of strings to use to add weighting factors to the vendor field.
|
||||||
* @param productWeightings Adds a list of strings that will be used to add weighting factors to the title search.
|
* @param productWeightings Adds a list of strings that will be used to add weighting factors to the product search.
|
||||||
* @return a list of possible CPE values.
|
* @return a list of possible CPE values.
|
||||||
* @throws CorruptIndexException when the Lucene index is corrupt.
|
* @throws CorruptIndexException when the Lucene index is corrupt.
|
||||||
* @throws IOException when the Lucene index is not found.
|
* @throws IOException when the Lucene index is not found.
|
||||||
@@ -347,11 +315,11 @@ public class CPEQuery {
|
|||||||
* data is used to add weighting factors to the search string generated.</p>
|
* data is used to add weighting factors to the search string generated.</p>
|
||||||
*
|
*
|
||||||
* @param vendor text to search the vendor field.
|
* @param vendor text to search the vendor field.
|
||||||
* @param product text to search the title field.
|
* @param product text to search the product field.
|
||||||
* @param version text to search the version field.
|
* @param version text to search the version field.
|
||||||
* @param vendorWeighting a list of strings to apply to the vendor
|
* @param vendorWeighting a list of strings to apply to the vendor
|
||||||
* to boost the terms weight.
|
* to boost the terms weight.
|
||||||
* @param produdctWeightings a list of strings to apply to the product/title
|
* @param produdctWeightings a list of strings to apply to the product
|
||||||
* to boost the terms weight.
|
* to boost the terms weight.
|
||||||
* @return the Lucene query.
|
* @return the Lucene query.
|
||||||
*/
|
*/
|
||||||
@@ -473,7 +441,7 @@ public class CPEQuery {
|
|||||||
/**
|
/**
|
||||||
* Takes a list of entries and a dependency. If the entry has terms that were
|
* Takes a list of entries and a dependency. If the entry has terms that were
|
||||||
* used (i.e. this CPE entry wasn't identified because the version matched
|
* used (i.e. this CPE entry wasn't identified because the version matched
|
||||||
* but the product and title did not) then the CPE Entry is returned in a list
|
* but the product names did not) then the CPE Entry is returned in a list
|
||||||
* of possible CPE Entries.
|
* of possible CPE Entries.
|
||||||
*
|
*
|
||||||
* @param entries a list of CPE entries.
|
* @param entries a list of CPE entries.
|
||||||
@@ -483,7 +451,7 @@ public class CPEQuery {
|
|||||||
private List<String> verifyEntries(final List<Entry> entries, final Dependency dependency) {
|
private List<String> verifyEntries(final List<Entry> entries, final Dependency dependency) {
|
||||||
List<String> verified = new ArrayList<String>();
|
List<String> verified = new ArrayList<String>();
|
||||||
for (Entry e : entries) {
|
for (Entry e : entries) {
|
||||||
if (dependency.getTitleEvidence().containsUsedString(e.getProduct())
|
if (dependency.getProductEvidence().containsUsedString(e.getProduct())
|
||||||
&& dependency.getVendorEvidence().containsUsedString(e.getVendor())) {
|
&& dependency.getVendorEvidence().containsUsedString(e.getVendor())) {
|
||||||
//TODO - determine if this is right? Should we be carrying too much about the
|
//TODO - determine if this is right? Should we be carrying too much about the
|
||||||
// version at this point? Likely need to implement the versionAnalyzer....
|
// version at this point? Likely need to implement the versionAnalyzer....
|
||||||
|
|||||||
@@ -44,6 +44,8 @@ import org.apache.lucene.index.IndexWriterConfig;
|
|||||||
import org.apache.lucene.store.Directory;
|
import org.apache.lucene.store.Directory;
|
||||||
import org.apache.lucene.store.FSDirectory;
|
import org.apache.lucene.store.FSDirectory;
|
||||||
import org.apache.lucene.util.Version;
|
import org.apache.lucene.util.Version;
|
||||||
|
import org.codesecure.dependencycheck.data.AbstractIndex;
|
||||||
|
import org.codesecure.dependencycheck.data.WebDataIndex;
|
||||||
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;
|
||||||
@@ -55,48 +57,17 @@ import org.xml.sax.SAXException;
|
|||||||
*
|
*
|
||||||
* @author Jeremy Long (jeremy.long@gmail.com)
|
* @author Jeremy Long (jeremy.long@gmail.com)
|
||||||
*/
|
*/
|
||||||
public class Index {
|
public class Index extends AbstractIndex implements WebDataIndex {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Te name of the properties file containing the timestamp of the last update.
|
* The name of the properties file containing the timestamp of the last update.
|
||||||
*/
|
*/
|
||||||
private static final String UPDATE_PROPERTIES_FILE = "lastupdated.prop";
|
private static final String UPDATE_PROPERTIES_FILE = "lastupdated.prop";
|
||||||
/**
|
/**
|
||||||
* The properties file key for the last updated field.
|
* The properties file key for the last updated field.
|
||||||
*/
|
*/
|
||||||
private static final String LAST_UPDATED = "lastupdated";
|
private static final String LAST_UPDATED = "lastupdated";
|
||||||
/**
|
|
||||||
* The Lucene directory containing the index.
|
|
||||||
*/
|
|
||||||
protected Directory directory = null;
|
|
||||||
/**
|
|
||||||
* The IndexWriter for the Lucene index.
|
|
||||||
*/
|
|
||||||
protected IndexWriter indexWriter = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Opens the CPE Index.
|
|
||||||
* @throws IOException is thrown if an IOException occurs opening the index.
|
|
||||||
*/
|
|
||||||
public void open() throws IOException {
|
|
||||||
directory = Index.getDirectory();
|
|
||||||
|
|
||||||
Analyzer analyzer = Index.createAnalyzer(); //new StandardAnalyzer(Version.LUCENE_35);
|
|
||||||
IndexWriterConfig conf = new IndexWriterConfig(Version.LUCENE_35, analyzer);
|
|
||||||
indexWriter = new IndexWriter(directory, conf);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Closes the CPE Index.
|
|
||||||
*
|
|
||||||
* @throws CorruptIndexException is thrown if the index is corrupt.
|
|
||||||
* @throws IOException is thrown if an IOException occurs closing the index.
|
|
||||||
*/
|
|
||||||
public void close() throws CorruptIndexException, IOException {
|
|
||||||
indexWriter.commit();
|
|
||||||
indexWriter.close(true);
|
|
||||||
directory.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the directory that holds the CPE Index.
|
* Returns the directory that holds the CPE Index.
|
||||||
@@ -104,12 +75,12 @@ public class Index {
|
|||||||
* @return the Directory containing the CPE Index.
|
* @return the Directory containing the CPE Index.
|
||||||
* @throws IOException is thrown if an IOException occurs.
|
* @throws IOException is thrown if an IOException occurs.
|
||||||
*/
|
*/
|
||||||
public static Directory getDirectory() throws IOException {
|
public Directory getDirectory() throws IOException {
|
||||||
String fileName = Settings.getString(Settings.KEYS.CPE_INDEX);
|
String fileName = Settings.getString(Settings.KEYS.CPE_INDEX);
|
||||||
File path = new File(fileName);
|
File path = new File(fileName);
|
||||||
Directory directory = FSDirectory.open(path);
|
Directory dir = FSDirectory.open(path);
|
||||||
|
|
||||||
return directory;
|
return dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -117,11 +88,11 @@ public class Index {
|
|||||||
*
|
*
|
||||||
* @return the CPE Analyzer.
|
* @return the CPE Analyzer.
|
||||||
*/
|
*/
|
||||||
public static Analyzer createAnalyzer() {
|
@SuppressWarnings("unchecked")
|
||||||
|
public Analyzer createAnalyzer() {
|
||||||
Map fieldAnalyzers = new HashMap();
|
Map fieldAnalyzers = new HashMap();
|
||||||
|
|
||||||
fieldAnalyzers.put(Fields.VERSION, new KeywordAnalyzer());
|
fieldAnalyzers.put(Fields.VERSION, new KeywordAnalyzer());
|
||||||
//new WhitespaceAnalyzer(Version.LUCENE_35)); //
|
|
||||||
|
|
||||||
PerFieldAnalyzerWrapper wrapper = new PerFieldAnalyzerWrapper(
|
PerFieldAnalyzerWrapper wrapper = new PerFieldAnalyzerWrapper(
|
||||||
new StandardAnalyzer(Version.LUCENE_35), fieldAnalyzers);
|
new StandardAnalyzer(Version.LUCENE_35), fieldAnalyzers);
|
||||||
|
|||||||
@@ -25,6 +25,10 @@ import org.apache.lucene.index.CorruptIndexException;
|
|||||||
import org.apache.lucene.index.FieldInfo.IndexOptions;
|
import org.apache.lucene.index.FieldInfo.IndexOptions;
|
||||||
import org.apache.lucene.index.Term;
|
import org.apache.lucene.index.Term;
|
||||||
import org.codesecure.dependencycheck.data.LuceneUtils;
|
import org.codesecure.dependencycheck.data.LuceneUtils;
|
||||||
|
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.cpe.xml.EntrySaveDelegate;
|
||||||
import org.codesecure.dependencycheck.data.cpe.xml.EntrySaveDelegate;
|
import org.codesecure.dependencycheck.data.cpe.xml.EntrySaveDelegate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -97,4 +101,5 @@ public class Indexer extends Index implements EntrySaveDelegate {
|
|||||||
|
|
||||||
return doc;
|
return doc;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,12 +18,12 @@ package org.codesecure.dependencycheck.data.cpe.xml;
|
|||||||
* Copyright (c) 2012 Jeremy Long. All Rights Reserved.
|
* Copyright (c) 2012 Jeremy Long. All Rights Reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import org.codesecure.dependencycheck.data.cpe.Indexer;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import javax.xml.parsers.ParserConfigurationException;
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
import javax.xml.parsers.SAXParser;
|
import javax.xml.parsers.SAXParser;
|
||||||
import javax.xml.parsers.SAXParserFactory;
|
import javax.xml.parsers.SAXParserFactory;
|
||||||
import org.codesecure.dependencycheck.data.cpe.Indexer;
|
|
||||||
import org.xml.sax.SAXException;
|
import org.xml.sax.SAXException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -53,7 +53,7 @@ public class Importer {
|
|||||||
SAXParser saxParser = factory.newSAXParser();
|
SAXParser saxParser = factory.newSAXParser();
|
||||||
CPEHandler handler = new CPEHandler();
|
CPEHandler handler = new CPEHandler();
|
||||||
Indexer indexer = new Indexer();
|
Indexer indexer = new Indexer();
|
||||||
indexer.open();
|
indexer.openIndexWriter();
|
||||||
handler.registerSaveDelegate(indexer);
|
handler.registerSaveDelegate(indexer);
|
||||||
saxParser.parse(file, handler);
|
saxParser.parse(file, handler);
|
||||||
indexer.close();
|
indexer.close();
|
||||||
|
|||||||
380
src/main/java/org/codesecure/dependencycheck/data/cve/Entry.java
Normal file
380
src/main/java/org/codesecure/dependencycheck/data/cve/Entry.java
Normal file
@@ -0,0 +1,380 @@
|
|||||||
|
package org.codesecure.dependencycheck.data.cve;
|
||||||
|
/*
|
||||||
|
* This file is part of DependencyCheck.
|
||||||
|
*
|
||||||
|
* DependencyCheck is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* DependencyCheck is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with DependencyCheck. If not, see http://www.gnu.org/licenses/.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2012 Jeremy Long. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.net.URLDecoder;
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
import org.apache.lucene.document.Document;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A single CVE entry from the cve.xml files downloaded from
|
||||||
|
* <a href="http://nvd.nist.gov/cpe.cfm">http://nvd.nist.gov/cpe.cfm</a>.
|
||||||
|
*
|
||||||
|
* @author Jeremy Long (jeremy.long@gmail.com)
|
||||||
|
*/
|
||||||
|
public class Entry {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This parse method does not fully convert a Lucene Document into a CPE Entry;
|
||||||
|
* it only sets the Entry.Name.
|
||||||
|
*
|
||||||
|
* @param doc a Lucene Document.
|
||||||
|
* @return a CPE Entry.
|
||||||
|
*/
|
||||||
|
public static Entry parse(Document doc) {
|
||||||
|
Entry entry = new Entry();
|
||||||
|
try {
|
||||||
|
entry.setName(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;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* The title of the CPE
|
||||||
|
*/
|
||||||
|
protected String title;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value of title
|
||||||
|
*
|
||||||
|
* @return the value of title
|
||||||
|
*/
|
||||||
|
public String getTitle() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the value of title
|
||||||
|
*
|
||||||
|
* @param title new value of title
|
||||||
|
*/
|
||||||
|
public void setTitle(String title) {
|
||||||
|
this.title = title;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* The name of the CPE entry.
|
||||||
|
*/
|
||||||
|
protected String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value of name
|
||||||
|
*
|
||||||
|
* @return the value of name
|
||||||
|
*/
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the value of name and calls parseName to obtain the vendor:product:version:revision
|
||||||
|
*
|
||||||
|
* @param name new value of name
|
||||||
|
* @throws UnsupportedEncodingException should never be thrown...
|
||||||
|
*/
|
||||||
|
public void setName(String name) throws UnsupportedEncodingException {
|
||||||
|
this.name = name;
|
||||||
|
parseName();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* The status of the CPE Entry.
|
||||||
|
*/
|
||||||
|
protected String status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value of status
|
||||||
|
*
|
||||||
|
* @return the value of status
|
||||||
|
*/
|
||||||
|
public String getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the value of status
|
||||||
|
*
|
||||||
|
* @param status new value of status
|
||||||
|
*/
|
||||||
|
public void setStatus(String status) {
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* The modification date of the CPE Entry.
|
||||||
|
*/
|
||||||
|
protected Date modificationDate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value of modificationDate
|
||||||
|
*
|
||||||
|
* @return the value of modificationDate
|
||||||
|
*/
|
||||||
|
public Date getModificationDate() {
|
||||||
|
return modificationDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the value of modificationDate
|
||||||
|
*
|
||||||
|
* @param modificationDate new value of modificationDate
|
||||||
|
*/
|
||||||
|
public void setModificationDate(Date modificationDate) {
|
||||||
|
this.modificationDate = modificationDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the value of modificationDate
|
||||||
|
*
|
||||||
|
* Expected format: yyyy-MM-dd'T'HH:mm:ss.SSS'Z'
|
||||||
|
*
|
||||||
|
* @param modificationDate new value of modificationDate
|
||||||
|
* @throws ParseException is thrown when a parse exception occurs.
|
||||||
|
*/
|
||||||
|
public void setModificationDate(String modificationDate) throws ParseException {
|
||||||
|
|
||||||
|
String formatStr = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
|
||||||
|
Date tempDate = null;
|
||||||
|
SimpleDateFormat sdf = new SimpleDateFormat(formatStr);
|
||||||
|
sdf.setLenient(true);
|
||||||
|
tempDate = sdf.parse(modificationDate);
|
||||||
|
|
||||||
|
this.modificationDate = tempDate;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* The nvdId.
|
||||||
|
*/
|
||||||
|
protected String nvdId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value of nvdId
|
||||||
|
*
|
||||||
|
* @return the value of nvdId
|
||||||
|
*/
|
||||||
|
public String getNvdId() {
|
||||||
|
return nvdId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the value of nvdId
|
||||||
|
*
|
||||||
|
* @param nvdId new value of nvdId
|
||||||
|
*/
|
||||||
|
public void setNvdId(String nvdId) {
|
||||||
|
this.nvdId = nvdId;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* The vendor name.
|
||||||
|
*/
|
||||||
|
protected String vendor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value of vendor
|
||||||
|
*
|
||||||
|
* @return the value of vendor
|
||||||
|
*/
|
||||||
|
public String getVendor() {
|
||||||
|
return vendor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the value of vendor
|
||||||
|
*
|
||||||
|
* @param vendor new value of vendor
|
||||||
|
*/
|
||||||
|
public void setVendor(String vendor) {
|
||||||
|
this.vendor = vendor;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* The product name.
|
||||||
|
*/
|
||||||
|
protected String product;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value of product
|
||||||
|
*
|
||||||
|
* @return the value of product
|
||||||
|
*/
|
||||||
|
public String getProduct() {
|
||||||
|
return product;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the value of product
|
||||||
|
*
|
||||||
|
* @param product new value of product
|
||||||
|
*/
|
||||||
|
public void setProduct(String product) {
|
||||||
|
this.product = product;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* The product version.
|
||||||
|
*/
|
||||||
|
protected String version;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value of version
|
||||||
|
*
|
||||||
|
* @return the value of version
|
||||||
|
*/
|
||||||
|
public String getVersion() {
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the value of version
|
||||||
|
*
|
||||||
|
* @param version new value of version
|
||||||
|
*/
|
||||||
|
public void setVersion(String version) {
|
||||||
|
this.version = version;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* The product revision.
|
||||||
|
*/
|
||||||
|
protected String revision;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value of revision
|
||||||
|
*
|
||||||
|
* @return the value of revision
|
||||||
|
*/
|
||||||
|
public String getRevision() {
|
||||||
|
return revision;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the value of revision
|
||||||
|
*
|
||||||
|
* @param revision new value of revision
|
||||||
|
*/
|
||||||
|
public void setRevision(String revision) {
|
||||||
|
this.revision = revision;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* If the CPE Entry is well known (i.e. based off a hash)
|
||||||
|
*/
|
||||||
|
protected boolean wellKnown = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value of wellKnown
|
||||||
|
*
|
||||||
|
* @return the value of wellKnown
|
||||||
|
*/
|
||||||
|
public boolean isWellKnown() {
|
||||||
|
return wellKnown;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the value of wellKnown
|
||||||
|
*
|
||||||
|
* @param wellKnown new value of wellKnown
|
||||||
|
*/
|
||||||
|
public void setWellKnown(boolean wellKnown) {
|
||||||
|
this.wellKnown = wellKnown;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* The search score.
|
||||||
|
*/
|
||||||
|
protected float searchScore;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value of searchScore
|
||||||
|
*
|
||||||
|
* @return the value of searchScore
|
||||||
|
*/
|
||||||
|
public float getSearchScore() {
|
||||||
|
return searchScore;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the value of searchScore
|
||||||
|
*
|
||||||
|
* @param searchScore new value of searchScore
|
||||||
|
*/
|
||||||
|
public void setSearchScore(float searchScore) {
|
||||||
|
this.searchScore = searchScore;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Parses a name attribute value, from the cpe.xml, into its
|
||||||
|
* corresponding parts: vendor, product, version, revision.</p>
|
||||||
|
* <p>Example:</p>
|
||||||
|
* <code> cpe:/a:apache:struts:1.1:rc2</code>
|
||||||
|
*
|
||||||
|
* <p>Results in:</p>
|
||||||
|
* <ul>
|
||||||
|
* <li>Vendor: apache</li>
|
||||||
|
* <li>Product: struts</li>
|
||||||
|
* <li>Version: 1.1</li>
|
||||||
|
* <li>Revision: rc2</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @throws UnsupportedEncodingException should never be thrown...
|
||||||
|
*/
|
||||||
|
private void parseName() throws UnsupportedEncodingException {
|
||||||
|
if (name != null && name.length() > 7) {
|
||||||
|
String[] data = name.substring(7).split(":");
|
||||||
|
if (data.length >= 1) {
|
||||||
|
vendor = URLDecoder.decode(data[0], "UTF-8");
|
||||||
|
if (data.length >= 2) {
|
||||||
|
product = URLDecoder.decode(data[1], "UTF-8");
|
||||||
|
if (data.length >= 3) {
|
||||||
|
version = URLDecoder.decode(data[2], "UTF-8");
|
||||||
|
if (data.length >= 4) {
|
||||||
|
revision = URLDecoder.decode(data[3], "UTF-8");
|
||||||
|
}
|
||||||
|
//ignore edition and language fields.. don't really see them used in the a:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (obj == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (getClass() != obj.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
final Entry other = (Entry) obj;
|
||||||
|
if ((this.name == null) ? (other.name != null) : !this.name.equals(other.name)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int hash = 5;
|
||||||
|
hash = 83 * hash + (this.name != null ? this.name.hashCode() : 0);
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
package org.codesecure.dependencycheck.data.cve;
|
||||||
|
/*
|
||||||
|
* This file is part of DependencyCheck.
|
||||||
|
*
|
||||||
|
* DependencyCheck is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* DependencyCheck is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with DependencyCheck. If not, see http://www.gnu.org/licenses/.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2012 Jeremy Long. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fields is a collection of field names used within the Lucene index for CPE
|
||||||
|
* entries.
|
||||||
|
*
|
||||||
|
* @author Jeremy Long (jeremy.long@gmail.com)
|
||||||
|
*/
|
||||||
|
public abstract class Fields {
|
||||||
|
/**
|
||||||
|
* The key for the name field.
|
||||||
|
*/
|
||||||
|
public static final String NAME = "name";
|
||||||
|
/**
|
||||||
|
* The key for the vendor field.
|
||||||
|
*/
|
||||||
|
public static final String VENDOR = "vendor";
|
||||||
|
/**
|
||||||
|
* The key for the version field.
|
||||||
|
*/
|
||||||
|
public static final String VERSION = "version";
|
||||||
|
//public static final String REVISION = "revision";
|
||||||
|
/**
|
||||||
|
* The key for the product field.
|
||||||
|
*/
|
||||||
|
public static final String PRODUCT = "product";
|
||||||
|
/**
|
||||||
|
* The key for the title field. This is a field combining vendor, product, and version.
|
||||||
|
*/
|
||||||
|
public static final String TITLE = "title";
|
||||||
|
/**
|
||||||
|
* The key for the nvdId field.
|
||||||
|
*/
|
||||||
|
public static final String NVDID = "nvdid";
|
||||||
|
}
|
||||||
255
src/main/java/org/codesecure/dependencycheck/data/cve/Index.java
Normal file
255
src/main/java/org/codesecure/dependencycheck/data/cve/Index.java
Normal file
@@ -0,0 +1,255 @@
|
|||||||
|
package org.codesecure.dependencycheck.data.cve;
|
||||||
|
/*
|
||||||
|
* This file is part of DependencyCheck.
|
||||||
|
*
|
||||||
|
* DependencyCheck is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* DependencyCheck is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with DependencyCheck. If not, see http://www.gnu.org/licenses/.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2012 Jeremy Long. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.io.OutputStreamWriter;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Properties;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
|
import org.apache.lucene.analysis.Analyzer;
|
||||||
|
import org.apache.lucene.analysis.KeywordAnalyzer;
|
||||||
|
import org.apache.lucene.analysis.PerFieldAnalyzerWrapper;
|
||||||
|
import org.apache.lucene.analysis.standard.StandardAnalyzer;
|
||||||
|
import org.apache.lucene.store.Directory;
|
||||||
|
import org.apache.lucene.store.FSDirectory;
|
||||||
|
import org.apache.lucene.util.Version;
|
||||||
|
import org.codesecure.dependencycheck.data.AbstractIndex;
|
||||||
|
import org.codesecure.dependencycheck.data.WebDataIndex;
|
||||||
|
import org.codesecure.dependencycheck.utils.Downloader;
|
||||||
|
import org.codesecure.dependencycheck.utils.Settings;
|
||||||
|
import org.codesecure.dependencycheck.data.cpe.xml.Importer;
|
||||||
|
import org.codesecure.dependencycheck.utils.DownloadFailedException;
|
||||||
|
import org.xml.sax.SAXException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Index class is used to utilize and maintain the CVE Index.
|
||||||
|
*
|
||||||
|
* @author Jeremy Long (jeremy.long@gmail.com)
|
||||||
|
*/
|
||||||
|
public class Index extends AbstractIndex implements WebDataIndex {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the properties file containing the timestamp of the last update.
|
||||||
|
*/
|
||||||
|
private static final String UPDATE_PROPERTIES_FILE = "lastupdated.prop";
|
||||||
|
/**
|
||||||
|
* The properties file key for the last updated field.
|
||||||
|
*/
|
||||||
|
private static final String LAST_UPDATED = "lastupdated";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the directory that holds the CPE Index.
|
||||||
|
*
|
||||||
|
* @return the Directory containing the CPE 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);
|
||||||
|
Directory dir = FSDirectory.open(path);
|
||||||
|
|
||||||
|
return dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an Analyzer for the CPE Index.
|
||||||
|
*
|
||||||
|
* @return the CPE Analyzer.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public Analyzer createAnalyzer() {
|
||||||
|
Map fieldAnalyzers = new HashMap();
|
||||||
|
|
||||||
|
fieldAnalyzers.put(Fields.VERSION, new KeywordAnalyzer());
|
||||||
|
|
||||||
|
PerFieldAnalyzerWrapper wrapper = new PerFieldAnalyzerWrapper(
|
||||||
|
new StandardAnalyzer(Version.LUCENE_35), fieldAnalyzers);
|
||||||
|
|
||||||
|
return wrapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Downloads the latest CPE XML file from the web and imports it into
|
||||||
|
* the current CPE Index.
|
||||||
|
*
|
||||||
|
* @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 MalformedURLException, ParserConfigurationException, SAXException, IOException {
|
||||||
|
long timeStamp = updateNeeded();
|
||||||
|
if (timeStamp > 0) {
|
||||||
|
URL url = new URL(Settings.getString(Settings.KEYS.CPE_URL));
|
||||||
|
File outputPath = null;
|
||||||
|
try {
|
||||||
|
outputPath = File.createTempFile("cve", ".xml");
|
||||||
|
Downloader.fetchFile(url, outputPath, true);
|
||||||
|
Importer.importXML(outputPath.toString());
|
||||||
|
writeLastUpdatedPropertyFile(timeStamp);
|
||||||
|
} catch (DownloadFailedException ex) {
|
||||||
|
Logger.getLogger(Index.class.getName()).log(Level.SEVERE, null, ex);
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if (outputPath != null && outputPath.exists()) {
|
||||||
|
outputPath.delete();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (outputPath != null && outputPath.exists()) {
|
||||||
|
outputPath.deleteOnExit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes a properties file containing the last updated date to the CPE directory.
|
||||||
|
* @param timeStamp the timestamp to write.
|
||||||
|
*/
|
||||||
|
private void writeLastUpdatedPropertyFile(long timeStamp) {
|
||||||
|
String dir = Settings.getString(Settings.KEYS.CPE_INDEX);
|
||||||
|
File cpeProp = new File(dir + File.separatorChar + UPDATE_PROPERTIES_FILE);
|
||||||
|
Properties prop = new Properties();
|
||||||
|
prop.put(Index.LAST_UPDATED, String.valueOf(timeStamp));
|
||||||
|
OutputStream os = null;
|
||||||
|
try {
|
||||||
|
os = new FileOutputStream(cpeProp);
|
||||||
|
OutputStreamWriter out = new OutputStreamWriter(os);
|
||||||
|
prop.store(out, dir);
|
||||||
|
} catch (FileNotFoundException ex) {
|
||||||
|
Logger.getLogger(Index.class.getName()).log(Level.SEVERE, null, ex);
|
||||||
|
} catch (IOException ex) {
|
||||||
|
Logger.getLogger(Index.class.getName()).log(Level.SEVERE, null, ex);
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
os.flush();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
Logger.getLogger(Index.class.getName()).log(Level.SEVERE, null, ex);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
os.close();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
Logger.getLogger(Index.class.getName()).log(Level.SEVERE, null, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if the index needs to be updated. This is done by fetching the
|
||||||
|
* cpe.meta data and checking the lastModifiedDate. If the CPE data needs to
|
||||||
|
* be refreshed this method will return the timestamp of the new CPE. If an
|
||||||
|
* update is not required this function will return 0.
|
||||||
|
*
|
||||||
|
* @return the timestamp of the currently published CPE.xml if the index needs to be updated, otherwise returns 0..
|
||||||
|
* @throws MalformedURLException is thrown if the URL for the CPE Meta data is incorrect.
|
||||||
|
* @throws DownloadFailedException is thrown if there is an error downloading the cpe.meta data file.
|
||||||
|
*/
|
||||||
|
public long updateNeeded() throws MalformedURLException, DownloadFailedException {
|
||||||
|
long retVal = 0;
|
||||||
|
long lastUpdated = 0;
|
||||||
|
long currentlyPublishedDate = retrieveCurrentCPETimestampFromWeb();
|
||||||
|
if (currentlyPublishedDate == 0) {
|
||||||
|
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);
|
||||||
|
if (!f.exists()) {
|
||||||
|
retVal = currentlyPublishedDate;
|
||||||
|
} else {
|
||||||
|
File cpeProp = new File(dir + File.separatorChar + UPDATE_PROPERTIES_FILE);
|
||||||
|
if (!cpeProp.exists()) {
|
||||||
|
retVal = currentlyPublishedDate;
|
||||||
|
} else {
|
||||||
|
Properties prop = new Properties();
|
||||||
|
InputStream is = null;
|
||||||
|
try {
|
||||||
|
is = new FileInputStream(cpeProp);
|
||||||
|
prop.load(is);
|
||||||
|
lastUpdated = Long.parseLong(prop.getProperty(Index.LAST_UPDATED));
|
||||||
|
} catch (FileNotFoundException ex) {
|
||||||
|
Logger.getLogger(Index.class.getName()).log(Level.FINEST, null, ex);
|
||||||
|
} catch (IOException ex) {
|
||||||
|
Logger.getLogger(Index.class.getName()).log(Level.FINEST, null, ex);
|
||||||
|
} catch (NumberFormatException ex) {
|
||||||
|
Logger.getLogger(Index.class.getName()).log(Level.FINEST, null, ex);
|
||||||
|
}
|
||||||
|
if (currentlyPublishedDate > lastUpdated) {
|
||||||
|
retVal = currentlyPublishedDate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the timestamp from the CPE meta data file.
|
||||||
|
* @return the timestamp from the currently published cpe.meta.
|
||||||
|
* @throws MalformedURLException is thrown if the URL for the CPE Meta data is incorrect.
|
||||||
|
* @throws DownloadFailedException is thrown if there is an error downloading the cpe.meta data file.
|
||||||
|
*/
|
||||||
|
private long retrieveCurrentCPETimestampFromWeb() throws MalformedURLException, DownloadFailedException {
|
||||||
|
long timestamp = 0;
|
||||||
|
File tmp = null;
|
||||||
|
InputStream is = null;
|
||||||
|
try {
|
||||||
|
tmp = File.createTempFile("cpe", "meta");
|
||||||
|
URL url = new URL(Settings.getString(Settings.KEYS.CPE_META_URL));
|
||||||
|
Downloader.fetchFile(url, tmp);
|
||||||
|
Properties prop = new Properties();
|
||||||
|
is = new FileInputStream(tmp);
|
||||||
|
prop.load(is);
|
||||||
|
timestamp = Long.parseLong(prop.getProperty("lastModifiedDate"));
|
||||||
|
} catch (IOException ex) {
|
||||||
|
throw new DownloadFailedException("Unable to create temporary file for CPE Meta File download.", ex);
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if (is != null) {
|
||||||
|
try {
|
||||||
|
is.close();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
Logger.getLogger(Index.class.getName()).log(Level.FINEST, null, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (tmp != null && tmp.exists()) {
|
||||||
|
tmp.delete();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (tmp != null && tmp.exists()) {
|
||||||
|
tmp.deleteOnExit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return timestamp;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
package org.codesecure.dependencycheck.data.cve;
|
||||||
|
/*
|
||||||
|
* This file is part of DependencyCheck.
|
||||||
|
*
|
||||||
|
* DependencyCheck is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* DependencyCheck is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with DependencyCheck. If not, see http://www.gnu.org/licenses/.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2012 Jeremy Long. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
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.LuceneUtils;
|
||||||
|
import org.codesecure.dependencycheck.data.cve.xml.EntrySaveDelegate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Indexer is used to convert a CPE Entry, retrieved from the CPE XML file,
|
||||||
|
* into a Document that is stored in the Lucene index.
|
||||||
|
*
|
||||||
|
* @author Jeremy Long (jeremy.long@gmail.com)
|
||||||
|
*/
|
||||||
|
public class Indexer extends Index implements EntrySaveDelegate {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves a CPE Entry into the Lucene index.
|
||||||
|
*
|
||||||
|
* @param entry a CPE entry.
|
||||||
|
* @throws CorruptIndexException is thrown if the index is corrupt.
|
||||||
|
* @throws IOException is thrown if an IOException occurs.
|
||||||
|
*/
|
||||||
|
public void saveEntry(Entry entry) throws CorruptIndexException, IOException {
|
||||||
|
Document doc = convertEntryToDoc(entry);
|
||||||
|
Term term = new Term(Fields.NVDID, LuceneUtils.escapeLuceneQuery(entry.getNvdId()));
|
||||||
|
indexWriter.updateDocument(term, doc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converst a CPE entry into a Lucene Document.
|
||||||
|
*
|
||||||
|
* @param entry a CPE Entry.
|
||||||
|
* @return a Lucene Document containing a CPE Entry.
|
||||||
|
*/
|
||||||
|
protected Document convertEntryToDoc(Entry entry) {
|
||||||
|
Document doc = new Document();
|
||||||
|
|
||||||
|
Field name = new Field(Fields.NAME, entry.getName(), Field.Store.YES, Field.Index.ANALYZED);
|
||||||
|
name.setIndexOptions(IndexOptions.DOCS_ONLY);
|
||||||
|
doc.add(name);
|
||||||
|
|
||||||
|
Field nvdId = new Field(Fields.NVDID, entry.getNvdId(), Field.Store.NO, Field.Index.ANALYZED);
|
||||||
|
nvdId.setIndexOptions(IndexOptions.DOCS_ONLY);
|
||||||
|
doc.add(nvdId);
|
||||||
|
|
||||||
|
Field vendor = new Field(Fields.VENDOR, entry.getVendor(), Field.Store.NO, Field.Index.ANALYZED);
|
||||||
|
vendor.setIndexOptions(IndexOptions.DOCS_ONLY);
|
||||||
|
vendor.setBoost(5.0F);
|
||||||
|
doc.add(vendor);
|
||||||
|
|
||||||
|
Field product = new Field(Fields.PRODUCT, entry.getProduct(), Field.Store.NO, Field.Index.ANALYZED);
|
||||||
|
product.setIndexOptions(IndexOptions.DOCS_ONLY);
|
||||||
|
product.setBoost(5.0F);
|
||||||
|
doc.add(product);
|
||||||
|
|
||||||
|
Field title = new Field(Fields.TITLE, entry.getTitle(), Field.Store.NO, Field.Index.ANALYZED);
|
||||||
|
title.setIndexOptions(IndexOptions.DOCS_ONLY);
|
||||||
|
//title.setBoost(1.0F);
|
||||||
|
doc.add(title);
|
||||||
|
|
||||||
|
//TODO revision should likely be its own field
|
||||||
|
if (entry.getVersion() != null) {
|
||||||
|
Field version = null;
|
||||||
|
if (entry.getRevision() != null) {
|
||||||
|
version = new Field(Fields.VERSION, entry.getVersion() + " "
|
||||||
|
+ entry.getRevision(), Field.Store.NO, Field.Index.ANALYZED);
|
||||||
|
} else {
|
||||||
|
version = new Field(Fields.VERSION, entry.getVersion(),
|
||||||
|
Field.Store.NO, Field.Index.ANALYZED);
|
||||||
|
}
|
||||||
|
version.setIndexOptions(IndexOptions.DOCS_ONLY);
|
||||||
|
version.setBoost(0.8F);
|
||||||
|
doc.add(version);
|
||||||
|
}
|
||||||
|
|
||||||
|
return doc;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
/**
|
||||||
|
* <html>
|
||||||
|
* <head>
|
||||||
|
* <title>org.codesecure.dependencycheck.data.cve.xml</title>
|
||||||
|
* </head>
|
||||||
|
* <body>
|
||||||
|
* Contains classes used to parse the CVE XML files.
|
||||||
|
* </body>
|
||||||
|
* </html>
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.codesecure.dependencycheck.data.cve;
|
||||||
@@ -0,0 +1,350 @@
|
|||||||
|
package org.codesecure.dependencycheck.data.cve.xml;
|
||||||
|
/*
|
||||||
|
* This file is part of DependencyCheck.
|
||||||
|
*
|
||||||
|
* DependencyCheck is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* DependencyCheck is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with DependencyCheck. If not, see http://www.gnu.org/licenses/.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2012 Jeremy Long. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import org.codesecure.dependencycheck.data.cve.Entry;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
import org.apache.lucene.index.CorruptIndexException;
|
||||||
|
import org.xml.sax.Attributes;
|
||||||
|
import org.xml.sax.SAXException;
|
||||||
|
import org.xml.sax.helpers.DefaultHandler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A SAX Handler that will parse the CVE XML Listing.
|
||||||
|
*
|
||||||
|
* @author Jeremy Long (jeremy.long@gmail.com)
|
||||||
|
*/
|
||||||
|
public class CVEHandler extends DefaultHandler {
|
||||||
|
|
||||||
|
private static final String CURRENT_SCHEMA_VERSION = "2.2";
|
||||||
|
EntrySaveDelegate saveDelegate = null;
|
||||||
|
Entry entry = null;
|
||||||
|
boolean languageIsUS = false;
|
||||||
|
StringBuilder nodeText = null;
|
||||||
|
boolean skip = false;
|
||||||
|
Element current = new Element();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a EntrySaveDelegate object. When the last node of an entry is
|
||||||
|
* reached if a save delegate has been regsitered the save method will be invoked.
|
||||||
|
*
|
||||||
|
* @param delegate the delegate used to save an entry
|
||||||
|
*/
|
||||||
|
public void registerSaveDelegate(EntrySaveDelegate delegate) {
|
||||||
|
this.saveDelegate = delegate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
|
||||||
|
nodeText = null;
|
||||||
|
current.setNode(qName);
|
||||||
|
if (current.isCpeItemNode()) {
|
||||||
|
entry = new Entry();
|
||||||
|
String temp = attributes.getValue("deprecated");
|
||||||
|
String name = attributes.getValue("name");
|
||||||
|
skip = (temp != null && temp.equals("true"));
|
||||||
|
try {
|
||||||
|
if (!skip && name.startsWith("cpe:/a:")) {
|
||||||
|
entry.setName(name);
|
||||||
|
} else {
|
||||||
|
skip = true;
|
||||||
|
}
|
||||||
|
} catch (UnsupportedEncodingException ex) {
|
||||||
|
throw new SAXException(ex);
|
||||||
|
}
|
||||||
|
} else if (current.isTitleNode()) {
|
||||||
|
nodeText = new StringBuilder(100);
|
||||||
|
if ("en-US".equalsIgnoreCase(attributes.getValue("xml:lang"))) {
|
||||||
|
languageIsUS = true;
|
||||||
|
} else {
|
||||||
|
languageIsUS = false;
|
||||||
|
}
|
||||||
|
} else if (current.isMetaNode()) {
|
||||||
|
try {
|
||||||
|
entry.setModificationDate(attributes.getValue("modification-date"));
|
||||||
|
} catch (ParseException ex) {
|
||||||
|
Logger.getLogger(CVEHandler.class.getName()).log(Level.SEVERE, null, ex);
|
||||||
|
}
|
||||||
|
entry.setStatus(attributes.getValue("status"));
|
||||||
|
entry.setNvdId(attributes.getValue("nvd-id"));
|
||||||
|
} else if (current.isSchemaVersionNode()) {
|
||||||
|
nodeText = new StringBuilder(3);
|
||||||
|
} else if (current.isTimestampNode()) {
|
||||||
|
nodeText = new StringBuilder(24);
|
||||||
|
}
|
||||||
|
// } else if (current.isCpeListNode()) {
|
||||||
|
// //do nothing
|
||||||
|
// } else if (current.isNotesNode()) {
|
||||||
|
// //do nothing
|
||||||
|
// } else if (current.isNoteNode()) {
|
||||||
|
// //do nothing
|
||||||
|
// } else if (current.isCheckNode()) {
|
||||||
|
// //do nothing
|
||||||
|
// } else if (current.isGeneratorNode()) {
|
||||||
|
// //do nothing
|
||||||
|
// } else if (current.isProductNameNode()) {
|
||||||
|
// //do nothing
|
||||||
|
// } else if (current.isProductVersionNode()) {
|
||||||
|
// //do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void characters(char[] ch, int start, int length) throws SAXException {
|
||||||
|
//nodeText += new String(ch, start, length);
|
||||||
|
if (nodeText != null) {
|
||||||
|
nodeText.append(ch, start, length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void endElement(String uri, String localName, String qName) throws SAXException {
|
||||||
|
current.setNode(qName);
|
||||||
|
if (current.isCpeItemNode()) {
|
||||||
|
if (saveDelegate != null && !skip) {
|
||||||
|
try {
|
||||||
|
saveDelegate.saveEntry(entry);
|
||||||
|
} catch (CorruptIndexException ex) {
|
||||||
|
Logger.getLogger(CVEHandler.class.getName()).log(Level.SEVERE, null, ex);
|
||||||
|
throw new SAXException(ex);
|
||||||
|
} catch (IOException ex) {
|
||||||
|
Logger.getLogger(CVEHandler.class.getName()).log(Level.SEVERE, null, ex);
|
||||||
|
throw new SAXException(ex);
|
||||||
|
}
|
||||||
|
entry = null;
|
||||||
|
}
|
||||||
|
} else if (current.isTitleNode()) {
|
||||||
|
if (languageIsUS) {
|
||||||
|
entry.setTitle(nodeText.toString());
|
||||||
|
}
|
||||||
|
} else if (current.isSchemaVersionNode() && !CURRENT_SCHEMA_VERSION.equals(nodeText.toString())) {
|
||||||
|
throw new SAXException("ERROR: Invalid Schema Version, expected: "
|
||||||
|
+ CURRENT_SCHEMA_VERSION + ", file is: " + nodeText);
|
||||||
|
}
|
||||||
|
// } else if (current.isCpeListNode()) {
|
||||||
|
// //do nothing
|
||||||
|
// } else if (current.isMetaNode()) {
|
||||||
|
// //do nothing
|
||||||
|
// } else if (current.isNotesNode()) {
|
||||||
|
// //do nothing
|
||||||
|
// } else if (current.isNoteNode()) {
|
||||||
|
// //do nothing
|
||||||
|
// } else if (current.isCheckNode()) {
|
||||||
|
// //do nothing
|
||||||
|
// } else if (current.isGeneratorNode()) {
|
||||||
|
// //do nothing
|
||||||
|
// } else if (current.isProductNameNode()) {
|
||||||
|
// //do nothing
|
||||||
|
// } else if (current.isProductVersionNode()) {
|
||||||
|
// //do nothing
|
||||||
|
// else if (current.isTimestampNode()) {
|
||||||
|
// //do nothing
|
||||||
|
// } else {
|
||||||
|
// throw new SAXException("ERROR STATE: Unexpected qName '" + qName + "'");
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
// <editor-fold defaultstate="collapsed" desc="The Element Class that maintains state information about the current node">
|
||||||
|
/**
|
||||||
|
* A simple class to maintain information about the current element while parsing
|
||||||
|
* the CPE XML.
|
||||||
|
*/
|
||||||
|
protected class Element {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A node type in the CPE Schema 2.2
|
||||||
|
*/
|
||||||
|
public static final String CPE_LIST = "cpe-list";
|
||||||
|
/**
|
||||||
|
* A node type in the CPE Schema 2.2
|
||||||
|
*/
|
||||||
|
public static final String CPE_ITEM = "cpe-item";
|
||||||
|
/**
|
||||||
|
* A node type in the CPE Schema 2.2
|
||||||
|
*/
|
||||||
|
public static final String TITLE = "title";
|
||||||
|
/**
|
||||||
|
* A node type in the CPE Schema 2.2
|
||||||
|
*/
|
||||||
|
public static final String NOTES = "notes";
|
||||||
|
/**
|
||||||
|
* A node type in the CPE Schema 2.2
|
||||||
|
*/
|
||||||
|
public static final String NOTE = "note";
|
||||||
|
/**
|
||||||
|
* A node type in the CPE Schema 2.2
|
||||||
|
*/
|
||||||
|
public static final String CHECK = "check";
|
||||||
|
/**
|
||||||
|
* A node type in the CPE Schema 2.2
|
||||||
|
*/
|
||||||
|
public static final String META = "meta:item-metadata";
|
||||||
|
/**
|
||||||
|
* A node type in the CPE Schema 2.2
|
||||||
|
*/
|
||||||
|
public static final String GENERATOR = "generator";
|
||||||
|
/**
|
||||||
|
* A node type in the CPE Schema 2.2
|
||||||
|
*/
|
||||||
|
public static final String PRODUCT_NAME = "product_name";
|
||||||
|
/**
|
||||||
|
* A node type in the CPE Schema 2.2
|
||||||
|
*/
|
||||||
|
public static final String PRODUCT_VERSION = "product_version";
|
||||||
|
/**
|
||||||
|
* A node type in the CPE Schema 2.2
|
||||||
|
*/
|
||||||
|
public static final String SCHEMA_VERSION = "schema_version";
|
||||||
|
/**
|
||||||
|
* A node type in the CPE Schema 2.2
|
||||||
|
*/
|
||||||
|
public static final String TIMESTAMP = "timestamp";
|
||||||
|
private String node = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the value of node
|
||||||
|
*
|
||||||
|
* @return the value of node
|
||||||
|
*/
|
||||||
|
public String getNode() {
|
||||||
|
return this.node;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the value of node
|
||||||
|
*
|
||||||
|
* @param node new value of node
|
||||||
|
*/
|
||||||
|
public void setNode(String node) {
|
||||||
|
this.node = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the handler is at the CPE_LIST node
|
||||||
|
*
|
||||||
|
* @return true or false
|
||||||
|
*/
|
||||||
|
public boolean isCpeListNode() {
|
||||||
|
return CPE_LIST.equals(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the handler is at the CPE_ITEM node
|
||||||
|
*
|
||||||
|
* @return true or false
|
||||||
|
*/
|
||||||
|
public boolean isCpeItemNode() {
|
||||||
|
return CPE_ITEM.equals(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the handler is at the TITLE node
|
||||||
|
*
|
||||||
|
* @return true or false
|
||||||
|
*/
|
||||||
|
public boolean isTitleNode() {
|
||||||
|
return TITLE.equals(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the handler is at the NOTES node
|
||||||
|
*
|
||||||
|
* @return true or false
|
||||||
|
*/
|
||||||
|
public boolean isNotesNode() {
|
||||||
|
return NOTES.equals(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the handler is at the NOTE node
|
||||||
|
*
|
||||||
|
* @return true or false
|
||||||
|
*/
|
||||||
|
public boolean isNoteNode() {
|
||||||
|
return NOTE.equals(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the handler is at the CHECK node
|
||||||
|
*
|
||||||
|
* @return true or false
|
||||||
|
*/
|
||||||
|
public boolean isCheckNode() {
|
||||||
|
return CHECK.equals(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the handler is at the META node
|
||||||
|
*
|
||||||
|
* @return true or false
|
||||||
|
*/
|
||||||
|
public boolean isMetaNode() {
|
||||||
|
return META.equals(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the handler is at the GENERATOR node
|
||||||
|
*
|
||||||
|
* @return true or false
|
||||||
|
*/
|
||||||
|
public boolean isGeneratorNode() {
|
||||||
|
return GENERATOR.equals(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the handler is at the PRODUCT_NAME node
|
||||||
|
*
|
||||||
|
* @return true or false
|
||||||
|
*/
|
||||||
|
public boolean isProductNameNode() {
|
||||||
|
return PRODUCT_NAME.equals(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the handler is at the PRODUCT_VERSION node
|
||||||
|
*
|
||||||
|
* @return true or false
|
||||||
|
*/
|
||||||
|
public boolean isProductVersionNode() {
|
||||||
|
return PRODUCT_VERSION.equals(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the handler is at the SCHEMA_VERSION node
|
||||||
|
*
|
||||||
|
* @return true or false
|
||||||
|
*/
|
||||||
|
public boolean isSchemaVersionNode() {
|
||||||
|
return SCHEMA_VERSION.equals(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the handler is at the TIMESTAMP node
|
||||||
|
*
|
||||||
|
* @return true or false
|
||||||
|
*/
|
||||||
|
public boolean isTimestampNode() {
|
||||||
|
return TIMESTAMP.equals(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// </editor-fold>
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package org.codesecure.dependencycheck.data.cve.xml;
|
||||||
|
/*
|
||||||
|
* This file is part of DependencyCheck.
|
||||||
|
*
|
||||||
|
* DependencyCheck is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* DependencyCheck is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with DependencyCheck. If not, see http://www.gnu.org/licenses/.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2012 Jeremy Long. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import org.codesecure.dependencycheck.data.cve.Entry;
|
||||||
|
import java.io.IOException;
|
||||||
|
import org.apache.lucene.index.CorruptIndexException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* An interface used to define the save function used when parsing the CVE XML
|
||||||
|
* file.
|
||||||
|
*
|
||||||
|
* @author Jeremy Long (jeremy.long@gmail.com)
|
||||||
|
*/
|
||||||
|
public interface EntrySaveDelegate {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves a CVE Entry into the Lucene index.
|
||||||
|
*
|
||||||
|
* @param entry a CVE entry.
|
||||||
|
* @throws CorruptIndexException is thrown if the index is corrupt.
|
||||||
|
* @throws IOException is thrown if an IOException occurs.
|
||||||
|
*/
|
||||||
|
void saveEntry(Entry entry) throws CorruptIndexException, IOException;
|
||||||
|
}
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
package org.codesecure.dependencycheck.data.cve.xml;
|
||||||
|
/*
|
||||||
|
* This file is part of DependencyCheck.
|
||||||
|
*
|
||||||
|
* DependencyCheck is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* DependencyCheck is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with DependencyCheck. If not, see http://www.gnu.org/licenses/.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2012 Jeremy Long. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import org.codesecure.dependencycheck.data.cve.Indexer;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
|
import javax.xml.parsers.SAXParser;
|
||||||
|
import javax.xml.parsers.SAXParserFactory;
|
||||||
|
import org.xml.sax.SAXException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Imports a CVE XML file into the Lucene CVE Index.
|
||||||
|
*
|
||||||
|
* @author Jeremy Long (jeremy.long@gmail.com)
|
||||||
|
*/
|
||||||
|
public class Importer {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private constructor for utility class.
|
||||||
|
*/
|
||||||
|
private Importer() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Imports the CPE XML File into the Lucene Index.
|
||||||
|
*
|
||||||
|
* @param file containing the path to the CPE XML file.
|
||||||
|
* @throws ParserConfigurationException is thrown if the parser is misconfigured.
|
||||||
|
* @throws SAXException is thrown when there is a SAXException.
|
||||||
|
* @throws IOException is thrown when there is an IOException.
|
||||||
|
*/
|
||||||
|
public static void importXML(File file) throws ParserConfigurationException, SAXException, IOException {
|
||||||
|
SAXParserFactory factory = SAXParserFactory.newInstance();
|
||||||
|
SAXParser saxParser = factory.newSAXParser();
|
||||||
|
CVEHandler handler = new CVEHandler();
|
||||||
|
Indexer indexer = new Indexer();
|
||||||
|
indexer.open();
|
||||||
|
handler.registerSaveDelegate(indexer);
|
||||||
|
saxParser.parse(file, handler);
|
||||||
|
indexer.close();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Imports the CPE XML File into the Lucene Index.
|
||||||
|
*
|
||||||
|
* @param path the path to the CPE XML file.
|
||||||
|
* @throws ParserConfigurationException is thrown if the parser is misconfigured.
|
||||||
|
* @throws SAXException is thrown when there is a SAXException.
|
||||||
|
* @throws IOException is thrown when there is an IOException.
|
||||||
|
*/
|
||||||
|
public static void importXML(String path) throws ParserConfigurationException, SAXException, IOException {
|
||||||
|
File f = new File(path);
|
||||||
|
if (!f.exists()) {
|
||||||
|
f.mkdirs();
|
||||||
|
}
|
||||||
|
Importer.importXML(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
/**
|
||||||
|
* <html>
|
||||||
|
* <head>
|
||||||
|
* <title>org.codesecure.dependencycheck.data.cve.xml</title>
|
||||||
|
* </head>
|
||||||
|
* <body>
|
||||||
|
* Contains classes used to parse the CVE XML file.
|
||||||
|
* </body>
|
||||||
|
* </html>
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.codesecure.dependencycheck.data.cve.xml;
|
||||||
@@ -57,9 +57,9 @@ public class Dependency {
|
|||||||
*/
|
*/
|
||||||
protected EvidenceCollection vendorEvidence = null;
|
protected EvidenceCollection vendorEvidence = null;
|
||||||
/**
|
/**
|
||||||
* A collection of title evidence.
|
* A collection of product evidence.
|
||||||
*/
|
*/
|
||||||
protected EvidenceCollection titleEvidence = null;
|
protected EvidenceCollection productEvidence = null;
|
||||||
/**
|
/**
|
||||||
* A collection of version evidence.
|
* A collection of version evidence.
|
||||||
*/
|
*/
|
||||||
@@ -70,7 +70,7 @@ public class Dependency {
|
|||||||
*/
|
*/
|
||||||
public Dependency() {
|
public Dependency() {
|
||||||
vendorEvidence = new EvidenceCollection();
|
vendorEvidence = new EvidenceCollection();
|
||||||
titleEvidence = new EvidenceCollection();
|
productEvidence = new EvidenceCollection();
|
||||||
versionEvidence = new EvidenceCollection();
|
versionEvidence = new EvidenceCollection();
|
||||||
cpes = new ArrayList<String>();
|
cpes = new ArrayList<String>();
|
||||||
}
|
}
|
||||||
@@ -181,7 +181,7 @@ public class Dependency {
|
|||||||
* @return an EvidenceCollection.
|
* @return an EvidenceCollection.
|
||||||
*/
|
*/
|
||||||
public EvidenceCollection getEvidence() {
|
public EvidenceCollection getEvidence() {
|
||||||
return EvidenceCollection.mergeUsed(this.titleEvidence, this.vendorEvidence, this.versionEvidence);
|
return EvidenceCollection.mergeUsed(this.productEvidence, this.vendorEvidence, this.versionEvidence);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -191,7 +191,7 @@ public class Dependency {
|
|||||||
* @return an EvidenceCollection.
|
* @return an EvidenceCollection.
|
||||||
*/
|
*/
|
||||||
public EvidenceCollection getEvidenceUsed() {
|
public EvidenceCollection getEvidenceUsed() {
|
||||||
EvidenceCollection ec = EvidenceCollection.mergeUsed(this.titleEvidence, this.vendorEvidence, this.versionEvidence);
|
EvidenceCollection ec = EvidenceCollection.mergeUsed(this.productEvidence, this.vendorEvidence, this.versionEvidence);
|
||||||
return ec;
|
return ec;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -205,12 +205,12 @@ public class Dependency {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the Title Evidence.
|
* Gets the Product Evidence.
|
||||||
*
|
*
|
||||||
* @return an EvidenceCollection.
|
* @return an EvidenceCollection.
|
||||||
*/
|
*/
|
||||||
public EvidenceCollection getTitleEvidence() {
|
public EvidenceCollection getProductEvidence() {
|
||||||
return this.titleEvidence;
|
return this.productEvidence;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -244,7 +244,7 @@ public class Dependency {
|
|||||||
if (vendorEvidence.containsUsedString(str)) {
|
if (vendorEvidence.containsUsedString(str)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (titleEvidence.containsUsedString(str)) {
|
if (productEvidence.containsUsedString(str)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (versionEvidence.containsUsedString(fnd)) {
|
if (versionEvidence.containsUsedString(fnd)) {
|
||||||
|
|||||||
@@ -179,7 +179,7 @@ public class JarAnalyzer extends AbstractAnalyzer {
|
|||||||
}
|
}
|
||||||
Pattern rx = Pattern.compile("\\s\\s+");
|
Pattern rx = Pattern.compile("\\s\\s+");
|
||||||
fileNameEvidence = rx.matcher(sb.toString()).replaceAll(" ");
|
fileNameEvidence = rx.matcher(sb.toString()).replaceAll(" ");
|
||||||
dependency.getTitleEvidence().addEvidence("jar", "file name",
|
dependency.getProductEvidence().addEvidence("jar", "file name",
|
||||||
fileNameEvidence, Evidence.Confidence.HIGH);
|
fileNameEvidence, Evidence.Confidence.HIGH);
|
||||||
dependency.getVendorEvidence().addEvidence("jar", "file name",
|
dependency.getVendorEvidence().addEvidence("jar", "file name",
|
||||||
fileNameEvidence, Evidence.Confidence.HIGH);
|
fileNameEvidence, Evidence.Confidence.HIGH);
|
||||||
@@ -276,14 +276,14 @@ public class JarAnalyzer extends AbstractAnalyzer {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
EvidenceCollection vendor = dependency.getVendorEvidence();
|
EvidenceCollection vendor = dependency.getVendorEvidence();
|
||||||
EvidenceCollection title = dependency.getTitleEvidence();
|
EvidenceCollection product = dependency.getProductEvidence();
|
||||||
|
|
||||||
for (String s : level0.keySet()) {
|
for (String s : level0.keySet()) {
|
||||||
if (!"org".equals(s) && !"com".equals(s)) {
|
if (!"org".equals(s) && !"com".equals(s)) {
|
||||||
vendor.addWeighting(s);
|
vendor.addWeighting(s);
|
||||||
title.addWeighting(s);
|
product.addWeighting(s);
|
||||||
vendor.addEvidence("jar", "package", s, Evidence.Confidence.LOW);
|
vendor.addEvidence("jar", "package", s, Evidence.Confidence.LOW);
|
||||||
title.addEvidence("jar", "package", s, Evidence.Confidence.LOW);
|
product.addEvidence("jar", "package", s, Evidence.Confidence.LOW);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (String s : level1.keySet()) {
|
for (String s : level1.keySet()) {
|
||||||
@@ -296,9 +296,9 @@ public class JarAnalyzer extends AbstractAnalyzer {
|
|||||||
vendor.addEvidence("jar", "package", parts[1], Evidence.Confidence.LOW);
|
vendor.addEvidence("jar", "package", parts[1], Evidence.Confidence.LOW);
|
||||||
} else {
|
} else {
|
||||||
vendor.addWeighting(parts[0]);
|
vendor.addWeighting(parts[0]);
|
||||||
title.addWeighting(parts[1]);
|
product.addWeighting(parts[1]);
|
||||||
vendor.addEvidence("jar", "package", parts[0], Evidence.Confidence.LOW);
|
vendor.addEvidence("jar", "package", parts[0], Evidence.Confidence.LOW);
|
||||||
title.addEvidence("jar", "package", parts[1], Evidence.Confidence.LOW);
|
product.addEvidence("jar", "package", parts[1], Evidence.Confidence.LOW);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -309,18 +309,18 @@ public class JarAnalyzer extends AbstractAnalyzer {
|
|||||||
String[] parts = s.split("/");
|
String[] parts = s.split("/");
|
||||||
if ("org".equals(parts[0]) || "com".equals(parts[0])) {
|
if ("org".equals(parts[0]) || "com".equals(parts[0])) {
|
||||||
vendor.addWeighting(parts[1]);
|
vendor.addWeighting(parts[1]);
|
||||||
title.addWeighting(parts[2]);
|
product.addWeighting(parts[2]);
|
||||||
vendor.addEvidence("jar", "package", parts[1], Evidence.Confidence.LOW);
|
vendor.addEvidence("jar", "package", parts[1], Evidence.Confidence.LOW);
|
||||||
title.addEvidence("jar", "package", parts[2], Evidence.Confidence.LOW);
|
product.addEvidence("jar", "package", parts[2], Evidence.Confidence.LOW);
|
||||||
} else {
|
} else {
|
||||||
vendor.addWeighting(parts[0]);
|
vendor.addWeighting(parts[0]);
|
||||||
vendor.addWeighting(parts[1]);
|
vendor.addWeighting(parts[1]);
|
||||||
title.addWeighting(parts[1]);
|
product.addWeighting(parts[1]);
|
||||||
title.addWeighting(parts[2]);
|
product.addWeighting(parts[2]);
|
||||||
vendor.addEvidence("jar", "package", parts[0], Evidence.Confidence.LOW);
|
vendor.addEvidence("jar", "package", parts[0], Evidence.Confidence.LOW);
|
||||||
vendor.addEvidence("jar", "package", parts[1], Evidence.Confidence.LOW);
|
vendor.addEvidence("jar", "package", parts[1], Evidence.Confidence.LOW);
|
||||||
title.addEvidence("jar", "package", parts[1], Evidence.Confidence.LOW);
|
product.addEvidence("jar", "package", parts[1], Evidence.Confidence.LOW);
|
||||||
title.addEvidence("jar", "package", parts[2], Evidence.Confidence.LOW);
|
product.addEvidence("jar", "package", parts[2], Evidence.Confidence.LOW);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -332,26 +332,26 @@ public class JarAnalyzer extends AbstractAnalyzer {
|
|||||||
if ("org".equals(parts[0]) || "com".equals(parts[0])) {
|
if ("org".equals(parts[0]) || "com".equals(parts[0])) {
|
||||||
vendor.addWeighting(parts[1]);
|
vendor.addWeighting(parts[1]);
|
||||||
vendor.addWeighting(parts[2]);
|
vendor.addWeighting(parts[2]);
|
||||||
title.addWeighting(parts[2]);
|
product.addWeighting(parts[2]);
|
||||||
title.addWeighting(parts[3]);
|
product.addWeighting(parts[3]);
|
||||||
vendor.addEvidence("jar", "package", parts[1], Evidence.Confidence.LOW);
|
vendor.addEvidence("jar", "package", parts[1], Evidence.Confidence.LOW);
|
||||||
vendor.addEvidence("jar", "package", parts[2], Evidence.Confidence.LOW);
|
vendor.addEvidence("jar", "package", parts[2], Evidence.Confidence.LOW);
|
||||||
title.addEvidence("jar", "package", parts[2], Evidence.Confidence.LOW);
|
product.addEvidence("jar", "package", parts[2], Evidence.Confidence.LOW);
|
||||||
title.addEvidence("jar", "package", parts[3], Evidence.Confidence.LOW);
|
product.addEvidence("jar", "package", parts[3], Evidence.Confidence.LOW);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
vendor.addWeighting(parts[0]);
|
vendor.addWeighting(parts[0]);
|
||||||
vendor.addWeighting(parts[1]);
|
vendor.addWeighting(parts[1]);
|
||||||
vendor.addWeighting(parts[2]);
|
vendor.addWeighting(parts[2]);
|
||||||
title.addWeighting(parts[1]);
|
product.addWeighting(parts[1]);
|
||||||
title.addWeighting(parts[2]);
|
product.addWeighting(parts[2]);
|
||||||
title.addWeighting(parts[3]);
|
product.addWeighting(parts[3]);
|
||||||
vendor.addEvidence("jar", "package", parts[0], Evidence.Confidence.LOW);
|
vendor.addEvidence("jar", "package", parts[0], Evidence.Confidence.LOW);
|
||||||
vendor.addEvidence("jar", "package", parts[1], Evidence.Confidence.LOW);
|
vendor.addEvidence("jar", "package", parts[1], Evidence.Confidence.LOW);
|
||||||
vendor.addEvidence("jar", "package", parts[2], Evidence.Confidence.LOW);
|
vendor.addEvidence("jar", "package", parts[2], Evidence.Confidence.LOW);
|
||||||
title.addEvidence("jar", "package", parts[1], Evidence.Confidence.LOW);
|
product.addEvidence("jar", "package", parts[1], Evidence.Confidence.LOW);
|
||||||
title.addEvidence("jar", "package", parts[2], Evidence.Confidence.LOW);
|
product.addEvidence("jar", "package", parts[2], Evidence.Confidence.LOW);
|
||||||
title.addEvidence("jar", "package", parts[3], Evidence.Confidence.LOW);
|
product.addEvidence("jar", "package", parts[3], Evidence.Confidence.LOW);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -380,7 +380,7 @@ public class JarAnalyzer extends AbstractAnalyzer {
|
|||||||
Attributes atts = manifest.getMainAttributes();
|
Attributes atts = manifest.getMainAttributes();
|
||||||
|
|
||||||
EvidenceCollection vendorEvidence = dependency.getVendorEvidence();
|
EvidenceCollection vendorEvidence = dependency.getVendorEvidence();
|
||||||
EvidenceCollection titleEvidence = dependency.getTitleEvidence();
|
EvidenceCollection productEvidence = dependency.getProductEvidence();
|
||||||
EvidenceCollection versionEvidence = dependency.getVersionEvidence();
|
EvidenceCollection versionEvidence = dependency.getVersionEvidence();
|
||||||
|
|
||||||
String source = "Manifest";
|
String source = "Manifest";
|
||||||
@@ -389,7 +389,7 @@ public class JarAnalyzer extends AbstractAnalyzer {
|
|||||||
String key = entry.getKey().toString();
|
String key = entry.getKey().toString();
|
||||||
String value = atts.getValue(key);
|
String value = atts.getValue(key);
|
||||||
if (key.equals(Attributes.Name.IMPLEMENTATION_TITLE.toString())) {
|
if (key.equals(Attributes.Name.IMPLEMENTATION_TITLE.toString())) {
|
||||||
titleEvidence.addEvidence(source, key, value, Evidence.Confidence.HIGH);
|
productEvidence.addEvidence(source, key, value, Evidence.Confidence.HIGH);
|
||||||
} else if (key.equals(Attributes.Name.IMPLEMENTATION_VERSION.toString())) {
|
} else if (key.equals(Attributes.Name.IMPLEMENTATION_VERSION.toString())) {
|
||||||
versionEvidence.addEvidence(source, key, value, Evidence.Confidence.HIGH);
|
versionEvidence.addEvidence(source, key, value, Evidence.Confidence.HIGH);
|
||||||
} else if (key.equals(Attributes.Name.IMPLEMENTATION_VENDOR.toString())) {
|
} else if (key.equals(Attributes.Name.IMPLEMENTATION_VENDOR.toString())) {
|
||||||
@@ -397,15 +397,15 @@ public class JarAnalyzer extends AbstractAnalyzer {
|
|||||||
} else if (key.equals(Attributes.Name.IMPLEMENTATION_VENDOR_ID.toString())) {
|
} else if (key.equals(Attributes.Name.IMPLEMENTATION_VENDOR_ID.toString())) {
|
||||||
vendorEvidence.addEvidence(source, key, value, Evidence.Confidence.MEDIUM);
|
vendorEvidence.addEvidence(source, key, value, Evidence.Confidence.MEDIUM);
|
||||||
} else if (key.equals(BUNDLE_DESCRIPTION)) {
|
} else if (key.equals(BUNDLE_DESCRIPTION)) {
|
||||||
titleEvidence.addEvidence(source, key, value, Evidence.Confidence.MEDIUM);
|
productEvidence.addEvidence(source, key, value, Evidence.Confidence.MEDIUM);
|
||||||
} else if (key.equals(BUNDLE_NAME)) {
|
} else if (key.equals(BUNDLE_NAME)) {
|
||||||
titleEvidence.addEvidence(source, key, value, Evidence.Confidence.MEDIUM);
|
productEvidence.addEvidence(source, key, value, Evidence.Confidence.MEDIUM);
|
||||||
} else if (key.equals(BUNDLE_VENDOR)) {
|
} else if (key.equals(BUNDLE_VENDOR)) {
|
||||||
vendorEvidence.addEvidence(source, key, value, Evidence.Confidence.HIGH);
|
vendorEvidence.addEvidence(source, key, value, Evidence.Confidence.HIGH);
|
||||||
} else if (key.equals(BUNDLE_VERSION)) {
|
} else if (key.equals(BUNDLE_VERSION)) {
|
||||||
versionEvidence.addEvidence(source, key, value, Evidence.Confidence.HIGH);
|
versionEvidence.addEvidence(source, key, value, Evidence.Confidence.HIGH);
|
||||||
} else if (key.equals(Attributes.Name.MAIN_CLASS.toString())) {
|
} else if (key.equals(Attributes.Name.MAIN_CLASS.toString())) {
|
||||||
titleEvidence.addEvidence(source, key, value, Evidence.Confidence.MEDIUM);
|
productEvidence.addEvidence(source, key, value, Evidence.Confidence.MEDIUM);
|
||||||
vendorEvidence.addEvidence(source, key, value, Evidence.Confidence.MEDIUM);
|
vendorEvidence.addEvidence(source, key, value, Evidence.Confidence.MEDIUM);
|
||||||
} else {
|
} else {
|
||||||
key = key.toLowerCase();
|
key = key.toLowerCase();
|
||||||
@@ -414,14 +414,14 @@ public class JarAnalyzer extends AbstractAnalyzer {
|
|||||||
if (key.contains("version")) {
|
if (key.contains("version")) {
|
||||||
versionEvidence.addEvidence(source, key, value, Evidence.Confidence.MEDIUM);
|
versionEvidence.addEvidence(source, key, value, Evidence.Confidence.MEDIUM);
|
||||||
} else if (key.contains("title")) {
|
} else if (key.contains("title")) {
|
||||||
titleEvidence.addEvidence(source, key, value, Evidence.Confidence.MEDIUM);
|
productEvidence.addEvidence(source, key, value, Evidence.Confidence.MEDIUM);
|
||||||
} else if (key.contains("vendor")) {
|
} else if (key.contains("vendor")) {
|
||||||
vendorEvidence.addEvidence(source, key, value, Evidence.Confidence.MEDIUM);
|
vendorEvidence.addEvidence(source, key, value, Evidence.Confidence.MEDIUM);
|
||||||
} else if (key.contains("name")) {
|
} else if (key.contains("name")) {
|
||||||
titleEvidence.addEvidence(source, key, value, Evidence.Confidence.MEDIUM);
|
productEvidence.addEvidence(source, key, value, Evidence.Confidence.MEDIUM);
|
||||||
vendorEvidence.addEvidence(source, key, value, Evidence.Confidence.MEDIUM);
|
vendorEvidence.addEvidence(source, key, value, Evidence.Confidence.MEDIUM);
|
||||||
} else {
|
} else {
|
||||||
titleEvidence.addEvidence(source, key, value, Evidence.Confidence.LOW);
|
productEvidence.addEvidence(source, key, value, Evidence.Confidence.LOW);
|
||||||
vendorEvidence.addEvidence(source, key, value, Evidence.Confidence.LOW);
|
vendorEvidence.addEvidence(source, key, value, Evidence.Confidence.LOW);
|
||||||
if (value.matches(".*\\d.*")) {
|
if (value.matches(".*\\d.*")) {
|
||||||
versionEvidence.addEvidence(source, key, value, Evidence.Confidence.LOW);
|
versionEvidence.addEvidence(source, key, value, Evidence.Confidence.LOW);
|
||||||
|
|||||||
@@ -56,13 +56,7 @@ public class IndexTest extends BaseIndexTestCase {
|
|||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
fail(ex.getMessage());
|
fail(ex.getMessage());
|
||||||
}
|
}
|
||||||
try {
|
instance.close();
|
||||||
instance.close();
|
|
||||||
} catch (CorruptIndexException ex) {
|
|
||||||
fail(ex.getMessage());
|
|
||||||
} catch (IOException ex) {
|
|
||||||
fail(ex.getMessage());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -71,7 +65,8 @@ public class IndexTest extends BaseIndexTestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testGetDirectory() throws Exception {
|
public void testGetDirectory() throws Exception {
|
||||||
System.out.println("getDirectory");
|
System.out.println("getDirectory");
|
||||||
Directory result = Index.getDirectory();
|
Index index = new Index();
|
||||||
|
Directory result = index.getDirectory();
|
||||||
String exp = "\\target\\store\\cpe";
|
String exp = "\\target\\store\\cpe";
|
||||||
// TODO review the generated test code and remove the default call to fail.
|
// TODO review the generated test code and remove the default call to fail.
|
||||||
assertTrue(result.toString().contains(exp));
|
assertTrue(result.toString().contains(exp));
|
||||||
|
|||||||
@@ -1,33 +0,0 @@
|
|||||||
/*
|
|
||||||
* To change this template, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package org.codesecure.dependencycheck.data.cpe;
|
|
||||||
|
|
||||||
import org.codesecure.dependencycheck.data.BaseIndexTestCase;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author jeremy
|
|
||||||
*/
|
|
||||||
public class IndexTestCase extends BaseIndexTestCase {
|
|
||||||
|
|
||||||
public IndexTestCase(String testName) {
|
|
||||||
super(testName);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setUp() throws Exception {
|
|
||||||
super.setUp();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void tearDown() throws Exception {
|
|
||||||
super.tearDown();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testIgnoreThisClass() throws Exception {
|
|
||||||
assertTrue(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -68,10 +68,10 @@ public class ReportGeneratorTest extends BaseIndexTestCase {
|
|||||||
d.addCPEentry("cpe://a:/some:cpe:1.0");
|
d.addCPEentry("cpe://a:/some:cpe:1.0");
|
||||||
|
|
||||||
List<Dependency> dependencies = new ArrayList<Dependency>();
|
List<Dependency> dependencies = new ArrayList<Dependency>();
|
||||||
d.getTitleEvidence().addEvidence("jar","filename","<test>test", Confidence.HIGH);
|
d.getProductEvidence().addEvidence("jar","filename","<test>test", Confidence.HIGH);
|
||||||
d.getTitleEvidence().addEvidence("manifest","vendor","<test>test", Confidence.HIGH);
|
d.getProductEvidence().addEvidence("manifest","vendor","<test>test", Confidence.HIGH);
|
||||||
|
|
||||||
for (Evidence e : d.getTitleEvidence().iterator(Confidence.HIGH)) {
|
for (Evidence e : d.getProductEvidence().iterator(Confidence.HIGH)) {
|
||||||
String t = e.getValue();
|
String t = e.getValue();
|
||||||
}
|
}
|
||||||
dependencies.add(d);
|
dependencies.add(d);
|
||||||
@@ -82,10 +82,10 @@ public class ReportGeneratorTest extends BaseIndexTestCase {
|
|||||||
d2.addCPEentry("cpe://a:/another:cpe:1.0");
|
d2.addCPEentry("cpe://a:/another:cpe:1.0");
|
||||||
d2.addCPEentry("cpe://a:/another:cpe:1.1");
|
d2.addCPEentry("cpe://a:/another:cpe:1.1");
|
||||||
d2.addCPEentry("cpe://a:/another:cpe:1.2");
|
d2.addCPEentry("cpe://a:/another:cpe:1.2");
|
||||||
d2.getTitleEvidence().addEvidence("jar","filename","another.jar", Confidence.HIGH);
|
d2.getProductEvidence().addEvidence("jar","filename","another.jar", Confidence.HIGH);
|
||||||
d2.getTitleEvidence().addEvidence("manifest","vendor","Company A", Confidence.MEDIUM);
|
d2.getProductEvidence().addEvidence("manifest","vendor","Company A", Confidence.MEDIUM);
|
||||||
|
|
||||||
for (Evidence e : d2.getTitleEvidence().iterator(Confidence.HIGH)) {
|
for (Evidence e : d2.getProductEvidence().iterator(Confidence.HIGH)) {
|
||||||
String t = e.getValue();
|
String t = e.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,9 +94,9 @@ public class ReportGeneratorTest extends BaseIndexTestCase {
|
|||||||
Dependency d3 = new Dependency();
|
Dependency d3 = new Dependency();
|
||||||
d3.setFileName("Third.jar");
|
d3.setFileName("Third.jar");
|
||||||
d3.setFilePath("lib/Third.jar");
|
d3.setFilePath("lib/Third.jar");
|
||||||
d3.getTitleEvidence().addEvidence("jar","filename","third.jar", Confidence.HIGH);
|
d3.getProductEvidence().addEvidence("jar","filename","third.jar", Confidence.HIGH);
|
||||||
|
|
||||||
for (Evidence e : d3.getTitleEvidence().iterator(Confidence.HIGH)) {
|
for (Evidence e : d3.getProductEvidence().iterator(Confidence.HIGH)) {
|
||||||
String t = e.getValue();
|
String t = e.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ public class JarAnalyzerTest {
|
|||||||
|
|
||||||
result = instance.insepct(file);
|
result = instance.insepct(file);
|
||||||
boolean found = false;
|
boolean found = false;
|
||||||
for (Evidence e : result.getTitleEvidence()) {
|
for (Evidence e : result.getProductEvidence()) {
|
||||||
if (e.getName().equals("package-title") && e.getValue().equals("org.mortbay.http")) {
|
if (e.getName().equals("package-title") && e.getValue().equals("org.mortbay.http")) {
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
|
|||||||
Reference in New Issue
Block a user