Autopsy  4.20.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
InterCaseSearchResultsProcessor.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2018-2020 Basis Technology Corp.
5  * Contact: carrier <at> sleuthkit <dot> org
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 package org.sleuthkit.autopsy.commonpropertiessearch;
20 
21 import com.google.common.collect.Iterables;
22 import java.sql.ResultSet;
23 import java.sql.SQLException;
24 import java.util.ArrayList;
25 import java.util.Arrays;
26 import java.util.Collections;
27 import java.util.HashMap;
28 import java.util.HashSet;
29 import java.util.Set;
30 import java.util.List;
31 import java.util.Map;
32 import java.util.TreeMap;
33 import java.util.logging.Level;
34 import java.util.stream.Collectors;
45 import org.sleuthkit.datamodel.CaseDbAccessManager;
46 import org.sleuthkit.datamodel.TskData;
47 import org.sleuthkit.datamodel.HashUtility;
48 import org.sleuthkit.datamodel.TskCoreException;
50 
55 final class InterCaseSearchResultsProcessor {
56 
57  private static final Logger LOGGER = Logger.getLogger(CommonAttributePanel.class.getName());
58  private static final String INTER_CASE_WHERE_CLAUSE = "case_id=%s AND (known_status !=%s OR known_status IS NULL)"; //NON-NLS
62  private final Type correlationType;
63 
71  InterCaseSearchResultsProcessor(CorrelationAttributeInstance.Type theType) {
72  this.correlationType = theType;
73  }
74 
82  CorrelationAttributeInstance findSingleCorrelationAttribute(int attrbuteId) {
83  try {
84 
85  InterCaseCommonAttributeRowCallback instancetableCallback = new InterCaseCommonAttributeRowCallback();
86  CentralRepository dbManager = CentralRepository.getInstance();
87  dbManager.processInstanceTableWhere(correlationType, String.format("id = %s", attrbuteId), instancetableCallback);
88 
89  return instancetableCallback.getCorrelationAttribute();
90 
91  } catch (CentralRepoException ex) {
92  LOGGER.log(Level.SEVERE, "Error accessing EamDb processing InstanceTable row.", ex);
93  }
94 
95  return null;
96  }
97 
109  private String getFileQuery(Set<String> mimeTypesToFilterOn) throws CentralRepoException {
110  String query;
111  query = "md5 AS value FROM tsk_files WHERE known!=" + TskData.FileKnown.KNOWN.getFileKnownValue() + " AND md5 IS NOT NULL"; //NON-NLS
112  if (!mimeTypesToFilterOn.isEmpty()) {
113  query = query + " AND mime_type IS NOT NULL AND mime_type IN ('" + String.join("', '", mimeTypesToFilterOn) + "')"; //NON-NLS
114  }
115  return query;
116  }
117 
129  Map<String, Map<String, CommonAttributeValueList>> findInterCaseValuesByCase(Case currentCase, Set<String> mimeTypesToFilterOn) {
130  try {
131 
132  CentralRepository dbManager = CentralRepository.getInstance();
133  int caseId = dbManager.getCase(currentCase).getID();
134  InterCaseByCaseCallback instancetableCallback = new InterCaseByCaseCallback(caseId);
135  if (correlationType.getId() == CorrelationAttributeInstance.FILES_TYPE_ID) {
136  currentCase.getSleuthkitCase().getCaseDbAccessManager().select(getFileQuery(mimeTypesToFilterOn), instancetableCallback);
137  } else {
138  dbManager.processInstanceTableWhere(correlationType, String.format(INTER_CASE_WHERE_CLAUSE, caseId,
139  TskData.FileKnown.KNOWN.getFileKnownValue()),
140  instancetableCallback);
141  }
142  return instancetableCallback.getInstanceCollatedCommonFiles();
143 
144  } catch (CentralRepoException | TskCoreException ex) {
145  LOGGER.log(Level.SEVERE, "Error accessing EamDb processing CaseInstancesTable.", ex);
146  }
147  return new HashMap<>();
148  }
149 
159  Map<Integer, CommonAttributeValueList> findInterCaseValuesByCount(Case currentCase, Set<String> mimeTypesToFilterOn) {
160  try {
161 
162  CentralRepository dbManager = CentralRepository.getInstance();
163 
164  int caseId = dbManager.getCase(currentCase).getID();
165  InterCaseByCountCallback instancetableCallback = new InterCaseByCountCallback(caseId);
166  if (correlationType.getId() == CorrelationAttributeInstance.FILES_TYPE_ID) {
167  currentCase.getSleuthkitCase().getCaseDbAccessManager().select(getFileQuery(mimeTypesToFilterOn), instancetableCallback);
168  } else {
169  dbManager.processInstanceTableWhere(correlationType, String.format(INTER_CASE_WHERE_CLAUSE, caseId,
170  TskData.FileKnown.KNOWN.getFileKnownValue()),
171  instancetableCallback);
172  }
173  return instancetableCallback.getInstanceCollatedCommonFiles();
174 
175  } catch (CentralRepoException | TskCoreException ex) {
176  LOGGER.log(Level.SEVERE, "Error accessing EamDb processing CaseInstancesTable.", ex);
177  }
178  return new TreeMap<>();
179  }
180 
193  Map<Integer, CommonAttributeValueList> findSingleInterCaseValuesByCount(Case currentCase, Set<String> mimeTypesToFilterOn, CorrelationCase singleCase) {
194  try {
195  CentralRepository dbManager = CentralRepository.getInstance();
196  int caseId = dbManager.getCase(currentCase).getID();
197  int targetCaseId = singleCase.getID();
198  InterCaseByCountCallback instancetableCallback = new InterCaseByCountCallback(caseId, targetCaseId);
199  if (correlationType.getId() == CorrelationAttributeInstance.FILES_TYPE_ID) {
200  currentCase.getSleuthkitCase().getCaseDbAccessManager().select(getFileQuery(mimeTypesToFilterOn), instancetableCallback);
201  } else {
202  dbManager.processInstanceTableWhere(correlationType, String.format(INTER_CASE_WHERE_CLAUSE, caseId,
203  TskData.FileKnown.KNOWN.getFileKnownValue()),
204  instancetableCallback);
205  }
206  return instancetableCallback.getInstanceCollatedCommonFiles();
207  } catch (CentralRepoException | TskCoreException ex) {
208  LOGGER.log(Level.SEVERE, "Error accessing EamDb processing CaseInstancesTable.", ex);
209  }
210  return new TreeMap<>();
211  }
212 
226  Map<String, Map<String, CommonAttributeValueList>> findSingleInterCaseValuesByCase(Case currentCase, Set<String> mimeTypesToFilterOn, CorrelationCase singleCase) {
227  try {
228 
229  CentralRepository dbManager = CentralRepository.getInstance();
230  int caseId = dbManager.getCase(currentCase).getID();
231  int targetCaseId = singleCase.getID();
232  InterCaseByCaseCallback instancetableCallback = new InterCaseByCaseCallback(caseId, targetCaseId);
233  if (correlationType.getId() == CorrelationAttributeInstance.FILES_TYPE_ID) {
234  currentCase.getSleuthkitCase().getCaseDbAccessManager().select(getFileQuery(mimeTypesToFilterOn), instancetableCallback);
235  } else {
236  dbManager.processInstanceTableWhere(correlationType, String.format(INTER_CASE_WHERE_CLAUSE, caseId,
237  TskData.FileKnown.KNOWN.getFileKnownValue()),
238  instancetableCallback);
239  }
240  return instancetableCallback.getInstanceCollatedCommonFiles();
241  } catch (CentralRepoException | TskCoreException ex) {
242  LOGGER.log(Level.SEVERE, "Error accessing EamDb processing CaseInstancesTable.", ex);
243  }
244  return new HashMap<>();
245  }
246 
251  private class InterCaseByCountCallback implements CaseDbAccessManager.CaseDbAccessQueryCallback, InstanceTableCallback {
252 
253  private final TreeMap<Integer, CommonAttributeValueList> instanceCollatedCommonFiles = new TreeMap<>();
254  private final int caseID;
255  private final int targetCase;
256 
257  private InterCaseByCountCallback(int caseId) {
258  this(caseId, 0);
259  }
260 
261  private InterCaseByCountCallback(int caseId, int targetCase) {
262  this.caseID = caseId;
263  this.targetCase = targetCase;
264  }
265 
266  @Override
267  public void process(ResultSet resultSet) {
268  try {
269  Set<String> values = new HashSet<>();
270  List<Integer> targetCases = new ArrayList<>();
271  if (targetCase != 0) {
272  targetCases.add(caseID);
273  targetCases.add(targetCase);
274  }
275  while (resultSet.next()) {
276  String corValue = InstanceTableCallback.getValue(resultSet);
277  if (corValue == null || HashUtility.isNoDataMd5(corValue)) {
278  continue;
279  }
280  values.add(corValue);
281  }
282  for (String corValue : values) {
283  List<CorrelationAttributeInstance> instances;
284  if (targetCases.isEmpty()) {
285  instances = CentralRepository.getInstance().getArtifactInstancesByTypeValues(correlationType, Arrays.asList(corValue));
286  } else {
287  instances = CentralRepository.getInstance().getArtifactInstancesByTypeValuesAndCases(correlationType, Arrays.asList(corValue), targetCases);
288  }
289  int size = instances.stream().map(instance -> instance.getCorrelationDataSource().getID()).collect(Collectors.toSet()).size();
290  if (size > 1) {
291  CommonAttributeValue commonAttributeValue = new CommonAttributeValue(corValue);
292  boolean anotherCase = false;
293  for (CorrelationAttributeInstance instance : instances) {
294  CentralRepoCommonAttributeInstance searchResult = new CentralRepoCommonAttributeInstance(instance.getID(), correlationType, NODE_TYPE.COUNT_NODE);
295  searchResult.setCurrentAttributeInst(instance);
296  commonAttributeValue.addInstance(searchResult);
297  anotherCase = anotherCase || instance.getCorrelationCase().getID() != caseID;
298  }
299  if (anotherCase) {
300  if (instanceCollatedCommonFiles.containsKey(size)) {
301  instanceCollatedCommonFiles.get(size).addMetadataToList(commonAttributeValue);
302  } else {
304  value.addMetadataToList(commonAttributeValue);
305  instanceCollatedCommonFiles.put(size, value);
306  }
307  }
308  }
309  }
311  LOGGER.log(Level.WARNING, "Error getting artifact instances from database.", ex); // NON-NLS
312  }
313  }
314 
315  Map<Integer, CommonAttributeValueList> getInstanceCollatedCommonFiles() {
316  return Collections.unmodifiableSortedMap(instanceCollatedCommonFiles);
317  }
318  }
319 
324  private class InterCaseByCaseCallback implements CaseDbAccessManager.CaseDbAccessQueryCallback, InstanceTableCallback {
325 
326  private static final int VALUE_BATCH_SIZE = 500;
327  private final Map<String, Map<String, CommonAttributeValueList>> caseCollatedDataSourceCollections = new HashMap<>();
328  private final int caseID;
329  private final int targetCase;
330 
331  private InterCaseByCaseCallback(int caseId) {
332  this(caseId, 0);
333  }
334 
335  private InterCaseByCaseCallback(int caseId, int targetCase) {
336  this.caseID = caseId;
337  this.targetCase = targetCase;
338  }
339 
340  @Override
341  public void process(ResultSet resultSet) {
342  try {
343  List<Integer> targetCases = new ArrayList<>();
344  if (targetCase != 0) {
345  targetCases.add(caseID);
346  targetCases.add(targetCase);
347  }
348  Set<String> values = new HashSet<>();
349  while (resultSet.next()) {
350  String corValue = InstanceTableCallback.getValue(resultSet);
351  if (corValue == null || HashUtility.isNoDataMd5(corValue)) {
352  continue;
353  }
354  values.add(corValue);
355  }
356  for (List<String> valuesChunk : Iterables.partition(values, VALUE_BATCH_SIZE)) {
357  List<CorrelationAttributeInstance> instances;
358  if (targetCases.isEmpty()) {
359  instances = CentralRepository.getInstance().getArtifactInstancesByTypeValues(correlationType, valuesChunk);
360  } else {
361  instances = CentralRepository.getInstance().getArtifactInstancesByTypeValuesAndCases(correlationType, valuesChunk, targetCases);
362  }
363  if (instances.size() > 1) {
364  for (CorrelationAttributeInstance instance : instances) {
365  CorrelationCase correlationCase = instance.getCorrelationCase();
366  String caseName = correlationCase.getDisplayName();
367  CorrelationDataSource correlationDatasource = instance.getCorrelationDataSource();
368  //label datasource with it's id for uniqueness done in same manner as ImageGallery does in the DataSourceCell class
369  String dataSourceNameKey = correlationDatasource.getName() + " (Id: " + correlationDatasource.getDataSourceObjectID() + ")";
370  if (!caseCollatedDataSourceCollections.containsKey(caseName)) {
371  caseCollatedDataSourceCollections.put(caseName, new HashMap<>());
372  }
373  Map<String, CommonAttributeValueList> dataSourceToFile = caseCollatedDataSourceCollections.get(caseName);
374  if (!dataSourceToFile.containsKey(dataSourceNameKey)) {
375  dataSourceToFile.put(dataSourceNameKey, new CommonAttributeValueList());
376  }
377  CommonAttributeValueList valueList = dataSourceToFile.get(dataSourceNameKey);
378  CentralRepoCommonAttributeInstance searchResult = new CentralRepoCommonAttributeInstance(instance.getID(), correlationType, NODE_TYPE.CASE_NODE);
379  searchResult.setCurrentAttributeInst(instance);
380  CommonAttributeValue commonAttributeValue = new CommonAttributeValue(instance.getCorrelationValue());
381  commonAttributeValue.addInstance(searchResult);
382  valueList.addMetadataToList(commonAttributeValue);
383  dataSourceToFile.put(dataSourceNameKey, valueList);
384  caseCollatedDataSourceCollections.put(caseName, dataSourceToFile);
385  }
386  }
387  }
389  LOGGER.log(Level.WARNING, "Error getting artifact instances from database.", ex); // NON-NLS
390  }
391  }
392 
393  Map<String, Map<String, CommonAttributeValueList>> getInstanceCollatedCommonFiles() {
394  return Collections.unmodifiableMap(caseCollatedDataSourceCollections);
395  }
396  }
397 
403 
404  CorrelationAttributeInstance correlationAttributeInstance = null;
405 
406  @Override
407  public void process(ResultSet resultSet) {
408  try {
410 
411  while (resultSet.next()) {
412  CorrelationCase correlationCase = dbManager.getCaseById(InstanceTableCallback.getCaseId(resultSet));
413  CorrelationDataSource dataSource = dbManager.getDataSourceById(correlationCase, InstanceTableCallback.getDataSourceId(resultSet));
414  try {
415  long fileObjectId = InstanceTableCallback.getFileObjectId(resultSet);
416  if (fileObjectId != 0) {
417  correlationAttributeInstance = dbManager.getCorrelationAttributeInstance(correlationType,
418  correlationCase, dataSource, fileObjectId);
419  } else {
420  correlationAttributeInstance = dbManager.getCorrelationAttributeInstance(correlationType,
421  correlationCase,
422  dataSource,
423  InstanceTableCallback.getValue(resultSet),
425  }
427  LOGGER.log(Level.INFO, "Unable to get CorrelationAttributeInstance.", ex); // NON-NLS
428  }
429 
430  }
431  } catch (SQLException | CentralRepoException ex) {
432  LOGGER.log(Level.WARNING, "Error getting single correlation artifact instance from database.", ex); // NON-NLS
433  }
434  }
435 
436  CorrelationAttributeInstance getCorrelationAttribute() {
437  return correlationAttributeInstance;
438  }
439  }
440 }
List< CorrelationAttributeInstance > getArtifactInstancesByTypeValues(CorrelationAttributeInstance.Type aType, List< String > values)
CorrelationAttributeInstance getCorrelationAttributeInstance(CorrelationAttributeInstance.Type type, CorrelationCase correlationCase, CorrelationDataSource correlationDataSource, String value, String filePath)
List< CorrelationAttributeInstance > getArtifactInstancesByTypeValuesAndCases(CorrelationAttributeInstance.Type aType, List< String > values, List< Integer > caseIds)
CorrelationDataSource getDataSourceById(CorrelationCase correlationCase, int dataSourceId)

Copyright © 2012-2022 Basis Technology. Generated on: Tue Aug 1 2023
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.