mirror of
https://github.com/ysoftdevs/DependencyCheck.git
synced 2026-03-20 16:24:11 +01:00
Merge branch 'stefanneuhaus-misc_performance_tweaking_and_cleanup'
This commit is contained in:
@@ -43,6 +43,7 @@ import java.util.regex.Pattern;
|
|||||||
import java.util.zip.ZipEntry;
|
import java.util.zip.ZipEntry;
|
||||||
import org.apache.commons.compress.utils.IOUtils;
|
import org.apache.commons.compress.utils.IOUtils;
|
||||||
import org.apache.commons.io.FilenameUtils;
|
import org.apache.commons.io.FilenameUtils;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.jsoup.Jsoup;
|
import org.jsoup.Jsoup;
|
||||||
import org.owasp.dependencycheck.Engine;
|
import org.owasp.dependencycheck.Engine;
|
||||||
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
|
import org.owasp.dependencycheck.analyzer.exception.AnalysisException;
|
||||||
@@ -1150,7 +1151,7 @@ public class JarAnalyzer extends AbstractFileTypeAnalyzer {
|
|||||||
ClassNameInformation(String className) {
|
ClassNameInformation(String className) {
|
||||||
name = className;
|
name = className;
|
||||||
if (name.contains("/")) {
|
if (name.contains("/")) {
|
||||||
final String[] tmp = className.toLowerCase().split("/");
|
final String[] tmp = StringUtils.split(className.toLowerCase(), '/');
|
||||||
int start = 0;
|
int start = 0;
|
||||||
int end = 3;
|
int end = 3;
|
||||||
if ("com".equals(tmp[0]) || "org".equals(tmp[0])) {
|
if ("com".equals(tmp[0]) || "org".equals(tmp[0])) {
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ package org.owasp.dependencycheck.data.cpe;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.net.URLDecoder;
|
import java.net.URLDecoder;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A CPE entry containing the name, vendor, product, and version.
|
* A CPE entry containing the name, vendor, product, and version.
|
||||||
@@ -143,7 +144,8 @@ public class IndexEntry implements Serializable {
|
|||||||
*/
|
*/
|
||||||
public void parseName(String cpeName) throws UnsupportedEncodingException {
|
public void parseName(String cpeName) throws UnsupportedEncodingException {
|
||||||
if (cpeName != null && cpeName.length() > 7) {
|
if (cpeName != null && cpeName.length() > 7) {
|
||||||
final String[] data = cpeName.substring(7).split(":");
|
final String cpeNameWithoutPrefix = cpeName.substring(7);
|
||||||
|
final String[] data = StringUtils.split(cpeNameWithoutPrefix, ':');
|
||||||
if (data.length >= 1) {
|
if (data.length >= 1) {
|
||||||
vendor = URLDecoder.decode(data[0].replace("+", "%2B"), "UTF-8");
|
vendor = URLDecoder.decode(data[0].replace("+", "%2B"), "UTF-8");
|
||||||
if (data.length >= 2) {
|
if (data.length >= 2) {
|
||||||
|
|||||||
@@ -23,8 +23,8 @@ import java.sql.Connection;
|
|||||||
import java.sql.PreparedStatement;
|
import java.sql.PreparedStatement;
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.sql.Statement;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.EnumMap;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -35,6 +35,7 @@ import java.util.MissingResourceException;
|
|||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.ResourceBundle;
|
import java.util.ResourceBundle;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import javax.annotation.concurrent.ThreadSafe;
|
||||||
import org.owasp.dependencycheck.data.cwe.CweDB;
|
import org.owasp.dependencycheck.data.cwe.CweDB;
|
||||||
import org.owasp.dependencycheck.dependency.Reference;
|
import org.owasp.dependencycheck.dependency.Reference;
|
||||||
import org.owasp.dependencycheck.dependency.Vulnerability;
|
import org.owasp.dependencycheck.dependency.Vulnerability;
|
||||||
@@ -47,12 +48,17 @@ import org.owasp.dependencycheck.utils.Settings;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import static org.owasp.dependencycheck.data.nvdcve.CveDB.PreparedStatementCveDb.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The database holding information about the NVD CVE data.
|
* The database holding information about the NVD CVE data.
|
||||||
|
* This class is safe to be accessed from multiple threads in parallel, however
|
||||||
|
* internally only one connection will be used.
|
||||||
*
|
*
|
||||||
* @author Jeremy Long
|
* @author Jeremy Long
|
||||||
*/
|
*/
|
||||||
public class CveDB {
|
@ThreadSafe
|
||||||
|
public final class CveDB {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The logger.
|
* The logger.
|
||||||
@@ -61,18 +67,54 @@ public class CveDB {
|
|||||||
/**
|
/**
|
||||||
* Database connection
|
* Database connection
|
||||||
*/
|
*/
|
||||||
private Connection conn;
|
private Connection connection;
|
||||||
/**
|
/**
|
||||||
* The bundle of statements used when accessing the database.
|
* The bundle of statements used when accessing the database.
|
||||||
*/
|
*/
|
||||||
private ResourceBundle statementBundle = null;
|
private final ResourceBundle statementBundle;
|
||||||
|
/**
|
||||||
|
* Database properties object containing the 'properties' from the database
|
||||||
|
* table.
|
||||||
|
*/
|
||||||
|
private final DatabaseProperties databaseProperties;
|
||||||
|
/**
|
||||||
|
* Does the underlying connection support batch operations?
|
||||||
|
* Currently we do not support batch execution.
|
||||||
|
*/
|
||||||
|
private final boolean batchSupported = false;
|
||||||
|
/**
|
||||||
|
* The prepared statements.
|
||||||
|
*/
|
||||||
|
private final EnumMap<PreparedStatementCveDb, PreparedStatement> preparedStatements;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new CveDB object and opens the database connection. Note, the
|
* The enum value names must match the keys of the statements in the
|
||||||
* connection must be closed by the caller by calling the close method.
|
* statement bundles "dbStatements*.properties".
|
||||||
* ======= Does the underlying connection support batch operations?
|
|
||||||
*/
|
*/
|
||||||
private boolean batchSupported;
|
enum PreparedStatementCveDb {
|
||||||
|
CLEANUP_ORPHANS,
|
||||||
|
COUNT_CPE,
|
||||||
|
DELETE_REFERENCE,
|
||||||
|
DELETE_SOFTWARE,
|
||||||
|
DELETE_VULNERABILITY,
|
||||||
|
INSERT_CPE,
|
||||||
|
INSERT_PROPERTY,
|
||||||
|
INSERT_REFERENCE,
|
||||||
|
INSERT_SOFTWARE,
|
||||||
|
INSERT_VULNERABILITY,
|
||||||
|
MERGE_PROPERTY,
|
||||||
|
SELECT_CPE_ENTRIES,
|
||||||
|
SELECT_CPE_ID,
|
||||||
|
SELECT_CVE_FROM_SOFTWARE,
|
||||||
|
SELECT_PROPERTIES,
|
||||||
|
SELECT_REFERENCES,
|
||||||
|
SELECT_SOFTWARE,
|
||||||
|
SELECT_VENDOR_PRODUCT_LIST,
|
||||||
|
SELECT_VULNERABILITY,
|
||||||
|
SELECT_VULNERABILITY_ID,
|
||||||
|
UPDATE_PROPERTY,
|
||||||
|
UPDATE_VULNERABILITY
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new CveDB object and opens the database connection. Note, the
|
* Creates a new CveDB object and opens the database connection. Note, the
|
||||||
@@ -82,24 +124,28 @@ public class CveDB {
|
|||||||
* database.
|
* database.
|
||||||
*/
|
*/
|
||||||
public CveDB() throws DatabaseException {
|
public CveDB() throws DatabaseException {
|
||||||
super();
|
open();
|
||||||
|
final String databaseProductName = determineDatabaseProductName();
|
||||||
|
statementBundle = databaseProductName != null ?
|
||||||
|
ResourceBundle.getBundle("data/dbStatements", new Locale(databaseProductName)) :
|
||||||
|
ResourceBundle.getBundle("data/dbStatements");
|
||||||
|
preparedStatements = prepareStatements();
|
||||||
|
databaseProperties = new DatabaseProperties(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tries to determine the product name of the database.
|
||||||
|
*
|
||||||
|
* @return the product name of the database if successful, {@code null} else
|
||||||
|
*/
|
||||||
|
private String determineDatabaseProductName() {
|
||||||
try {
|
try {
|
||||||
open();
|
final String databaseProductName = getConnection().getMetaData().getDatabaseProductName();
|
||||||
try {
|
LOGGER.debug("Database product: {}", databaseProductName);
|
||||||
final String databaseProductName = conn.getMetaData().getDatabaseProductName();
|
return databaseProductName;
|
||||||
LOGGER.debug("Database dialect: {}", databaseProductName);
|
} catch (SQLException se) {
|
||||||
final Locale dbDialect = new Locale(databaseProductName);
|
LOGGER.warn("Problem determining database product!", se);
|
||||||
statementBundle = ResourceBundle.getBundle("data/dbStatements", dbDialect);
|
return null;
|
||||||
if ("mysql".equalsIgnoreCase(databaseProductName)) {
|
|
||||||
batchSupported = false;
|
|
||||||
}
|
|
||||||
} catch (SQLException se) {
|
|
||||||
LOGGER.warn("Problem loading database specific dialect!", se);
|
|
||||||
statementBundle = ResourceBundle.getBundle("data/dbStatements");
|
|
||||||
}
|
|
||||||
databaseProperties = new DatabaseProperties(this);
|
|
||||||
} catch (DatabaseException ex) {
|
|
||||||
throw ex;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,8 +154,8 @@ public class CveDB {
|
|||||||
*
|
*
|
||||||
* @return the database connection
|
* @return the database connection
|
||||||
*/
|
*/
|
||||||
protected Connection getConnection() {
|
private Connection getConnection() {
|
||||||
return conn;
|
return connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -119,9 +165,9 @@ public class CveDB {
|
|||||||
* @throws DatabaseException thrown if there is an error opening the
|
* @throws DatabaseException thrown if there is an error opening the
|
||||||
* database connection
|
* database connection
|
||||||
*/
|
*/
|
||||||
public final synchronized void open() throws DatabaseException {
|
public synchronized void open() throws DatabaseException {
|
||||||
if (!isOpen()) {
|
if (!isOpen()) {
|
||||||
conn = ConnectionFactory.getConnection();
|
connection = ConnectionFactory.getConnection();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,9 +176,10 @@ public class CveDB {
|
|||||||
* is done being used.
|
* is done being used.
|
||||||
*/
|
*/
|
||||||
public synchronized void close() {
|
public synchronized void close() {
|
||||||
if (conn != null) {
|
if (isOpen()) {
|
||||||
|
closeStatements();
|
||||||
try {
|
try {
|
||||||
conn.close();
|
getConnection().close();
|
||||||
} catch (SQLException ex) {
|
} catch (SQLException ex) {
|
||||||
LOGGER.error("There was an error attempting to close the CveDB, see the log for more details.");
|
LOGGER.error("There was an error attempting to close the CveDB, see the log for more details.");
|
||||||
LOGGER.debug("", ex);
|
LOGGER.debug("", ex);
|
||||||
@@ -140,7 +187,7 @@ public class CveDB {
|
|||||||
LOGGER.error("There was an exception attempting to close the CveDB, see the log for more details.");
|
LOGGER.error("There was an exception attempting to close the CveDB, see the log for more details.");
|
||||||
LOGGER.debug("", ex);
|
LOGGER.debug("", ex);
|
||||||
}
|
}
|
||||||
conn = null;
|
connection = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,8 +196,57 @@ public class CveDB {
|
|||||||
*
|
*
|
||||||
* @return whether the database connection is open or closed
|
* @return whether the database connection is open or closed
|
||||||
*/
|
*/
|
||||||
public synchronized boolean isOpen() {
|
private boolean isOpen() {
|
||||||
return conn != null;
|
return getConnection() != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepares all statements to be used and returns them.
|
||||||
|
*
|
||||||
|
* @return the prepared statements
|
||||||
|
* @throws DatabaseException thrown if there is an error preparing the statements
|
||||||
|
*/
|
||||||
|
private EnumMap<PreparedStatementCveDb, PreparedStatement> prepareStatements()
|
||||||
|
throws DatabaseException {
|
||||||
|
|
||||||
|
final EnumMap<PreparedStatementCveDb, PreparedStatement> result = new EnumMap<PreparedStatementCveDb, PreparedStatement>(PreparedStatementCveDb.class);
|
||||||
|
for (PreparedStatementCveDb key : values()) {
|
||||||
|
final String statementString = statementBundle.getString(key.name());
|
||||||
|
final PreparedStatement preparedStatement;
|
||||||
|
try {
|
||||||
|
if (key == INSERT_VULNERABILITY || key == INSERT_CPE) {
|
||||||
|
preparedStatement = getConnection().prepareStatement(statementString, new String[]{"id"});
|
||||||
|
} else {
|
||||||
|
preparedStatement = getConnection().prepareStatement(statementString);
|
||||||
|
}
|
||||||
|
} catch (SQLException exception) {
|
||||||
|
throw new DatabaseException(exception);
|
||||||
|
}
|
||||||
|
result.put(key, preparedStatement);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes all prepared statements.
|
||||||
|
*/
|
||||||
|
private void closeStatements() {
|
||||||
|
for (PreparedStatement preparedStatement : preparedStatements.values()) {
|
||||||
|
DBUtils.closeStatement(preparedStatement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the specified prepared statement.
|
||||||
|
*
|
||||||
|
* @param key the prepared statement from {@link PreparedStatementCveDb} to return
|
||||||
|
* @return the prepared statement
|
||||||
|
* @throws SQLException thrown if a SQL Exception occurs
|
||||||
|
*/
|
||||||
|
private PreparedStatement getPreparedStatement(PreparedStatementCveDb key) throws SQLException {
|
||||||
|
final PreparedStatement preparedStatement = preparedStatements.get(key);
|
||||||
|
preparedStatement.clearParameters();
|
||||||
|
return preparedStatement;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -160,8 +256,8 @@ public class CveDB {
|
|||||||
*/
|
*/
|
||||||
public synchronized void commit() throws SQLException {
|
public synchronized void commit() throws SQLException {
|
||||||
//temporary remove this as autocommit is on.
|
//temporary remove this as autocommit is on.
|
||||||
//if (conn != null) {
|
//if (isOpen()) {
|
||||||
// conn.commit();
|
// getConnection().commit();
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -177,11 +273,6 @@ public class CveDB {
|
|||||||
close();
|
close();
|
||||||
super.finalize();
|
super.finalize();
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* Database properties object containing the 'properties' from the database
|
|
||||||
* table.
|
|
||||||
*/
|
|
||||||
private DatabaseProperties databaseProperties;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the value of databaseProperties.
|
* Get the value of databaseProperties.
|
||||||
@@ -205,9 +296,8 @@ public class CveDB {
|
|||||||
public synchronized Set<VulnerableSoftware> getCPEs(String vendor, String product) {
|
public synchronized Set<VulnerableSoftware> getCPEs(String vendor, String product) {
|
||||||
final Set<VulnerableSoftware> cpe = new HashSet<VulnerableSoftware>();
|
final Set<VulnerableSoftware> cpe = new HashSet<VulnerableSoftware>();
|
||||||
ResultSet rs = null;
|
ResultSet rs = null;
|
||||||
PreparedStatement ps = null;
|
|
||||||
try {
|
try {
|
||||||
ps = getConnection().prepareStatement(statementBundle.getString("SELECT_CPE_ENTRIES"));
|
final PreparedStatement ps = getPreparedStatement(SELECT_CPE_ENTRIES);
|
||||||
ps.setString(1, vendor);
|
ps.setString(1, vendor);
|
||||||
ps.setString(2, product);
|
ps.setString(2, product);
|
||||||
rs = ps.executeQuery();
|
rs = ps.executeQuery();
|
||||||
@@ -222,7 +312,6 @@ public class CveDB {
|
|||||||
LOGGER.debug("", ex);
|
LOGGER.debug("", ex);
|
||||||
} finally {
|
} finally {
|
||||||
DBUtils.closeResultSet(rs);
|
DBUtils.closeResultSet(rs);
|
||||||
DBUtils.closeStatement(ps);
|
|
||||||
}
|
}
|
||||||
return cpe;
|
return cpe;
|
||||||
}
|
}
|
||||||
@@ -237,9 +326,8 @@ public class CveDB {
|
|||||||
public synchronized Set<Pair<String, String>> getVendorProductList() throws DatabaseException {
|
public synchronized Set<Pair<String, String>> getVendorProductList() throws DatabaseException {
|
||||||
final Set<Pair<String, String>> data = new HashSet<Pair<String, String>>();
|
final Set<Pair<String, String>> data = new HashSet<Pair<String, String>>();
|
||||||
ResultSet rs = null;
|
ResultSet rs = null;
|
||||||
PreparedStatement ps = null;
|
|
||||||
try {
|
try {
|
||||||
ps = getConnection().prepareStatement(statementBundle.getString("SELECT_VENDOR_PRODUCT_LIST"));
|
final PreparedStatement ps = getPreparedStatement(SELECT_VENDOR_PRODUCT_LIST);
|
||||||
rs = ps.executeQuery();
|
rs = ps.executeQuery();
|
||||||
while (rs.next()) {
|
while (rs.next()) {
|
||||||
data.add(new Pair<String, String>(rs.getString(1), rs.getString(2)));
|
data.add(new Pair<String, String>(rs.getString(1), rs.getString(2)));
|
||||||
@@ -249,7 +337,6 @@ public class CveDB {
|
|||||||
throw new DatabaseException(msg, ex);
|
throw new DatabaseException(msg, ex);
|
||||||
} finally {
|
} finally {
|
||||||
DBUtils.closeResultSet(rs);
|
DBUtils.closeResultSet(rs);
|
||||||
DBUtils.closeStatement(ps);
|
|
||||||
}
|
}
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
@@ -261,10 +348,9 @@ public class CveDB {
|
|||||||
*/
|
*/
|
||||||
public synchronized Properties getProperties() {
|
public synchronized Properties getProperties() {
|
||||||
final Properties prop = new Properties();
|
final Properties prop = new Properties();
|
||||||
PreparedStatement ps = null;
|
|
||||||
ResultSet rs = null;
|
ResultSet rs = null;
|
||||||
try {
|
try {
|
||||||
ps = getConnection().prepareStatement(statementBundle.getString("SELECT_PROPERTIES"));
|
final PreparedStatement ps = getPreparedStatement(SELECT_PROPERTIES);
|
||||||
rs = ps.executeQuery();
|
rs = ps.executeQuery();
|
||||||
while (rs.next()) {
|
while (rs.next()) {
|
||||||
prop.setProperty(rs.getString(1), rs.getString(2));
|
prop.setProperty(rs.getString(1), rs.getString(2));
|
||||||
@@ -273,7 +359,6 @@ public class CveDB {
|
|||||||
LOGGER.error("An unexpected SQL Exception occurred; please see the verbose log for more details.");
|
LOGGER.error("An unexpected SQL Exception occurred; please see the verbose log for more details.");
|
||||||
LOGGER.debug("", ex);
|
LOGGER.debug("", ex);
|
||||||
} finally {
|
} finally {
|
||||||
DBUtils.closeStatement(ps);
|
|
||||||
DBUtils.closeResultSet(rs);
|
DBUtils.closeResultSet(rs);
|
||||||
}
|
}
|
||||||
return prop;
|
return prop;
|
||||||
@@ -288,31 +373,20 @@ public class CveDB {
|
|||||||
public synchronized void saveProperty(String key, String value) {
|
public synchronized void saveProperty(String key, String value) {
|
||||||
try {
|
try {
|
||||||
try {
|
try {
|
||||||
final PreparedStatement mergeProperty = getConnection().prepareStatement(statementBundle.getString("MERGE_PROPERTY"));
|
final PreparedStatement mergeProperty = getPreparedStatement(MERGE_PROPERTY);
|
||||||
try {
|
mergeProperty.setString(1, key);
|
||||||
mergeProperty.setString(1, key);
|
mergeProperty.setString(2, value);
|
||||||
mergeProperty.setString(2, value);
|
mergeProperty.executeUpdate();
|
||||||
mergeProperty.executeUpdate();
|
|
||||||
} finally {
|
|
||||||
DBUtils.closeStatement(mergeProperty);
|
|
||||||
}
|
|
||||||
} catch (MissingResourceException mre) {
|
} catch (MissingResourceException mre) {
|
||||||
// No Merge statement, so doing an Update/Insert...
|
// No Merge statement, so doing an Update/Insert...
|
||||||
PreparedStatement updateProperty = null;
|
final PreparedStatement updateProperty = getPreparedStatement(UPDATE_PROPERTY);
|
||||||
PreparedStatement insertProperty = null;
|
updateProperty.setString(1, value);
|
||||||
try {
|
updateProperty.setString(2, key);
|
||||||
updateProperty = getConnection().prepareStatement(statementBundle.getString("UPDATE_PROPERTY"));
|
if (updateProperty.executeUpdate() == 0) {
|
||||||
updateProperty.setString(1, value);
|
final PreparedStatement insertProperty = getPreparedStatement(INSERT_PROPERTY);
|
||||||
updateProperty.setString(2, key);
|
insertProperty.setString(1, key);
|
||||||
if (updateProperty.executeUpdate() == 0) {
|
insertProperty.setString(2, value);
|
||||||
insertProperty = getConnection().prepareStatement(statementBundle.getString("INSERT_PROPERTY"));
|
insertProperty.executeUpdate();
|
||||||
insertProperty.setString(1, key);
|
|
||||||
insertProperty.setString(2, value);
|
|
||||||
insertProperty.executeUpdate();
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
DBUtils.closeStatement(updateProperty);
|
|
||||||
DBUtils.closeStatement(insertProperty);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (SQLException ex) {
|
} catch (SQLException ex) {
|
||||||
@@ -338,10 +412,9 @@ public class CveDB {
|
|||||||
final DependencyVersion detectedVersion = parseDependencyVersion(cpe);
|
final DependencyVersion detectedVersion = parseDependencyVersion(cpe);
|
||||||
final List<Vulnerability> vulnerabilities = new ArrayList<Vulnerability>();
|
final List<Vulnerability> vulnerabilities = new ArrayList<Vulnerability>();
|
||||||
|
|
||||||
PreparedStatement ps = null;
|
|
||||||
ResultSet rs = null;
|
ResultSet rs = null;
|
||||||
try {
|
try {
|
||||||
ps = getConnection().prepareStatement(statementBundle.getString("SELECT_CVE_FROM_SOFTWARE"));
|
final PreparedStatement ps = getPreparedStatement(SELECT_CVE_FROM_SOFTWARE);
|
||||||
ps.setString(1, cpe.getVendor());
|
ps.setString(1, cpe.getVendor());
|
||||||
ps.setString(2, cpe.getProduct());
|
ps.setString(2, cpe.getProduct());
|
||||||
rs = ps.executeQuery();
|
rs = ps.executeQuery();
|
||||||
@@ -377,7 +450,6 @@ public class CveDB {
|
|||||||
throw new DatabaseException("Exception retrieving vulnerability for " + cpeStr, ex);
|
throw new DatabaseException("Exception retrieving vulnerability for " + cpeStr, ex);
|
||||||
} finally {
|
} finally {
|
||||||
DBUtils.closeResultSet(rs);
|
DBUtils.closeResultSet(rs);
|
||||||
DBUtils.closeStatement(ps);
|
|
||||||
}
|
}
|
||||||
return vulnerabilities;
|
return vulnerabilities;
|
||||||
}
|
}
|
||||||
@@ -390,16 +462,13 @@ public class CveDB {
|
|||||||
* @throws DatabaseException if an exception occurs
|
* @throws DatabaseException if an exception occurs
|
||||||
*/
|
*/
|
||||||
public synchronized Vulnerability getVulnerability(String cve) throws DatabaseException {
|
public synchronized Vulnerability getVulnerability(String cve) throws DatabaseException {
|
||||||
PreparedStatement psV = null;
|
|
||||||
PreparedStatement psR = null;
|
|
||||||
PreparedStatement psS = null;
|
|
||||||
ResultSet rsV = null;
|
ResultSet rsV = null;
|
||||||
ResultSet rsR = null;
|
ResultSet rsR = null;
|
||||||
ResultSet rsS = null;
|
ResultSet rsS = null;
|
||||||
Vulnerability vuln = null;
|
Vulnerability vuln = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
psV = getConnection().prepareStatement(statementBundle.getString("SELECT_VULNERABILITY"));
|
final PreparedStatement psV = getPreparedStatement(SELECT_VULNERABILITY);
|
||||||
psV.setString(1, cve);
|
psV.setString(1, cve);
|
||||||
rsV = psV.executeQuery();
|
rsV = psV.executeQuery();
|
||||||
if (rsV.next()) {
|
if (rsV.next()) {
|
||||||
@@ -423,13 +492,14 @@ public class CveDB {
|
|||||||
vuln.setCvssIntegrityImpact(rsV.getString(9));
|
vuln.setCvssIntegrityImpact(rsV.getString(9));
|
||||||
vuln.setCvssAvailabilityImpact(rsV.getString(10));
|
vuln.setCvssAvailabilityImpact(rsV.getString(10));
|
||||||
|
|
||||||
psR = getConnection().prepareStatement(statementBundle.getString("SELECT_REFERENCES"));
|
final PreparedStatement psR = getPreparedStatement(SELECT_REFERENCES);
|
||||||
psR.setInt(1, cveId);
|
psR.setInt(1, cveId);
|
||||||
rsR = psR.executeQuery();
|
rsR = psR.executeQuery();
|
||||||
while (rsR.next()) {
|
while (rsR.next()) {
|
||||||
vuln.addReference(rsR.getString(1), rsR.getString(2), rsR.getString(3));
|
vuln.addReference(rsR.getString(1), rsR.getString(2), rsR.getString(3));
|
||||||
}
|
}
|
||||||
psS = getConnection().prepareStatement(statementBundle.getString("SELECT_SOFTWARE"));
|
|
||||||
|
final PreparedStatement psS = getPreparedStatement(SELECT_SOFTWARE);
|
||||||
psS.setInt(1, cveId);
|
psS.setInt(1, cveId);
|
||||||
rsS = psS.executeQuery();
|
rsS = psS.executeQuery();
|
||||||
while (rsS.next()) {
|
while (rsS.next()) {
|
||||||
@@ -448,9 +518,6 @@ public class CveDB {
|
|||||||
DBUtils.closeResultSet(rsV);
|
DBUtils.closeResultSet(rsV);
|
||||||
DBUtils.closeResultSet(rsR);
|
DBUtils.closeResultSet(rsR);
|
||||||
DBUtils.closeResultSet(rsS);
|
DBUtils.closeResultSet(rsS);
|
||||||
DBUtils.closeStatement(psV);
|
|
||||||
DBUtils.closeStatement(psR);
|
|
||||||
DBUtils.closeStatement(psS);
|
|
||||||
}
|
}
|
||||||
return vuln;
|
return vuln;
|
||||||
}
|
}
|
||||||
@@ -463,52 +530,31 @@ public class CveDB {
|
|||||||
* @throws DatabaseException is thrown if the database
|
* @throws DatabaseException is thrown if the database
|
||||||
*/
|
*/
|
||||||
public synchronized void updateVulnerability(Vulnerability vuln) throws DatabaseException {
|
public synchronized void updateVulnerability(Vulnerability vuln) throws DatabaseException {
|
||||||
PreparedStatement selectVulnerabilityId = null;
|
|
||||||
PreparedStatement deleteVulnerability = null;
|
|
||||||
PreparedStatement deleteReferences = null;
|
|
||||||
PreparedStatement deleteSoftware = null;
|
|
||||||
PreparedStatement updateVulnerability = null;
|
|
||||||
PreparedStatement insertVulnerability = null;
|
|
||||||
PreparedStatement insertReference = null;
|
|
||||||
PreparedStatement selectCpeId = null;
|
|
||||||
PreparedStatement insertCpe = null;
|
|
||||||
PreparedStatement insertSoftware = null;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
selectVulnerabilityId = getConnection().prepareStatement(statementBundle.getString("SELECT_VULNERABILITY_ID"));
|
|
||||||
deleteVulnerability = getConnection().prepareStatement(statementBundle.getString("DELETE_VULNERABILITY"));
|
|
||||||
deleteReferences = getConnection().prepareStatement(statementBundle.getString("DELETE_REFERENCE"));
|
|
||||||
deleteSoftware = getConnection().prepareStatement(statementBundle.getString("DELETE_SOFTWARE"));
|
|
||||||
updateVulnerability = getConnection().prepareStatement(statementBundle.getString("UPDATE_VULNERABILITY"));
|
|
||||||
final String[] ids = {"id"};
|
|
||||||
insertVulnerability = getConnection().prepareStatement(statementBundle.getString("INSERT_VULNERABILITY"),
|
|
||||||
//Statement.RETURN_GENERATED_KEYS);
|
|
||||||
ids);
|
|
||||||
insertReference = getConnection().prepareStatement(statementBundle.getString("INSERT_REFERENCE"));
|
|
||||||
selectCpeId = getConnection().prepareStatement(statementBundle.getString("SELECT_CPE_ID"));
|
|
||||||
insertCpe = getConnection().prepareStatement(statementBundle.getString("INSERT_CPE"),
|
|
||||||
//Statement.RETURN_GENERATED_KEYS);
|
|
||||||
ids);
|
|
||||||
insertSoftware = getConnection().prepareStatement(statementBundle.getString("INSERT_SOFTWARE"));
|
|
||||||
int vulnerabilityId = 0;
|
int vulnerabilityId = 0;
|
||||||
|
final PreparedStatement selectVulnerabilityId = getPreparedStatement(SELECT_VULNERABILITY_ID);
|
||||||
selectVulnerabilityId.setString(1, vuln.getName());
|
selectVulnerabilityId.setString(1, vuln.getName());
|
||||||
ResultSet rs = selectVulnerabilityId.executeQuery();
|
ResultSet rs = selectVulnerabilityId.executeQuery();
|
||||||
if (rs.next()) {
|
if (rs.next()) {
|
||||||
vulnerabilityId = rs.getInt(1);
|
vulnerabilityId = rs.getInt(1);
|
||||||
// first delete any existing vulnerability info. We don't know what was updated. yes, slower but atm easier.
|
// first delete any existing vulnerability info. We don't know what was updated. yes, slower but atm easier.
|
||||||
deleteReferences.setInt(1, vulnerabilityId);
|
final PreparedStatement deleteReference = getPreparedStatement(DELETE_REFERENCE);
|
||||||
deleteReferences.execute();
|
deleteReference.setInt(1, vulnerabilityId);
|
||||||
|
deleteReference.execute();
|
||||||
|
|
||||||
|
final PreparedStatement deleteSoftware = getPreparedStatement(DELETE_SOFTWARE);
|
||||||
deleteSoftware.setInt(1, vulnerabilityId);
|
deleteSoftware.setInt(1, vulnerabilityId);
|
||||||
deleteSoftware.execute();
|
deleteSoftware.execute();
|
||||||
}
|
}
|
||||||
DBUtils.closeResultSet(rs);
|
DBUtils.closeResultSet(rs);
|
||||||
rs = null;
|
|
||||||
|
|
||||||
if (vulnerabilityId != 0) {
|
if (vulnerabilityId != 0) {
|
||||||
if (vuln.getDescription().contains("** REJECT **")) {
|
if (vuln.getDescription().contains("** REJECT **")) {
|
||||||
|
final PreparedStatement deleteVulnerability = getPreparedStatement(DELETE_VULNERABILITY);
|
||||||
deleteVulnerability.setInt(1, vulnerabilityId);
|
deleteVulnerability.setInt(1, vulnerabilityId);
|
||||||
deleteVulnerability.executeUpdate();
|
deleteVulnerability.executeUpdate();
|
||||||
} else {
|
} else {
|
||||||
|
final PreparedStatement updateVulnerability = getPreparedStatement(UPDATE_VULNERABILITY);
|
||||||
updateVulnerability.setString(1, vuln.getDescription());
|
updateVulnerability.setString(1, vuln.getDescription());
|
||||||
updateVulnerability.setString(2, vuln.getCwe());
|
updateVulnerability.setString(2, vuln.getCwe());
|
||||||
updateVulnerability.setFloat(3, vuln.getCvssScore());
|
updateVulnerability.setFloat(3, vuln.getCvssScore());
|
||||||
@@ -522,6 +568,7 @@ public class CveDB {
|
|||||||
updateVulnerability.executeUpdate();
|
updateVulnerability.executeUpdate();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
final PreparedStatement insertVulnerability = getPreparedStatement(INSERT_VULNERABILITY);
|
||||||
insertVulnerability.setString(1, vuln.getName());
|
insertVulnerability.setString(1, vuln.getName());
|
||||||
insertVulnerability.setString(2, vuln.getDescription());
|
insertVulnerability.setString(2, vuln.getDescription());
|
||||||
insertVulnerability.setString(3, vuln.getCwe());
|
insertVulnerability.setString(3, vuln.getCwe());
|
||||||
@@ -542,10 +589,13 @@ public class CveDB {
|
|||||||
throw new DatabaseException(msg, ex);
|
throw new DatabaseException(msg, ex);
|
||||||
} finally {
|
} finally {
|
||||||
DBUtils.closeResultSet(rs);
|
DBUtils.closeResultSet(rs);
|
||||||
rs = null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final PreparedStatement insertReference = getPreparedStatement(INSERT_REFERENCE);
|
||||||
|
if (batchSupported) {
|
||||||
|
insertReference.clearBatch();
|
||||||
|
}
|
||||||
for (Reference r : vuln.getReferences()) {
|
for (Reference r : vuln.getReferences()) {
|
||||||
insertReference.setInt(1, vulnerabilityId);
|
insertReference.setInt(1, vulnerabilityId);
|
||||||
insertReference.setString(2, r.getName());
|
insertReference.setString(2, r.getName());
|
||||||
@@ -563,8 +613,13 @@ public class CveDB {
|
|||||||
insertReference.executeBatch();
|
insertReference.executeBatch();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final PreparedStatement insertSoftware = getPreparedStatement(INSERT_SOFTWARE);
|
||||||
|
if (batchSupported) {
|
||||||
|
insertSoftware.clearBatch();
|
||||||
|
}
|
||||||
for (VulnerableSoftware s : vuln.getVulnerableSoftware()) {
|
for (VulnerableSoftware s : vuln.getVulnerableSoftware()) {
|
||||||
int cpeProductId = 0;
|
int cpeProductId = 0;
|
||||||
|
final PreparedStatement selectCpeId = getPreparedStatement(SELECT_CPE_ID);
|
||||||
selectCpeId.setString(1, s.getName());
|
selectCpeId.setString(1, s.getName());
|
||||||
try {
|
try {
|
||||||
rs = selectCpeId.executeQuery();
|
rs = selectCpeId.executeQuery();
|
||||||
@@ -575,10 +630,10 @@ public class CveDB {
|
|||||||
throw new DatabaseException("Unable to get primary key for new cpe: " + s.getName(), ex);
|
throw new DatabaseException("Unable to get primary key for new cpe: " + s.getName(), ex);
|
||||||
} finally {
|
} finally {
|
||||||
DBUtils.closeResultSet(rs);
|
DBUtils.closeResultSet(rs);
|
||||||
rs = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cpeProductId == 0) {
|
if (cpeProductId == 0) {
|
||||||
|
final PreparedStatement insertCpe = getPreparedStatement(INSERT_CPE);
|
||||||
insertCpe.setString(1, s.getName());
|
insertCpe.setString(1, s.getName());
|
||||||
insertCpe.setString(2, s.getVendor());
|
insertCpe.setString(2, s.getVendor());
|
||||||
insertCpe.setString(3, s.getProduct());
|
insertCpe.setString(3, s.getProduct());
|
||||||
@@ -605,7 +660,7 @@ public class CveDB {
|
|||||||
} catch (SQLException ex) {
|
} catch (SQLException ex) {
|
||||||
if (ex.getMessage().contains("Duplicate entry")) {
|
if (ex.getMessage().contains("Duplicate entry")) {
|
||||||
final String msg = String.format("Duplicate software key identified in '%s:%s'", vuln.getName(), s.getName());
|
final String msg = String.format("Duplicate software key identified in '%s:%s'", vuln.getName(), s.getName());
|
||||||
LOGGER.debug(msg, ex);
|
LOGGER.info(msg, ex);
|
||||||
} else {
|
} else {
|
||||||
throw ex;
|
throw ex;
|
||||||
}
|
}
|
||||||
@@ -619,17 +674,6 @@ public class CveDB {
|
|||||||
final String msg = String.format("Error updating '%s'", vuln.getName());
|
final String msg = String.format("Error updating '%s'", vuln.getName());
|
||||||
LOGGER.debug(msg, ex);
|
LOGGER.debug(msg, ex);
|
||||||
throw new DatabaseException(msg, ex);
|
throw new DatabaseException(msg, ex);
|
||||||
} finally {
|
|
||||||
DBUtils.closeStatement(selectVulnerabilityId);
|
|
||||||
DBUtils.closeStatement(deleteReferences);
|
|
||||||
DBUtils.closeStatement(deleteSoftware);
|
|
||||||
DBUtils.closeStatement(updateVulnerability);
|
|
||||||
DBUtils.closeStatement(deleteVulnerability);
|
|
||||||
DBUtils.closeStatement(insertVulnerability);
|
|
||||||
DBUtils.closeStatement(insertReference);
|
|
||||||
DBUtils.closeStatement(selectCpeId);
|
|
||||||
DBUtils.closeStatement(insertCpe);
|
|
||||||
DBUtils.closeStatement(insertSoftware);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -639,17 +683,16 @@ public class CveDB {
|
|||||||
* @return <code>true</code> if data exists; otherwise <code>false</code>
|
* @return <code>true</code> if data exists; otherwise <code>false</code>
|
||||||
*/
|
*/
|
||||||
public synchronized boolean dataExists() {
|
public synchronized boolean dataExists() {
|
||||||
Statement cs = null;
|
|
||||||
ResultSet rs = null;
|
ResultSet rs = null;
|
||||||
try {
|
try {
|
||||||
cs = conn.createStatement();
|
final PreparedStatement cs = getPreparedStatement(COUNT_CPE);
|
||||||
rs = cs.executeQuery("SELECT COUNT(*) records FROM cpeEntry");
|
rs = cs.executeQuery();
|
||||||
if (rs.next()) {
|
if (rs.next()) {
|
||||||
if (rs.getInt(1) > 0) {
|
if (rs.getInt(1) > 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (SQLException ex) {
|
} catch (Exception ex) {
|
||||||
String dd;
|
String dd;
|
||||||
try {
|
try {
|
||||||
dd = Settings.getDataDirectory().getAbsolutePath();
|
dd = Settings.getDataDirectory().getAbsolutePath();
|
||||||
@@ -664,7 +707,6 @@ public class CveDB {
|
|||||||
LOGGER.debug("", ex);
|
LOGGER.debug("", ex);
|
||||||
} finally {
|
} finally {
|
||||||
DBUtils.closeResultSet(rs);
|
DBUtils.closeResultSet(rs);
|
||||||
DBUtils.closeStatement(cs);
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -675,17 +717,14 @@ public class CveDB {
|
|||||||
* ensure orphan entries are removed.
|
* ensure orphan entries are removed.
|
||||||
*/
|
*/
|
||||||
public synchronized void cleanupDatabase() {
|
public synchronized void cleanupDatabase() {
|
||||||
PreparedStatement ps = null;
|
|
||||||
try {
|
try {
|
||||||
ps = getConnection().prepareStatement(statementBundle.getString("CLEANUP_ORPHANS"));
|
final PreparedStatement ps = getPreparedStatement(CLEANUP_ORPHANS);
|
||||||
if (ps != null) {
|
if (ps != null) {
|
||||||
ps.executeUpdate();
|
ps.executeUpdate();
|
||||||
}
|
}
|
||||||
} catch (SQLException ex) {
|
} catch (SQLException ex) {
|
||||||
LOGGER.error("An unexpected SQL Exception occurred; please see the verbose log for more details.");
|
LOGGER.error("An unexpected SQL Exception occurred; please see the verbose log for more details.");
|
||||||
LOGGER.debug("", ex);
|
LOGGER.debug("", ex);
|
||||||
} finally {
|
|
||||||
DBUtils.closeStatement(ps);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -819,7 +858,6 @@ public class CveDB {
|
|||||||
ps.executeUpdate();
|
ps.executeUpdate();
|
||||||
} catch (SQLException ex) {
|
} catch (SQLException ex) {
|
||||||
LOGGER.error("Unable to delete CPE dictionary entries", ex);
|
LOGGER.error("Unable to delete CPE dictionary entries", ex);
|
||||||
} finally {
|
|
||||||
DBUtils.closeStatement(ps);
|
DBUtils.closeStatement(ps);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -844,7 +882,6 @@ public class CveDB {
|
|||||||
ps.executeUpdate();
|
ps.executeUpdate();
|
||||||
} catch (SQLException ex) {
|
} catch (SQLException ex) {
|
||||||
LOGGER.error("Unable to add CPE dictionary entry", ex);
|
LOGGER.error("Unable to add CPE dictionary entry", ex);
|
||||||
} finally {
|
|
||||||
DBUtils.closeStatement(ps);
|
DBUtils.closeStatement(ps);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import java.util.Map;
|
|||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
|
import javax.annotation.concurrent.ThreadSafe;
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
import org.joda.time.format.DateTimeFormat;
|
import org.joda.time.format.DateTimeFormat;
|
||||||
import org.joda.time.format.DateTimeFormatter;
|
import org.joda.time.format.DateTimeFormatter;
|
||||||
@@ -31,9 +32,11 @@ import org.slf4j.LoggerFactory;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a wrapper around a set of properties that are stored in the database.
|
* This is a wrapper around a set of properties that are stored in the database.
|
||||||
|
* This class is safe to be accessed from multiple threads in parallel.
|
||||||
*
|
*
|
||||||
* @author Jeremy Long
|
* @author Jeremy Long
|
||||||
*/
|
*/
|
||||||
|
@ThreadSafe
|
||||||
public class DatabaseProperties {
|
public class DatabaseProperties {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.owasp.dependencycheck.data.update.cpe;
|
package org.owasp.dependencycheck.data.update.cpe;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.net.URLDecoder;
|
import java.net.URLDecoder;
|
||||||
import org.owasp.dependencycheck.data.update.exception.InvalidDataException;
|
import org.owasp.dependencycheck.data.update.exception.InvalidDataException;
|
||||||
@@ -36,7 +37,8 @@ public class Cpe {
|
|||||||
*/
|
*/
|
||||||
public Cpe(String value) throws UnsupportedEncodingException, InvalidDataException {
|
public Cpe(String value) throws UnsupportedEncodingException, InvalidDataException {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
final String[] data = value.substring(7).split(":");
|
final String valueWithoutPrefix = value.substring(7);
|
||||||
|
final String[] data = StringUtils.split(valueWithoutPrefix, ':');
|
||||||
if (data.length >= 2) {
|
if (data.length >= 2) {
|
||||||
vendor = URLDecoder.decode(data[0].replace("+", "%2B"), "UTF-8");
|
vendor = URLDecoder.decode(data[0].replace("+", "%2B"), "UTF-8");
|
||||||
product = URLDecoder.decode(data[1].replace("+", "%2B"), "UTF-8");
|
product = URLDecoder.decode(data[1].replace("+", "%2B"), "UTF-8");
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ import org.xml.sax.SAXException;
|
|||||||
import org.xml.sax.SAXNotSupportedException;
|
import org.xml.sax.SAXNotSupportedException;
|
||||||
import org.xml.sax.helpers.DefaultHandler;
|
import org.xml.sax.helpers.DefaultHandler;
|
||||||
|
|
||||||
|
import static org.owasp.dependencycheck.data.update.nvd.NvdCve20Handler.AttributeValues.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A SAX Handler that will parse the NVD CVE XML (schema version 2.0).
|
* A SAX Handler that will parse the NVD CVE XML (schema version 2.0).
|
||||||
*
|
*
|
||||||
@@ -48,6 +50,18 @@ public class NvdCve20Handler extends DefaultHandler {
|
|||||||
* the current supported schema version.
|
* the current supported schema version.
|
||||||
*/
|
*/
|
||||||
private static final String CURRENT_SCHEMA_VERSION = "2.0";
|
private static final String CURRENT_SCHEMA_VERSION = "2.0";
|
||||||
|
/**
|
||||||
|
* a possible attribute value of the {@link AttributeValues#XML_LANG} attribute
|
||||||
|
*/
|
||||||
|
private static final String EN = "en";
|
||||||
|
/**
|
||||||
|
* the prefix of the node text of a CPE
|
||||||
|
*/
|
||||||
|
private static final String CPE_NODE_TEXT_PREFIX = "cpe:/a:";
|
||||||
|
/**
|
||||||
|
* the node text of an entry marked for deletion
|
||||||
|
*/
|
||||||
|
private static final String REJECT_NODE_TEXT = "** REJECT **";
|
||||||
/**
|
/**
|
||||||
* the current element.
|
* the current element.
|
||||||
*/
|
*/
|
||||||
@@ -111,30 +125,30 @@ public class NvdCve20Handler extends DefaultHandler {
|
|||||||
if (current.isEntryNode()) {
|
if (current.isEntryNode()) {
|
||||||
hasApplicationCpe = false;
|
hasApplicationCpe = false;
|
||||||
vulnerability = new Vulnerability();
|
vulnerability = new Vulnerability();
|
||||||
vulnerability.setName(attributes.getValue("id"));
|
vulnerability.setName(attributes.getValue(ID));
|
||||||
} else if (current.isVulnProductNode()) {
|
} else if (current.isVulnProductNode()) {
|
||||||
nodeText = new StringBuilder(100);
|
nodeText = new StringBuilder(100);
|
||||||
} else if (current.isVulnReferencesNode()) {
|
} else if (current.isVulnReferencesNode()) {
|
||||||
final String lang = attributes.getValue("xml:lang");
|
final String lang = attributes.getValue(XML_LANG);
|
||||||
if ("en".equals(lang)) {
|
if (EN.equals(lang)) {
|
||||||
reference = new Reference();
|
reference = new Reference();
|
||||||
} else {
|
} else {
|
||||||
reference = null;
|
reference = null;
|
||||||
}
|
}
|
||||||
} else if (reference != null && current.isVulnReferenceNode()) {
|
} else if (reference != null && current.isVulnReferenceNode()) {
|
||||||
reference.setUrl(attributes.getValue("href"));
|
reference.setUrl(attributes.getValue(HREF));
|
||||||
nodeText = new StringBuilder(130);
|
nodeText = new StringBuilder(130);
|
||||||
} else if (reference != null && current.isVulnSourceNode()) {
|
} else if (reference != null && current.isVulnSourceNode()) {
|
||||||
nodeText = new StringBuilder(30);
|
nodeText = new StringBuilder(30);
|
||||||
} else if (current.isVulnSummaryNode()) {
|
} else if (current.isVulnSummaryNode()) {
|
||||||
nodeText = new StringBuilder(500);
|
nodeText = new StringBuilder(500);
|
||||||
} else if (current.isNVDNode()) {
|
} else if (current.isNVDNode()) {
|
||||||
final String nvdVer = attributes.getValue("nvd_xml_version");
|
final String nvdVer = attributes.getValue(NVD_XML_VERSION);
|
||||||
if (!CURRENT_SCHEMA_VERSION.equals(nvdVer)) {
|
if (!CURRENT_SCHEMA_VERSION.equals(nvdVer)) {
|
||||||
throw new SAXNotSupportedException("Schema version " + nvdVer + " is not supported");
|
throw new SAXNotSupportedException("Schema version " + nvdVer + " is not supported");
|
||||||
}
|
}
|
||||||
} else if (current.isVulnCWENode()) {
|
} else if (current.isVulnCWENode()) {
|
||||||
vulnerability.setCwe(attributes.getValue("id"));
|
vulnerability.setCwe(attributes.getValue(ID));
|
||||||
} else if (current.isCVSSScoreNode()) {
|
} else if (current.isCVSSScoreNode()) {
|
||||||
nodeText = new StringBuilder(5);
|
nodeText = new StringBuilder(5);
|
||||||
} else if (current.isCVSSAccessVectorNode()) {
|
} else if (current.isCVSSAccessVectorNode()) {
|
||||||
@@ -206,7 +220,7 @@ public class NvdCve20Handler extends DefaultHandler {
|
|||||||
nodeText = null;
|
nodeText = null;
|
||||||
} else if (current.isVulnProductNode()) {
|
} else if (current.isVulnProductNode()) {
|
||||||
final String cpe = nodeText.toString();
|
final String cpe = nodeText.toString();
|
||||||
if (cpe.startsWith("cpe:/a:")) {
|
if (cpe.startsWith(CPE_NODE_TEXT_PREFIX)) {
|
||||||
hasApplicationCpe = true;
|
hasApplicationCpe = true;
|
||||||
vulnerability.addVulnerableSoftware(cpe);
|
vulnerability.addVulnerableSoftware(cpe);
|
||||||
}
|
}
|
||||||
@@ -222,7 +236,7 @@ public class NvdCve20Handler extends DefaultHandler {
|
|||||||
nodeText = null;
|
nodeText = null;
|
||||||
} else if (current.isVulnSummaryNode()) {
|
} else if (current.isVulnSummaryNode()) {
|
||||||
vulnerability.setDescription(nodeText.toString());
|
vulnerability.setDescription(nodeText.toString());
|
||||||
if (nodeText.indexOf("** REJECT **") >= 0) {
|
if (nodeText.indexOf(REJECT_NODE_TEXT) >= 0) {
|
||||||
hasApplicationCpe = true; //ensure we process this to delete the vuln
|
hasApplicationCpe = true; //ensure we process this to delete the vuln
|
||||||
}
|
}
|
||||||
nodeText = null;
|
nodeText = null;
|
||||||
@@ -492,4 +506,27 @@ public class NvdCve20Handler extends DefaultHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// </editor-fold>
|
// </editor-fold>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A simple class to maintain information about the attribute values encountered while parsing the NVD CVE XML.
|
||||||
|
*/
|
||||||
|
protected static class AttributeValues {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An attribute in the NVD CVE Schema 2.0
|
||||||
|
*/
|
||||||
|
protected static final String ID = "id";
|
||||||
|
/**
|
||||||
|
* An attribute in the NVD CVE Schema 2.0
|
||||||
|
*/
|
||||||
|
protected static final String XML_LANG = "xml:lang";
|
||||||
|
/**
|
||||||
|
* An attribute in the NVD CVE Schema 2.0
|
||||||
|
*/
|
||||||
|
protected static final String HREF = "href";
|
||||||
|
/**
|
||||||
|
* An attribute in the NVD CVE Schema 2.0
|
||||||
|
*/
|
||||||
|
protected static final String NVD_XML_VERSION = "nvd_xml_version";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -230,10 +230,9 @@ public class Vulnerability implements Serializable, Comparable<Vulnerability> {
|
|||||||
* Adds an entry for vulnerable software.
|
* Adds an entry for vulnerable software.
|
||||||
*
|
*
|
||||||
* @param cpe string representation of a CPE entry
|
* @param cpe string representation of a CPE entry
|
||||||
* @return if the add succeeded
|
|
||||||
*/
|
*/
|
||||||
public boolean addVulnerableSoftware(String cpe) {
|
public void addVulnerableSoftware(String cpe) {
|
||||||
return addVulnerableSoftware(cpe, null);
|
addVulnerableSoftware(cpe, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -242,28 +241,26 @@ public class Vulnerability implements Serializable, Comparable<Vulnerability> {
|
|||||||
* @param cpe string representation of a cpe
|
* @param cpe string representation of a cpe
|
||||||
* @param previousVersion the previous version (previousVersion - cpe would
|
* @param previousVersion the previous version (previousVersion - cpe would
|
||||||
* be considered vulnerable)
|
* be considered vulnerable)
|
||||||
* @return if the add succeeded
|
|
||||||
*/
|
*/
|
||||||
public boolean addVulnerableSoftware(String cpe, String previousVersion) {
|
public void addVulnerableSoftware(String cpe, String previousVersion) {
|
||||||
final VulnerableSoftware vs = new VulnerableSoftware();
|
final VulnerableSoftware vs = new VulnerableSoftware();
|
||||||
vs.setCpe(cpe);
|
vs.setCpe(cpe);
|
||||||
if (previousVersion != null) {
|
if (previousVersion != null) {
|
||||||
vs.setPreviousVersion(previousVersion);
|
vs.setPreviousVersion(previousVersion);
|
||||||
}
|
}
|
||||||
return updateVulnerableSoftware(vs);
|
updateVulnerableSoftware(vs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds or updates a vulnerable software entry.
|
* Adds or updates a vulnerable software entry.
|
||||||
*
|
*
|
||||||
* @param vulnSoftware the vulnerable software
|
* @param vulnSoftware the vulnerable software
|
||||||
* @return if the update succeeded
|
|
||||||
*/
|
*/
|
||||||
public boolean updateVulnerableSoftware(VulnerableSoftware vulnSoftware) {
|
public void updateVulnerableSoftware(VulnerableSoftware vulnSoftware) {
|
||||||
if (vulnerableSoftware.contains(vulnSoftware)) {
|
if (vulnerableSoftware.contains(vulnSoftware)) {
|
||||||
vulnerableSoftware.remove(vulnSoftware);
|
vulnerableSoftware.remove(vulnSoftware);
|
||||||
}
|
}
|
||||||
return vulnerableSoftware.add(vulnSoftware);
|
vulnerableSoftware.add(vulnSoftware);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ package org.owasp.dependencycheck.dependency;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.net.URLDecoder;
|
import java.net.URLDecoder;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.owasp.dependencycheck.data.cpe.IndexEntry;
|
import org.owasp.dependencycheck.data.cpe.IndexEntry;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -73,7 +74,8 @@ public class VulnerableSoftware extends IndexEntry implements Serializable, Comp
|
|||||||
public void parseName(String cpeName) throws UnsupportedEncodingException {
|
public void parseName(String cpeName) throws UnsupportedEncodingException {
|
||||||
this.name = cpeName;
|
this.name = cpeName;
|
||||||
if (cpeName != null && cpeName.length() > 7) {
|
if (cpeName != null && cpeName.length() > 7) {
|
||||||
final String[] data = cpeName.substring(7).split(":");
|
final String cpeNameWithoutPrefix = cpeName.substring(7);
|
||||||
|
final String[] data = StringUtils.split(cpeNameWithoutPrefix, ':');
|
||||||
if (data.length >= 1) {
|
if (data.length >= 1) {
|
||||||
this.setVendor(urlDecode(data[0]));
|
this.setVendor(urlDecode(data[0]));
|
||||||
}
|
}
|
||||||
@@ -172,8 +174,8 @@ public class VulnerableSoftware extends IndexEntry implements Serializable, Comp
|
|||||||
@Override
|
@Override
|
||||||
public int compareTo(VulnerableSoftware vs) {
|
public int compareTo(VulnerableSoftware vs) {
|
||||||
int result = 0;
|
int result = 0;
|
||||||
final String[] left = this.name.split(":");
|
final String[] left = StringUtils.split(this.name, ':');
|
||||||
final String[] right = vs.getName().split(":");
|
final String[] right = StringUtils.split(vs.getName(), ':');
|
||||||
final int max = (left.length <= right.length) ? left.length : right.length;
|
final int max = (left.length <= right.length) ? left.length : right.length;
|
||||||
if (max > 0) {
|
if (max > 0) {
|
||||||
for (int i = 0; result == 0 && i < max; i++) {
|
for (int i = 0; result == 0 && i < max; i++) {
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ DELETE_REFERENCE=DELETE FROM reference WHERE cveid = ?
|
|||||||
DELETE_SOFTWARE=DELETE FROM software WHERE cveid = ?
|
DELETE_SOFTWARE=DELETE FROM software WHERE cveid = ?
|
||||||
DELETE_VULNERABILITY=DELETE FROM vulnerability WHERE id = ?
|
DELETE_VULNERABILITY=DELETE FROM vulnerability WHERE id = ?
|
||||||
CLEANUP_ORPHANS=DELETE FROM cpeEntry WHERE id not in (SELECT CPEEntryId FROM software);
|
CLEANUP_ORPHANS=DELETE FROM cpeEntry WHERE id not in (SELECT CPEEntryId FROM software);
|
||||||
|
COUNT_CPE=SELECT COUNT(*) records FROM cpeEntry
|
||||||
INSERT_REFERENCE=INSERT INTO reference (cveid, name, url, source) VALUES (?, ?, ?, ?)
|
INSERT_REFERENCE=INSERT INTO reference (cveid, name, url, source) VALUES (?, ?, ?, ?)
|
||||||
INSERT_SOFTWARE=INSERT INTO software (cveid, cpeEntryId, previousVersion) VALUES (?, ?, ?)
|
INSERT_SOFTWARE=INSERT INTO software (cveid, cpeEntryId, previousVersion) VALUES (?, ?, ?)
|
||||||
INSERT_CPE=INSERT INTO cpeEntry (cpe, vendor, product) VALUES (?, ?, ?)
|
INSERT_CPE=INSERT INTO cpeEntry (cpe, vendor, product) VALUES (?, ?, ?)
|
||||||
@@ -38,6 +39,6 @@ INSERT_PROPERTY=INSERT INTO properties (id, value) VALUES (?, ?)
|
|||||||
UPDATE_PROPERTY=UPDATE properties SET value = ? WHERE id = ?
|
UPDATE_PROPERTY=UPDATE properties SET value = ? WHERE id = ?
|
||||||
DELETE_PROPERTY=DELETE FROM properties WHERE id = ?
|
DELETE_PROPERTY=DELETE FROM properties WHERE id = ?
|
||||||
|
|
||||||
#the following two statements are unused and are only referenecd in dead code
|
#the following two statements are unused and are only referenced in dead code
|
||||||
DELETE_UNUSED_DICT_CPE=DELETE FROM cpeEntry WHERE dictionaryEntry=true AND id NOT IN (SELECT cpeEntryId FROM software)
|
DELETE_UNUSED_DICT_CPE=DELETE FROM cpeEntry WHERE dictionaryEntry=true AND id NOT IN (SELECT cpeEntryId FROM software)
|
||||||
ADD_DICT_CPE=MERGE INTO cpeEntry (cpe, vendor, product, dictionaryEntry) KEY(cpe) VALUES(?,?,?,true)
|
ADD_DICT_CPE=MERGE INTO cpeEntry (cpe, vendor, product, dictionaryEntry) KEY(cpe) VALUES(?,?,?,true)
|
||||||
|
|||||||
@@ -1 +1,15 @@
|
|||||||
|
# Copyright 2015 OWASP.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
CLEANUP_ORPHANS=DELETE FROM cpeEntry WHERE id not in (SELECT CPEEntryId FROM software)
|
CLEANUP_ORPHANS=DELETE FROM cpeEntry WHERE id not in (SELECT CPEEntryId FROM software)
|
||||||
|
|||||||
Reference in New Issue
Block a user