Autopsy 4.22.1
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 */
19package org.sleuthkit.autopsy.commonpropertiessearch;
20
21import com.google.common.collect.Iterables;
22import java.sql.ResultSet;
23import java.sql.SQLException;
24import java.util.ArrayList;
25import java.util.Arrays;
26import java.util.Collections;
27import java.util.HashMap;
28import java.util.HashSet;
29import java.util.Set;
30import java.util.List;
31import java.util.Map;
32import java.util.TreeMap;
33import java.util.logging.Level;
34import java.util.stream.Collectors;
35import org.sleuthkit.autopsy.casemodule.Case;
36import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance;
37import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance.Type;
38import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeNormalizationException;
39import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationCase;
40import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationDataSource;
41import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoException;
42import org.sleuthkit.autopsy.centralrepository.datamodel.InstanceTableCallback;
43import org.sleuthkit.autopsy.commonpropertiessearch.AbstractCommonAttributeInstance.NODE_TYPE;
44import org.sleuthkit.autopsy.coreutils.Logger;
45import org.sleuthkit.datamodel.CaseDbAccessManager;
46import org.sleuthkit.datamodel.TskData;
47import org.sleuthkit.datamodel.HashUtility;
48import org.sleuthkit.datamodel.TskCoreException;
49import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
50
55final 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
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,
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)
CorrelationDataSource getDataSourceById(CorrelationCase correlationCase, int dataSourceId)
List< CorrelationAttributeInstance > getArtifactInstancesByTypeValuesAndCases(CorrelationAttributeInstance.Type aType, List< String > values, List< Integer > caseIds)
CorrelationAttributeInstance getCorrelationAttributeInstance(CorrelationAttributeInstance.Type type, CorrelationCase correlationCase, CorrelationDataSource correlationDataSource, String value, String filePath)

Copyright © 2012-2024 Sleuth Kit Labs. Generated on:
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.