Add or clause to CR query to include current case results so that result will have count > 1. Move values check so that query will return empty.

This commit is contained in:
Andrew Ziehl 2018-06-01 10:01:33 -07:00
parent 4c529e2973
commit c78662885c
4 changed files with 70 additions and 64 deletions

View File

@ -653,18 +653,18 @@ public abstract class AbstractSqlEamDb implements EamDb {
* Retrieves eamArtiifact instances from the database that match the given * Retrieves eamArtiifact instances from the database that match the given
* list of MD5 values and optionally filters by given case. * list of MD5 values and optionally filters by given case.
* *
* Warning: Does not benefit from PreparedStatement caching to since values will * Warning: Does not benefit from PreparedStatement caching to since values
* be variable in length * will be variable in length
* *
* @param correlationCase Case id to search on, if null, searches all cases * @param correlationCase Case id to search on, if null, searches all cases
* @param values List of ArtifactInstance MD5 values to find matches of. * @param values List of ArtifactInstance MD5 values to find matches of.
* *
* @return List of artifact instances for a given list of MD5 values * @return List of artifact instances for a given list of MD5 values
* *
* @throws EamDbException if EamDb is inaccessible. * @throws EamDbException if EamDb is inaccessible.
*/ */
@Override @Override
public List<CorrelationAttributeCommonInstance> getArtifactInstancesByCaseValues(CorrelationCase correlationCase, Collection<String> values) throws EamDbException { public List<CorrelationAttributeCommonInstance> getArtifactInstancesByCaseValues(CorrelationCase correlationCase, Collection<String> values, int currentCaseId) throws EamDbException {
CorrelationAttribute.Type aType = CorrelationAttribute.getDefaultCorrelationTypes().get(0); // Files type CorrelationAttribute.Type aType = CorrelationAttribute.getDefaultCorrelationTypes().get(0); // Files type
if (aType == null) { if (aType == null) {
throw new EamDbException("Correlation Type is null"); throw new EamDbException("Correlation Type is null");
@ -673,69 +673,73 @@ public abstract class AbstractSqlEamDb implements EamDb {
if (correlationCase != null) { if (correlationCase != null) {
singleCase = true; singleCase = true;
} }
if (values != null) {
values = new ArrayList<String>();
}
Connection conn = connect(); Connection conn = connect();
List<CorrelationAttributeCommonInstance> artifactInstances = new ArrayList<>(); List<CorrelationAttributeCommonInstance> artifactInstances = new ArrayList<>();
// SELECT cases.case_name, cases.case_uid, data_sources.name, device_id, file_path, known_status, comment, data_sources.case_id, value FROM file_instances LEFT JOIN cases ON file_instances.case_id=cases.id LEFT JOIN data_sources ON file_instances.data_source_id=data_sources.id WHERE value IN (SELECT value FROM file_instances WHERE value IN ("59029becd7f830c0478aeb5e67cc3b20","d2b949c51cf3d5721699a6ea500eeba7","b90c8c8fb1c4687780002704b59585fe") GROUP BY value HAVING COUNT(*) > 1) ORDER BY value // SELECT cases.case_name, cases.case_uid, data_sources.name, device_id, file_path, known_status, comment, data_sources.case_id, value FROM file_instances LEFT JOIN cases ON file_instances.case_id=cases.id LEFT JOIN data_sources ON file_instances.data_source_id=data_sources.id WHERE value IN (SELECT value FROM file_instances WHERE value IN ("59029becd7f830c0478aeb5e67cc3b20","d2b949c51cf3d5721699a6ea500eeba7","b90c8c8fb1c4687780002704b59585fe") GROUP BY value HAVING COUNT(*) > 1) ORDER BY value
CorrelationAttributeCommonInstance artifactInstance; CorrelationAttributeCommonInstance artifactInstance;
PreparedStatement preparedStatement = null; PreparedStatement preparedStatement = null;
ResultSet resultSet = null; ResultSet resultSet = null;
if (values != null) {
String tableName = EamDbUtil.correlationTypeToInstanceTableName(aType);
StringBuilder sql = new StringBuilder(10);
sql.append("SELECT cases.case_name, cases.case_uid, data_sources.name, device_id, file_path, known_status, comment, data_sources.case_id, value FROM ");
sql.append(tableName);
sql.append(" LEFT JOIN cases ON ");
sql.append(tableName);
sql.append(".case_id=cases.id");
sql.append(" LEFT JOIN data_sources ON ");
sql.append(tableName);
sql.append(".data_source_id=data_sources.id");
sql.append(" WHERE value IN (SELECT value FROM ");
sql.append(tableName);
sql.append(" WHERE value IN (");
// Note: PreparedStatement has a limit on ? variable replacement so instead query is built with values appended directly into the string
for (String value : values) {
sql.append("'");
sql.append(value);
sql.append("',");
}
sql.deleteCharAt(sql.length() - 1); String tableName = EamDbUtil.correlationTypeToInstanceTableName(aType);
sql.append(") GROUP BY value HAVING COUNT(*) > 1)"); StringBuilder sql = new StringBuilder(10);
sql.append("SELECT cases.case_name, cases.case_uid, data_sources.name, device_id, file_path, known_status, comment, data_sources.case_id, value FROM ");
sql.append(tableName);
sql.append(" LEFT JOIN cases ON ");
sql.append(tableName);
sql.append(".case_id=cases.id");
sql.append(" LEFT JOIN data_sources ON ");
sql.append(tableName);
sql.append(".data_source_id=data_sources.id");
sql.append(" WHERE value IN (SELECT value FROM ");
sql.append(tableName);
sql.append(" WHERE value IN (");
// Note: PreparedStatement has a limit on ? variable replacement so instead query is built with values appended directly into the string
for (String value : values) {
sql.append("'");
sql.append(value);
sql.append("',");
}
sql.deleteCharAt(sql.length() - 1);
sql.append(") GROUP BY value HAVING COUNT(*) > 1)"); //
if (singleCase && correlationCase != null) {
sql.append(" AND ");
sql.append(tableName);
sql.append(".case_id=?");
sql.append(" OR ");
sql.append(tableName);
sql.append(".case_id=?");
}
sql.append(" ORDER BY value, cases.case_name, file_path");
try {
preparedStatement = conn.prepareStatement(sql.toString());
if (singleCase && correlationCase != null) { if (singleCase && correlationCase != null) {
sql.append(" AND "); preparedStatement.setInt(1, correlationCase.getID());
sql.append(tableName); preparedStatement.setInt(2, currentCaseId);
sql.append(".case_id=?");
} }
sql.append(" ORDER BY value, cases.case_name, file_path");
try { resultSet = preparedStatement.executeQuery();
preparedStatement = conn.prepareStatement(sql.toString()); while (resultSet.next()) {
int i = 1; artifactInstance = getCommonEamArtifactInstanceFromResultSet(resultSet);
if (singleCase && correlationCase != null) { artifactInstances.add(artifactInstance);
preparedStatement.setString(i, String.valueOf(correlationCase.getID()));
}
resultSet = preparedStatement.executeQuery();
while (resultSet.next()) {
artifactInstance = getCommonEamArtifactInstanceFromResultSet(resultSet);
artifactInstances.add(artifactInstance);
}
} catch (SQLException ex) {
throw new EamDbException("Error getting artifact instances by artifactType and artifactValue.", ex); // NON-NLS
} finally {
EamDbUtil.closePreparedStatement(preparedStatement);
EamDbUtil.closeResultSet(resultSet);
EamDbUtil.closeConnection(conn);
} }
} catch (SQLException ex) {
throw new EamDbException("Error getting artifact instances by artifactType and artifactValue.", ex); // NON-NLS
} finally {
EamDbUtil.closePreparedStatement(preparedStatement);
EamDbUtil.closeResultSet(resultSet);
EamDbUtil.closeConnection(conn);
} }
return artifactInstances; return artifactInstances;
@ -1032,7 +1036,7 @@ public abstract class AbstractSqlEamDb implements EamDb {
if (bulkArtifactsCount == 0) { if (bulkArtifactsCount == 0) {
return; return;
} }
TimingMetric timingMetric = EnterpriseHealthMonitor.getTimingMetric("Correlation Engine: Bulk insert"); TimingMetric timingMetric = EnterpriseHealthMonitor.getTimingMetric("Correlation Engine: Bulk insert");
for (CorrelationAttribute.Type type : artifactTypes) { for (CorrelationAttribute.Type type : artifactTypes) {
@ -1084,7 +1088,7 @@ public abstract class AbstractSqlEamDb implements EamDb {
bulkPs.executeBatch(); bulkPs.executeBatch();
bulkArtifacts.get(type.getDbTableName()).clear(); bulkArtifacts.get(type.getDbTableName()).clear();
} }
EnterpriseHealthMonitor.submitTimingMetric(timingMetric); EnterpriseHealthMonitor.submitTimingMetric(timingMetric);
// Reset state // Reset state

View File

@ -233,7 +233,7 @@ public interface EamDb {
* *
* @return List of artifact instances for a given list of MD5 values * @return List of artifact instances for a given list of MD5 values
*/ */
List<CorrelationAttributeCommonInstance> getArtifactInstancesByCaseValues(CorrelationCase correlationCase, Collection<String> values) throws EamDbException; List<CorrelationAttributeCommonInstance> getArtifactInstancesByCaseValues(CorrelationCase correlationCase, Collection<String> values, int currentCaseId) throws EamDbException;
/** /**
* Retrieves eamArtifact instances from the database that are associated * Retrieves eamArtifact instances from the database that are associated

View File

@ -18,7 +18,6 @@
*/ */
package org.sleuthkit.autopsy.centralrepository.datamodel; package org.sleuthkit.autopsy.centralrepository.datamodel;
import java.io.File;
import java.sql.Connection; import java.sql.Connection;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Statement; import java.sql.Statement;
@ -431,10 +430,10 @@ public class SqliteEamDb extends AbstractSqlEamDb {
* @return List of artifact instances for a given list of MD5 values * @return List of artifact instances for a given list of MD5 values
*/ */
@Override @Override
public List<CorrelationAttributeCommonInstance> getArtifactInstancesByCaseValues(CorrelationCase correlationCase, Collection<String> values) throws EamDbException { public List<CorrelationAttributeCommonInstance> getArtifactInstancesByCaseValues(CorrelationCase correlationCase, Collection<String> values, int currentCaseId) throws EamDbException {
try { try {
acquireSharedLock(); acquireSharedLock();
return super.getArtifactInstancesByCaseValues(correlationCase, values); return super.getArtifactInstancesByCaseValues(correlationCase, values, currentCaseId);
} finally { } finally {
releaseSharedLock(); releaseSharedLock();
} }

View File

@ -27,6 +27,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeCommonInstance; import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeCommonInstance;
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationCase; import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationCase;
@ -73,11 +74,13 @@ public abstract class EamDbCommonFilesAlgorithm extends CommonFilesMetadataBuild
protected CommonFilesMetadata findFiles(CorrelationCase correlationCase) throws TskCoreException, NoCurrentCaseException, SQLException, EamDbException, Exception { protected CommonFilesMetadata findFiles(CorrelationCase correlationCase) throws TskCoreException, NoCurrentCaseException, SQLException, EamDbException, Exception {
Map<String, Md5Metadata> currentCaseMetadata = getMetadataForCurrentCase(); Map<String, Md5Metadata> currentCaseMetadata = getMetadataForCurrentCase();
Collection<String> values = currentCaseMetadata.keySet(); Collection<String> values = currentCaseMetadata.keySet();
int currentCaseId;
Map<String, Md5Metadata> interCaseCommonFiles = new HashMap<>(); Map<String, Md5Metadata> interCaseCommonFiles = new HashMap<>();
try { try {
// Need to include current Cases results for specific case comparison
Collection<CorrelationAttributeCommonInstance> artifactInstances = dbManager.getArtifactInstancesByCaseValues(correlationCase, values).stream() currentCaseId = dbManager.getCase(Case.getCurrentCase()).getID();
Collection<CorrelationAttributeCommonInstance> artifactInstances = dbManager.getArtifactInstancesByCaseValues(correlationCase, values, currentCaseId).stream()
.collect(Collectors.toList()); .collect(Collectors.toList());
interCaseCommonFiles = gatherIntercaseResults(artifactInstances, currentCaseMetadata); interCaseCommonFiles = gatherIntercaseResults(artifactInstances, currentCaseMetadata);
@ -97,7 +100,7 @@ public abstract class EamDbCommonFilesAlgorithm extends CommonFilesMetadataBuild
private Map<String, Md5Metadata> gatherIntercaseResults(Collection<CorrelationAttributeCommonInstance> artifactInstances, Map<String, Md5Metadata> commonFiles) { private Map<String, Md5Metadata> gatherIntercaseResults(Collection<CorrelationAttributeCommonInstance> artifactInstances, Map<String, Md5Metadata> commonFiles) {
Map<String, Md5Metadata> interCaseCommonFiles = new HashMap<String, Md5Metadata>(); Map<String, Md5Metadata> interCaseCommonFiles = new HashMap<>();
for (CorrelationAttributeCommonInstance instance : artifactInstances) { for (CorrelationAttributeCommonInstance instance : artifactInstances) {