mirror of
https://github.com/ysoftdevs/DependencyCheck.git
synced 2026-03-23 17:41:28 +01:00
split out core DB functions into a base class to support storing settings in the database
Former-commit-id: 0c9d507e2e9e229691965aca09ef9f6c9e7e0965
This commit is contained in:
@@ -0,0 +1,245 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of dependency-check-core.
|
||||||
|
*
|
||||||
|
* Dependency-check-core is free software: you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the Free
|
||||||
|
* Software Foundation, either version 3 of the License, or (at your option) any
|
||||||
|
* later version.
|
||||||
|
*
|
||||||
|
* Dependency-check-core is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
|
* details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with
|
||||||
|
* dependency-check-core. If not, see http://www.gnu.org/licenses/.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 Jeremy Long. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
package org.owasp.dependencycheck.data;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.DriverManager;
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.sql.Statement;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
import org.owasp.dependencycheck.data.nvdcve.CveDB;
|
||||||
|
import static org.owasp.dependencycheck.data.nvdcve.CveDB.DB_SCHEMA_VERSION;
|
||||||
|
import org.owasp.dependencycheck.data.nvdcve.DatabaseException;
|
||||||
|
import org.owasp.dependencycheck.utils.Settings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Jeremy Long (jeremy.long@owasp.org)
|
||||||
|
*/
|
||||||
|
public class BaseDB {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resource location for SQL file used to create the database schema.
|
||||||
|
*/
|
||||||
|
public static final String DB_STRUCTURE_RESOURCE = "data/initialize.sql";
|
||||||
|
/**
|
||||||
|
* The version of the current DB Schema.
|
||||||
|
*/
|
||||||
|
public static final String DB_SCHEMA_VERSION = "2.7";
|
||||||
|
/**
|
||||||
|
* Database connection
|
||||||
|
*/
|
||||||
|
private Connection conn;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the database connection.
|
||||||
|
*
|
||||||
|
* @return the database connection
|
||||||
|
*/
|
||||||
|
protected Connection getConnection() {
|
||||||
|
return conn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens the database connection. If the database does not exist, it will
|
||||||
|
* create a new one.
|
||||||
|
*
|
||||||
|
* @throws IOException thrown if there is an IO Exception
|
||||||
|
* @throws SQLException thrown if there is a SQL Exception
|
||||||
|
* @throws DatabaseException thrown if there is an error initializing a new
|
||||||
|
* database
|
||||||
|
* @throws ClassNotFoundException thrown if the h2 database driver cannot be
|
||||||
|
* loaded
|
||||||
|
*/
|
||||||
|
@edu.umd.cs.findbugs.annotations.SuppressWarnings(
|
||||||
|
value = "DMI_EMPTY_DB_PASSWORD",
|
||||||
|
justification = "Yes, I know... Blank password.")
|
||||||
|
public void open() throws IOException, SQLException, DatabaseException, ClassNotFoundException {
|
||||||
|
final String fileName = CveDB.getDataDirectory().getCanonicalPath();
|
||||||
|
final File f = new File(fileName, "cve." + DB_SCHEMA_VERSION);
|
||||||
|
final File check = new File(f.getAbsolutePath() + ".h2.db");
|
||||||
|
final boolean createTables = !check.exists();
|
||||||
|
final String connStr = String.format("jdbc:h2:file:%s;AUTO_SERVER=TRUE", f.getAbsolutePath());
|
||||||
|
Class.forName("org.h2.Driver");
|
||||||
|
conn = DriverManager.getConnection(connStr, "sa", "");
|
||||||
|
if (createTables) {
|
||||||
|
createTables();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes the DB4O database. Close should be called on this object when it
|
||||||
|
* is done being used.
|
||||||
|
*/
|
||||||
|
public void close() {
|
||||||
|
if (conn != null) {
|
||||||
|
try {
|
||||||
|
conn.close();
|
||||||
|
} catch (SQLException ex) {
|
||||||
|
final String msg = "There was an error attempting to close the CveDB, see the log for more details.";
|
||||||
|
Logger.getLogger(BaseDB.class.getName()).log(Level.SEVERE, msg, ex);
|
||||||
|
Logger.getLogger(BaseDB.class.getName()).log(Level.FINE, null, ex);
|
||||||
|
}
|
||||||
|
conn = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Commits all completed transactions.
|
||||||
|
*
|
||||||
|
* @throws SQLException thrown if a SQL Exception occurs
|
||||||
|
*/
|
||||||
|
public void commit() throws SQLException {
|
||||||
|
if (conn != null) {
|
||||||
|
conn.commit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cleans up the object and ensures that "close" has been called.
|
||||||
|
*
|
||||||
|
* @throws Throwable thrown if there is a problem
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected void finalize() throws Throwable {
|
||||||
|
close();
|
||||||
|
super.finalize(); //not necessary if extending Object.
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the database structure (tables and indexes) to store the CVE data
|
||||||
|
*
|
||||||
|
* @throws SQLException thrown if there is a sql exception
|
||||||
|
* @throws DatabaseException thrown if there is a database exception
|
||||||
|
*/
|
||||||
|
private void createTables() throws SQLException, DatabaseException {
|
||||||
|
InputStream is;
|
||||||
|
InputStreamReader reader;
|
||||||
|
BufferedReader in = null;
|
||||||
|
try {
|
||||||
|
is = this.getClass().getClassLoader().getResourceAsStream(DB_STRUCTURE_RESOURCE);
|
||||||
|
reader = new InputStreamReader(is, "UTF-8");
|
||||||
|
in = new BufferedReader(reader);
|
||||||
|
final StringBuilder sb = new StringBuilder(2110);
|
||||||
|
String tmp;
|
||||||
|
while ((tmp = in.readLine()) != null) {
|
||||||
|
sb.append(tmp);
|
||||||
|
}
|
||||||
|
Statement statement = null;
|
||||||
|
try {
|
||||||
|
statement = conn.createStatement();
|
||||||
|
statement.execute(sb.toString());
|
||||||
|
} finally {
|
||||||
|
closeStatement(statement);
|
||||||
|
}
|
||||||
|
} catch (IOException ex) {
|
||||||
|
throw new DatabaseException("Unable to create database schema", ex);
|
||||||
|
} finally {
|
||||||
|
if (in != null) {
|
||||||
|
try {
|
||||||
|
in.close();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
Logger.getLogger(CveDB.class
|
||||||
|
.getName()).log(Level.FINEST, null, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the directory that the JAR file exists in so that we can ensure
|
||||||
|
* we always use a common data directory.
|
||||||
|
*
|
||||||
|
* @return the data directory for this index.
|
||||||
|
* @throws IOException is thrown if an IOException occurs of course...
|
||||||
|
*/
|
||||||
|
public static File getDataDirectory() throws IOException {
|
||||||
|
final File path = Settings.getFile(Settings.KEYS.CVE_DATA_DIRECTORY);
|
||||||
|
if (!path.exists()) {
|
||||||
|
if (!path.mkdirs()) {
|
||||||
|
throw new IOException("Unable to create NVD CVE Data directory");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the generated integer primary key for a newly inserted row.
|
||||||
|
*
|
||||||
|
* @param statement a prepared statement that just executed an insert
|
||||||
|
* @return a primary key
|
||||||
|
* @throws DatabaseException thrown if there is an exception obtaining the
|
||||||
|
* key
|
||||||
|
*/
|
||||||
|
protected int getGeneratedKey(PreparedStatement statement) throws DatabaseException {
|
||||||
|
ResultSet rs = null;
|
||||||
|
int id = 0;
|
||||||
|
try {
|
||||||
|
rs = statement.getGeneratedKeys();
|
||||||
|
rs.next();
|
||||||
|
id = rs.getInt(1);
|
||||||
|
} catch (SQLException ex) {
|
||||||
|
throw new DatabaseException("Unable to get primary key for inserted row");
|
||||||
|
} finally {
|
||||||
|
closeResultSet(rs);
|
||||||
|
}
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes the given statement object ignoring any exceptions that occur.
|
||||||
|
*
|
||||||
|
* @param statement a Statement object
|
||||||
|
*/
|
||||||
|
public void closeStatement(Statement statement) {
|
||||||
|
if (statement != null) {
|
||||||
|
try {
|
||||||
|
statement.close();
|
||||||
|
} catch (SQLException ex) {
|
||||||
|
Logger.getLogger(CveDB.class
|
||||||
|
.getName()).log(Level.FINEST, statement.toString(), ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes the result set capturing and ignoring any SQLExceptions that
|
||||||
|
* occur.
|
||||||
|
*
|
||||||
|
* @param rs a ResultSet to close
|
||||||
|
*/
|
||||||
|
public void closeResultSet(ResultSet rs) {
|
||||||
|
if (rs != null) {
|
||||||
|
try {
|
||||||
|
rs.close();
|
||||||
|
} catch (SQLException ex) {
|
||||||
|
Logger.getLogger(CveDB.class
|
||||||
|
.getName()).log(Level.FINEST, rs.toString(), ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,14 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.owasp.dependencycheck.data.nvdcve;
|
package org.owasp.dependencycheck.data.nvdcve;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.sql.Connection;
|
|
||||||
import java.sql.DriverManager;
|
|
||||||
import java.sql.PreparedStatement;
|
import java.sql.PreparedStatement;
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
@@ -36,6 +29,7 @@ import java.util.List;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
import org.owasp.dependencycheck.data.BaseDB;
|
||||||
import org.owasp.dependencycheck.data.cpe.IndexEntry;
|
import org.owasp.dependencycheck.data.cpe.IndexEntry;
|
||||||
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;
|
||||||
@@ -43,78 +37,65 @@ import org.owasp.dependencycheck.dependency.Vulnerability;
|
|||||||
import org.owasp.dependencycheck.dependency.VulnerableSoftware;
|
import org.owasp.dependencycheck.dependency.VulnerableSoftware;
|
||||||
import org.owasp.dependencycheck.utils.DependencyVersion;
|
import org.owasp.dependencycheck.utils.DependencyVersion;
|
||||||
import org.owasp.dependencycheck.utils.DependencyVersionUtil;
|
import org.owasp.dependencycheck.utils.DependencyVersionUtil;
|
||||||
import org.owasp.dependencycheck.utils.Settings;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The database holding information about the NVD CVE data.
|
* The database holding information about the NVD CVE data.
|
||||||
*
|
*
|
||||||
* @author Jeremy Long (jeremy.long@owasp.org)
|
* @author Jeremy Long (jeremy.long@owasp.org)
|
||||||
*/
|
*/
|
||||||
public class CveDB {
|
public class CveDB extends BaseDB {
|
||||||
|
|
||||||
/**
|
|
||||||
* Resource location for SQL file used to create the database schema.
|
|
||||||
*/
|
|
||||||
public static final String DB_STRUCTURE_RESOURCE = "data/initialize.sql";
|
|
||||||
/**
|
|
||||||
* The version of the current DB Schema.
|
|
||||||
*/
|
|
||||||
public static final String DB_SCHEMA_VERSION = "2.7";
|
|
||||||
/**
|
|
||||||
* Database connection
|
|
||||||
*/
|
|
||||||
private Connection conn;
|
|
||||||
//<editor-fold defaultstate="collapsed" desc="Constants to create, maintain, and retrieve data from the CVE Database">
|
//<editor-fold defaultstate="collapsed" desc="Constants to create, maintain, and retrieve data from the CVE Database">
|
||||||
/**
|
/**
|
||||||
* SQL Statement to delete references by vulnerability ID.
|
* SQL Statement to delete references by vulnerability ID.
|
||||||
*/
|
*/
|
||||||
public static final String DELETE_REFERENCE = "DELETE FROM reference WHERE cveid = ?";
|
private static final String DELETE_REFERENCE = "DELETE FROM reference WHERE cveid = ?";
|
||||||
/**
|
/**
|
||||||
* SQL Statement to delete software by vulnerability ID.
|
* SQL Statement to delete software by vulnerability ID.
|
||||||
*/
|
*/
|
||||||
public static final String DELETE_SOFTWARE = "DELETE FROM software WHERE cveid = ?";
|
private static final String DELETE_SOFTWARE = "DELETE FROM software WHERE cveid = ?";
|
||||||
/**
|
/**
|
||||||
* SQL Statement to delete a vulnerability by CVE.
|
* SQL Statement to delete a vulnerability by CVE.
|
||||||
*/
|
*/
|
||||||
public static final String DELETE_VULNERABILITY = "DELETE FROM vulnerability WHERE cve = ?";
|
private static final String DELETE_VULNERABILITY = "DELETE FROM vulnerability WHERE cve = ?";
|
||||||
/**
|
/**
|
||||||
* SQL Statement to cleanup orphan entries. Yes, the db schema could be a
|
* SQL Statement to cleanup orphan entries. Yes, the db schema could be a
|
||||||
* little tighter, but what we have works well to keep the data file size
|
* little tighter, but what we have works well to keep the data file size
|
||||||
* down a bit.
|
* down a bit.
|
||||||
*/
|
*/
|
||||||
public static final String CLEANUP_ORPHANS = "DELETE FROM CpeEntry WHERE id not in (SELECT CPEEntryId FROM Software); ";
|
private static final String CLEANUP_ORPHANS = "DELETE FROM CpeEntry WHERE id not in (SELECT CPEEntryId FROM Software); ";
|
||||||
/**
|
/**
|
||||||
* SQL Statement to insert a new reference.
|
* SQL Statement to insert a new reference.
|
||||||
*/
|
*/
|
||||||
public static final String INSERT_REFERENCE = "INSERT INTO reference (cveid, name, url, source) VALUES (?, ?, ?, ?)";
|
private static final String INSERT_REFERENCE = "INSERT INTO reference (cveid, name, url, source) VALUES (?, ?, ?, ?)";
|
||||||
/**
|
/**
|
||||||
* SQL Statement to insert a new software.
|
* SQL Statement to insert a new software.
|
||||||
*/
|
*/
|
||||||
public static final String INSERT_SOFTWARE = "INSERT INTO software (cveid, cpeEntryId, previousVersion) VALUES (?, ?, ?)";
|
private static final String INSERT_SOFTWARE = "INSERT INTO software (cveid, cpeEntryId, previousVersion) VALUES (?, ?, ?)";
|
||||||
/**
|
/**
|
||||||
* SQL Statement to insert a new cpe.
|
* SQL Statement to insert a new cpe.
|
||||||
*/
|
*/
|
||||||
public static final String INSERT_CPE = "INSERT INTO cpeEntry (cpe, vendor, product) VALUES (?, ?, ?)";
|
private static final String INSERT_CPE = "INSERT INTO cpeEntry (cpe, vendor, product) VALUES (?, ?, ?)";
|
||||||
/**
|
/**
|
||||||
* SQL Statement to get a CPEProductID.
|
* SQL Statement to get a CPEProductID.
|
||||||
*/
|
*/
|
||||||
public static final String SELECT_CPE_ID = "SELECT id FROM cpeEntry WHERE cpe = ?";
|
private static final String SELECT_CPE_ID = "SELECT id FROM cpeEntry WHERE cpe = ?";
|
||||||
/**
|
/**
|
||||||
* SQL Statement to insert a new vulnerability.
|
* SQL Statement to insert a new vulnerability.
|
||||||
*/
|
*/
|
||||||
public static final String INSERT_VULNERABILITY = "INSERT INTO vulnerability (cve, description, cwe, cvssScore, cvssAccessVector, "
|
private static final String INSERT_VULNERABILITY = "INSERT INTO vulnerability (cve, description, cwe, cvssScore, cvssAccessVector, "
|
||||||
+ "cvssAccessComplexity, cvssAuthentication, cvssConfidentialityImpact, cvssIntegrityImpact, cvssAvailabilityImpact) "
|
+ "cvssAccessComplexity, cvssAuthentication, cvssConfidentialityImpact, cvssIntegrityImpact, cvssAvailabilityImpact) "
|
||||||
+ "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
|
+ "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
|
||||||
/**
|
/**
|
||||||
* SQL Statement to update a vulnerability.
|
* SQL Statement to update a vulnerability.
|
||||||
*/
|
*/
|
||||||
public static final String UPDATE_VULNERABILITY = "UPDATE vulnerability SET description=?, cwe=?, cvssScore=?, cvssAccessVector=?, "
|
private static final String UPDATE_VULNERABILITY = "UPDATE vulnerability SET description=?, cwe=?, cvssScore=?, cvssAccessVector=?, "
|
||||||
+ "cvssAccessComplexity=?, cvssAuthentication=?, cvssConfidentialityImpact=?, cvssIntegrityImpact=?, cvssAvailabilityImpact=? "
|
+ "cvssAccessComplexity=?, cvssAuthentication=?, cvssConfidentialityImpact=?, cvssIntegrityImpact=?, cvssAvailabilityImpact=? "
|
||||||
+ "WHERE id=?";
|
+ "WHERE id=?";
|
||||||
/**
|
/**
|
||||||
* SQL Statement to find CVE entries based on CPE data.
|
* SQL Statement to find CVE entries based on CPE data.
|
||||||
*/
|
*/
|
||||||
public static final String SELECT_CVE_FROM_SOFTWARE = "SELECT cve, cpe, previousVersion "
|
private static final String SELECT_CVE_FROM_SOFTWARE = "SELECT cve, cpe, previousVersion "
|
||||||
+ "FROM software INNER JOIN vulnerability ON vulnerability.id = software.cveId "
|
+ "FROM software INNER JOIN vulnerability ON vulnerability.id = software.cveId "
|
||||||
+ "INNER JOIN cpeEntry ON cpeEntry.id = software.cpeEntryId "
|
+ "INNER JOIN cpeEntry ON cpeEntry.id = software.cpeEntryId "
|
||||||
+ "WHERE vendor = ? AND product = ?";
|
+ "WHERE vendor = ? AND product = ?";
|
||||||
@@ -124,19 +105,19 @@ public class CveDB {
|
|||||||
/**
|
/**
|
||||||
* SQL Statement to find the CPE entry based on the vendor and product.
|
* SQL Statement to find the CPE entry based on the vendor and product.
|
||||||
*/
|
*/
|
||||||
public static final String SELECT_CPE_ENTRIES = "SELECT cpe FROM cpeEntry WHERE vendor = ? AND product = ?";
|
private static final String SELECT_CPE_ENTRIES = "SELECT cpe FROM cpeEntry WHERE vendor = ? AND product = ?";
|
||||||
/**
|
/**
|
||||||
* SQL Statement to select references by CVEID.
|
* SQL Statement to select references by CVEID.
|
||||||
*/
|
*/
|
||||||
public static final String SELECT_REFERENCE = "SELECT source, name, url FROM reference WHERE cveid = ?";
|
private static final String SELECT_REFERENCE = "SELECT source, name, url FROM reference WHERE cveid = ?";
|
||||||
/**
|
/**
|
||||||
* SQL Statement to select vendor and product for lucene index.
|
* SQL Statement to select vendor and product for lucene index.
|
||||||
*/
|
*/
|
||||||
public static final String SELECT_VENDOR_PRODUCT_LIST = "SELECT vendor, product FROM cpeEntry GROUP BY vendor, product";
|
private static final String SELECT_VENDOR_PRODUCT_LIST = "SELECT vendor, product FROM cpeEntry GROUP BY vendor, product";
|
||||||
/**
|
/**
|
||||||
* SQL Statement to select software by CVEID.
|
* SQL Statement to select software by CVEID.
|
||||||
*/
|
*/
|
||||||
public static final String SELECT_SOFTWARE = "SELECT cpe, previousVersion "
|
private static final String SELECT_SOFTWARE = "SELECT cpe, previousVersion "
|
||||||
+ "FROM software INNER JOIN cpeEntry ON software.cpeEntryId = cpeEntry.id WHERE cveid = ?";
|
+ "FROM software INNER JOIN cpeEntry ON software.cpeEntryId = cpeEntry.id WHERE cveid = ?";
|
||||||
// public static final String SELECT_SOFTWARE = "SELECT part, vendor, product, version, revision, previousVersion "
|
// public static final String SELECT_SOFTWARE = "SELECT part, vendor, product, version, revision, previousVersion "
|
||||||
// + "FROM software INNER JOIN cpeProduct ON cpeProduct.id = software.cpeProductId LEFT JOIN cpeVersion ON "
|
// + "FROM software INNER JOIN cpeProduct ON cpeProduct.id = software.cpeProductId LEFT JOIN cpeVersion ON "
|
||||||
@@ -144,80 +125,14 @@ public class CveDB {
|
|||||||
/**
|
/**
|
||||||
* SQL Statement to select a vulnerability by CVEID.
|
* SQL Statement to select a vulnerability by CVEID.
|
||||||
*/
|
*/
|
||||||
public static final String SELECT_VULNERABILITY = "SELECT id, description, cwe, cvssScore, cvssAccessVector, cvssAccessComplexity, "
|
private static final String SELECT_VULNERABILITY = "SELECT id, description, cwe, cvssScore, cvssAccessVector, cvssAccessComplexity, "
|
||||||
+ "cvssAuthentication, cvssConfidentialityImpact, cvssIntegrityImpact, cvssAvailabilityImpact FROM vulnerability WHERE cve = ?";
|
+ "cvssAuthentication, cvssConfidentialityImpact, cvssIntegrityImpact, cvssAvailabilityImpact FROM vulnerability WHERE cve = ?";
|
||||||
/**
|
/**
|
||||||
* SQL Statement to select a vulnerability's primary key.
|
* SQL Statement to select a vulnerability's primary key.
|
||||||
*/
|
*/
|
||||||
public static final String SELECT_VULNERABILITY_ID = "SELECT id FROM vulnerability WHERE cve = ?";
|
private static final String SELECT_VULNERABILITY_ID = "SELECT id FROM vulnerability WHERE cve = ?";
|
||||||
//</editor-fold>
|
//</editor-fold>
|
||||||
|
|
||||||
/**
|
|
||||||
* Opens the database connection. If the database does not exist, it will
|
|
||||||
* create a new one.
|
|
||||||
*
|
|
||||||
* @throws IOException thrown if there is an IO Exception
|
|
||||||
* @throws SQLException thrown if there is a SQL Exception
|
|
||||||
* @throws DatabaseException thrown if there is an error initializing a new
|
|
||||||
* database
|
|
||||||
* @throws ClassNotFoundException thrown if the h2 database driver cannot be
|
|
||||||
* loaded
|
|
||||||
*/
|
|
||||||
@edu.umd.cs.findbugs.annotations.SuppressWarnings(
|
|
||||||
value = "DMI_EMPTY_DB_PASSWORD",
|
|
||||||
justification = "Yes, I know... Blank password.")
|
|
||||||
public void open() throws IOException, SQLException, DatabaseException, ClassNotFoundException {
|
|
||||||
final String fileName = CveDB.getDataDirectory().getCanonicalPath();
|
|
||||||
final File f = new File(fileName, "cve." + DB_SCHEMA_VERSION);
|
|
||||||
final File check = new File(f.getAbsolutePath() + ".h2.db");
|
|
||||||
final boolean createTables = !check.exists();
|
|
||||||
final String connStr = String.format("jdbc:h2:file:%s;AUTO_SERVER=TRUE", f.getAbsolutePath());
|
|
||||||
Class.forName("org.h2.Driver");
|
|
||||||
conn = DriverManager.getConnection(connStr, "sa", "");
|
|
||||||
if (createTables) {
|
|
||||||
createTables();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Commits all completed transactions.
|
|
||||||
*
|
|
||||||
* @throws SQLException thrown if a SQL Exception occurs
|
|
||||||
*/
|
|
||||||
public void commit() throws SQLException {
|
|
||||||
if (conn != null) {
|
|
||||||
conn.commit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cleans up the object and ensures that "close" has been called.
|
|
||||||
*
|
|
||||||
* @throws Throwable thrown if there is a problem
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected void finalize() throws Throwable {
|
|
||||||
close();
|
|
||||||
super.finalize(); //not necessary if extending Object.
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Closes the DB4O database. Close should be called on this object when it
|
|
||||||
* is done being used.
|
|
||||||
*/
|
|
||||||
public void close() {
|
|
||||||
if (conn != null) {
|
|
||||||
try {
|
|
||||||
conn.close();
|
|
||||||
} catch (SQLException ex) {
|
|
||||||
final String msg = "There was an error attempting to close the CveDB, see the log for more details.";
|
|
||||||
Logger.getLogger(CveDB.class.getName()).log(Level.SEVERE, msg, ex);
|
|
||||||
Logger.getLogger(CveDB.class.getName()).log(Level.FINE, null, ex);
|
|
||||||
}
|
|
||||||
conn = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Searches the CPE entries in the database and retrieves all entries for a
|
* Searches the CPE entries in the database and retrieves all entries for a
|
||||||
* given vendor and product combination. The returned list will include all
|
* given vendor and product combination. The returned list will include all
|
||||||
@@ -233,7 +148,7 @@ public class CveDB {
|
|||||||
ResultSet rs = null;
|
ResultSet rs = null;
|
||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
try {
|
try {
|
||||||
ps = conn.prepareStatement(SELECT_CPE_ENTRIES);
|
ps = getConnection().prepareStatement(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();
|
||||||
@@ -261,7 +176,7 @@ public class CveDB {
|
|||||||
final Set<IndexEntry> set = new HashSet<IndexEntry>();
|
final Set<IndexEntry> set = new HashSet<IndexEntry>();
|
||||||
ResultSet rs = null;
|
ResultSet rs = null;
|
||||||
try {
|
try {
|
||||||
PreparedStatement ps = conn.prepareStatement(SELECT_VENDOR_PRODUCT_LIST);
|
PreparedStatement ps = getConnection().prepareStatement(SELECT_VENDOR_PRODUCT_LIST);
|
||||||
rs = ps.executeQuery();
|
rs = ps.executeQuery();
|
||||||
} catch (SQLException ex) {
|
} catch (SQLException ex) {
|
||||||
Logger.getLogger(CveDB.class.getName()).log(Level.SEVERE, null, ex);
|
Logger.getLogger(CveDB.class.getName()).log(Level.SEVERE, null, ex);
|
||||||
@@ -290,7 +205,7 @@ public class CveDB {
|
|||||||
PreparedStatement ps;
|
PreparedStatement ps;
|
||||||
final HashSet<String> cveEntries = new HashSet<String>();
|
final HashSet<String> cveEntries = new HashSet<String>();
|
||||||
try {
|
try {
|
||||||
ps = conn.prepareStatement(SELECT_CVE_FROM_SOFTWARE);
|
ps = getConnection().prepareStatement(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();
|
||||||
@@ -333,7 +248,7 @@ public class CveDB {
|
|||||||
ResultSet rsS = null;
|
ResultSet rsS = null;
|
||||||
Vulnerability vuln = null;
|
Vulnerability vuln = null;
|
||||||
try {
|
try {
|
||||||
psV = conn.prepareStatement(SELECT_VULNERABILITY);
|
psV = getConnection().prepareStatement(SELECT_VULNERABILITY);
|
||||||
psV.setString(1, cve);
|
psV.setString(1, cve);
|
||||||
rsV = psV.executeQuery();
|
rsV = psV.executeQuery();
|
||||||
if (rsV.next()) {
|
if (rsV.next()) {
|
||||||
@@ -357,13 +272,13 @@ public class CveDB {
|
|||||||
vuln.setCvssIntegrityImpact(rsV.getString(9));
|
vuln.setCvssIntegrityImpact(rsV.getString(9));
|
||||||
vuln.setCvssAvailabilityImpact(rsV.getString(10));
|
vuln.setCvssAvailabilityImpact(rsV.getString(10));
|
||||||
|
|
||||||
psR = conn.prepareStatement(SELECT_REFERENCE);
|
psR = getConnection().prepareStatement(SELECT_REFERENCE);
|
||||||
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 = conn.prepareStatement(SELECT_SOFTWARE);
|
psS = getConnection().prepareStatement(SELECT_SOFTWARE);
|
||||||
psS.setInt(1, cveId);
|
psS.setInt(1, cveId);
|
||||||
rsS = psS.executeQuery();
|
rsS = psS.executeQuery();
|
||||||
while (rsS.next()) {
|
while (rsS.next()) {
|
||||||
@@ -408,15 +323,15 @@ public class CveDB {
|
|||||||
PreparedStatement insertSoftware = null;
|
PreparedStatement insertSoftware = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
selectVulnerabilityId = conn.prepareStatement(SELECT_VULNERABILITY_ID);
|
selectVulnerabilityId = getConnection().prepareStatement(SELECT_VULNERABILITY_ID);
|
||||||
deleteReferences = conn.prepareStatement(DELETE_REFERENCE);
|
deleteReferences = getConnection().prepareStatement(DELETE_REFERENCE);
|
||||||
deleteSoftware = conn.prepareStatement(DELETE_SOFTWARE);
|
deleteSoftware = getConnection().prepareStatement(DELETE_SOFTWARE);
|
||||||
updateVulnerability = conn.prepareStatement(UPDATE_VULNERABILITY);
|
updateVulnerability = getConnection().prepareStatement(UPDATE_VULNERABILITY);
|
||||||
insertVulnerability = conn.prepareStatement(INSERT_VULNERABILITY, Statement.RETURN_GENERATED_KEYS);
|
insertVulnerability = getConnection().prepareStatement(INSERT_VULNERABILITY, Statement.RETURN_GENERATED_KEYS);
|
||||||
insertReference = conn.prepareStatement(INSERT_REFERENCE);
|
insertReference = getConnection().prepareStatement(INSERT_REFERENCE);
|
||||||
selectCpeId = conn.prepareStatement(SELECT_CPE_ID);
|
selectCpeId = getConnection().prepareStatement(SELECT_CPE_ID);
|
||||||
insertCpe = conn.prepareStatement(INSERT_CPE, Statement.RETURN_GENERATED_KEYS);
|
insertCpe = getConnection().prepareStatement(INSERT_CPE, Statement.RETURN_GENERATED_KEYS);
|
||||||
insertSoftware = conn.prepareStatement(INSERT_SOFTWARE);
|
insertSoftware = getConnection().prepareStatement(INSERT_SOFTWARE);
|
||||||
int vulnerabilityId = 0;
|
int vulnerabilityId = 0;
|
||||||
selectVulnerabilityId.setString(1, vuln.getName());
|
selectVulnerabilityId.setString(1, vuln.getName());
|
||||||
ResultSet rs = selectVulnerabilityId.executeQuery();
|
ResultSet rs = selectVulnerabilityId.executeQuery();
|
||||||
@@ -526,23 +441,6 @@ public class CveDB {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the directory that the JAR file exists in so that we can ensure
|
|
||||||
* we always use a common data directory.
|
|
||||||
*
|
|
||||||
* @return the data directory for this index.
|
|
||||||
* @throws IOException is thrown if an IOException occurs of course...
|
|
||||||
*/
|
|
||||||
public static File getDataDirectory() throws IOException {
|
|
||||||
final File path = Settings.getFile(Settings.KEYS.CVE_DATA_DIRECTORY);
|
|
||||||
if (!path.exists()) {
|
|
||||||
if (!path.mkdirs()) {
|
|
||||||
throw new IOException("Unable to create NVD CVE Data directory");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* It is possible that orphaned rows may be generated during database
|
* It is possible that orphaned rows may be generated during database
|
||||||
* updates. This should be called after all updates have been completed to
|
* updates. This should be called after all updates have been completed to
|
||||||
@@ -551,7 +449,7 @@ public class CveDB {
|
|||||||
public void cleanupDatabase() {
|
public void cleanupDatabase() {
|
||||||
PreparedStatement ps = null;
|
PreparedStatement ps = null;
|
||||||
try {
|
try {
|
||||||
ps = conn.prepareStatement(CLEANUP_ORPHANS);
|
ps = getConnection().prepareStatement(CLEANUP_ORPHANS);
|
||||||
if (ps != null) {
|
if (ps != null) {
|
||||||
ps.executeUpdate();
|
ps.executeUpdate();
|
||||||
}
|
}
|
||||||
@@ -562,102 +460,6 @@ public class CveDB {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates the database structure (tables and indexes) to store the CVE data
|
|
||||||
*
|
|
||||||
* @throws SQLException thrown if there is a sql exception
|
|
||||||
* @throws DatabaseException thrown if there is a database exception
|
|
||||||
*/
|
|
||||||
protected void createTables() throws SQLException, DatabaseException {
|
|
||||||
InputStream is;
|
|
||||||
InputStreamReader reader;
|
|
||||||
BufferedReader in = null;
|
|
||||||
try {
|
|
||||||
is = this.getClass().getClassLoader().getResourceAsStream(DB_STRUCTURE_RESOURCE);
|
|
||||||
reader = new InputStreamReader(is, "UTF-8");
|
|
||||||
in = new BufferedReader(reader);
|
|
||||||
final StringBuilder sb = new StringBuilder(2110);
|
|
||||||
String tmp;
|
|
||||||
while ((tmp = in.readLine()) != null) {
|
|
||||||
sb.append(tmp);
|
|
||||||
}
|
|
||||||
Statement statement = null;
|
|
||||||
try {
|
|
||||||
statement = conn.createStatement();
|
|
||||||
statement.execute(sb.toString());
|
|
||||||
} finally {
|
|
||||||
closeStatement(statement);
|
|
||||||
}
|
|
||||||
} catch (IOException ex) {
|
|
||||||
throw new DatabaseException("Unable to create database schema", ex);
|
|
||||||
} finally {
|
|
||||||
if (in != null) {
|
|
||||||
try {
|
|
||||||
in.close();
|
|
||||||
} catch (IOException ex) {
|
|
||||||
Logger.getLogger(CveDB.class
|
|
||||||
.getName()).log(Level.FINEST, null, ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Closes the given statement object ignoring any exceptions that occur.
|
|
||||||
*
|
|
||||||
* @param statement a Statement object
|
|
||||||
*/
|
|
||||||
private void closeStatement(Statement statement) {
|
|
||||||
if (statement != null) {
|
|
||||||
try {
|
|
||||||
statement.close();
|
|
||||||
} catch (SQLException ex) {
|
|
||||||
Logger.getLogger(CveDB.class
|
|
||||||
.getName()).log(Level.FINEST, statement.toString(), ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Closes the result set capturing and ignoring any SQLExceptions that
|
|
||||||
* occur.
|
|
||||||
*
|
|
||||||
* @param rs a ResultSet to close
|
|
||||||
*/
|
|
||||||
public void closeResultSet(ResultSet rs) {
|
|
||||||
if (rs != null) {
|
|
||||||
try {
|
|
||||||
rs.close();
|
|
||||||
} catch (SQLException ex) {
|
|
||||||
Logger.getLogger(CveDB.class
|
|
||||||
.getName()).log(Level.FINEST, rs.toString(), ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the generated integer primary key for a newly inserted row.
|
|
||||||
*
|
|
||||||
* @param statement a prepared statement that just executed an insert
|
|
||||||
* @return a primary key
|
|
||||||
* @throws DatabaseException thrown if there is an exception obtaining the
|
|
||||||
* key
|
|
||||||
*/
|
|
||||||
private int getGeneratedKey(PreparedStatement statement) throws DatabaseException {
|
|
||||||
ResultSet rs = null;
|
|
||||||
int id = 0;
|
|
||||||
try {
|
|
||||||
rs = statement.getGeneratedKeys();
|
|
||||||
rs.next();
|
|
||||||
id = rs.getInt(1);
|
|
||||||
} catch (SQLException ex) {
|
|
||||||
throw new DatabaseException("Unable to get primary key for inserted row");
|
|
||||||
} finally {
|
|
||||||
closeResultSet(rs);
|
|
||||||
}
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines if the given identifiedVersion is affected by the given cpeId
|
* Determines if the given identifiedVersion is affected by the given cpeId
|
||||||
* and previous version flag. A non-null, non-empty string passed to the
|
* and previous version flag. A non-null, non-empty string passed to the
|
||||||
|
|||||||
Reference in New Issue
Block a user