Autopsy  4.19.1
Graphical digital forensics platform for The Sleuth Kit and other tools.
PastCasesSummary.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2019-2021 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.datasourcesummary.datamodel;
20 
21 import java.util.ArrayList;
22 import java.util.Arrays;
23 import java.util.Collection;
24 import java.util.Collections;
25 import java.util.HashSet;
26 import java.util.List;
27 import java.util.Set;
28 import java.util.stream.Collectors;
29 import java.util.stream.Stream;
30 import org.apache.commons.lang3.tuple.Pair;
35 import org.sleuthkit.datamodel.BlackboardArtifact;
36 import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
37 import org.sleuthkit.datamodel.BlackboardAttribute;
38 import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
39 import org.sleuthkit.datamodel.Content;
40 import org.sleuthkit.datamodel.DataSource;
41 import org.sleuthkit.datamodel.SleuthkitCase;
42 import org.sleuthkit.datamodel.TskCoreException;
43 
66 public class PastCasesSummary {
67 
71  public static class PastCasesResult {
72 
73  private final List<Pair<String, Long>> sameIdsResults;
74  private final List<Pair<String, Long>> taggedNotable;
75 
82  public PastCasesResult(List<Pair<String, Long>> sameIdsResults, List<Pair<String, Long>> taggedNotable) {
83  this.sameIdsResults = sameIdsResults;
84  this.taggedNotable = taggedNotable;
85  }
86 
90  public List<Pair<String, Long>> getSameIdsResults() {
91  return Collections.unmodifiableList(sameIdsResults);
92  }
93 
97  public List<Pair<String, Long>> getTaggedNotable() {
98  return Collections.unmodifiableList(taggedNotable);
99  }
100  }
101 
102  private static final Set<Integer> ARTIFACT_UPDATE_TYPE_IDS = new HashSet<>(Arrays.asList(
103  ARTIFACT_TYPE.TSK_PREVIOUSLY_SEEN.getTypeID(),
104  ARTIFACT_TYPE.TSK_PREVIOUSLY_NOTABLE.getTypeID()
105  ));
106 
107  private static final String CENTRAL_REPO_INGEST_NAME = CentralRepoIngestModuleFactory.getModuleName().toUpperCase().trim();
108  private static final BlackboardAttribute.Type TYPE_COMMENT = new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_OTHER_CASES);
109 
110  private static final Set<Integer> CR_DEVICE_TYPE_IDS = new HashSet<>(Arrays.asList(
111  ARTIFACT_TYPE.TSK_DEVICE_ATTACHED.getTypeID(),
112  ARTIFACT_TYPE.TSK_DEVICE_INFO.getTypeID(),
113  ARTIFACT_TYPE.TSK_SIM_ATTACHED.getTypeID(),
114  ARTIFACT_TYPE.TSK_WIFI_NETWORK_ADAPTER.getTypeID()
115  ));
116 
117  private static final String CASE_SEPARATOR = ",";
118 
120  private final java.util.logging.Logger logger;
121 
125  public PastCasesSummary() {
126  this(
129  );
130 
131  }
132 
142  SleuthkitCaseProvider provider,
143  java.util.logging.Logger logger) {
144 
145  this.caseProvider = provider;
146  this.logger = logger;
147  }
148 
158  private static boolean isCentralRepoGenerated(List<String> sources) {
159  if (sources == null) {
160  return false;
161  }
162 
163  return sources.stream().anyMatch((str) -> {
164  return str != null && CENTRAL_REPO_INGEST_NAME.equalsIgnoreCase(str.trim());
165  });
166  }
167 
176  private static List<String> getCasesFromArtifact(BlackboardArtifact artifact) {
177  if (artifact == null) {
178  return Collections.emptyList();
179  }
180 
181  BlackboardAttribute commentAttr = null;
182  try {
183  commentAttr = artifact.getAttribute(TYPE_COMMENT);
184  } catch (TskCoreException ignored) {
185  // ignore if no attribute can be found
186  }
187 
188  if (commentAttr == null) {
189  return Collections.emptyList();
190  }
191 
192  if (!isCentralRepoGenerated(commentAttr.getSources())) {
193  return Collections.emptyList();
194  }
195 
196  String justCasesStr = commentAttr.getValueString().trim();
197  return Stream.of(justCasesStr.split(CASE_SEPARATOR))
198  .map(String::trim)
199  .collect(Collectors.toList());
200 
201  }
202 
213  private static List<Pair<String, Long>> getCaseCounts(Stream<String> cases) {
214  Collection<List<String>> groupedCases = cases
215  // group by case insensitive compare of cases
216  .collect(Collectors.groupingBy((caseStr) -> caseStr.toUpperCase().trim()))
217  .values();
218 
219  return groupedCases
220  .stream()
221  // get any cases where an actual case is found
222  .filter((lst) -> lst != null && lst.size() > 0)
223  // get non-normalized (i.e. not all caps) case name and number of items found
224  .map((lst) -> Pair.of(lst.get(0), (long) lst.size()))
225  // sorted descending
226  .sorted((a, b) -> -Long.compare(a.getValue(), b.getValue()))
227  .collect(Collectors.toList());
228  }
229 
240  private BlackboardArtifact getParentArtifact(BlackboardArtifact artifact) throws SleuthkitCaseProvider.SleuthkitCaseProviderException, TskCoreException {
241 
242  BlackboardArtifact sourceArtifact = null;
243  SleuthkitCase skCase = caseProvider.get();
244  Content content = skCase.getContentById(artifact.getObjectID());
245  if (content instanceof BlackboardArtifact) {
246  sourceArtifact = (BlackboardArtifact) content;
247  }
248  return sourceArtifact;
249  }
250 
261  private boolean hasDeviceAssociatedArtifact(BlackboardArtifact artifact) throws SleuthkitCaseProvider.SleuthkitCaseProviderException, TskCoreException {
262  BlackboardArtifact parent = getParentArtifact(artifact);
263  if (parent == null) {
264  return false;
265  }
266 
267  return CR_DEVICE_TYPE_IDS.contains(parent.getArtifactTypeID());
268  }
269 
281  public PastCasesResult getPastCasesData(DataSource dataSource)
282  throws SleuthkitCaseProvider.SleuthkitCaseProviderException, TskCoreException {
283 
284  if (dataSource == null) {
285  return null;
286  }
287 
288  SleuthkitCase skCase = caseProvider.get();
289 
290  List<String> deviceArtifactCases = new ArrayList<>();
291  List<String> nonDeviceArtifactCases = new ArrayList<>();
292  for (Integer typeId : ARTIFACT_UPDATE_TYPE_IDS) {
293  for (BlackboardArtifact artifact : skCase.getBlackboard().getArtifacts(typeId, dataSource.getId())) {
294  List<String> cases = getCasesFromArtifact(artifact);
295  if (cases == null || cases.isEmpty()) {
296  continue;
297  }
298 
299  if (hasDeviceAssociatedArtifact(artifact)) {
300  deviceArtifactCases.addAll(cases);
301  } else {
302  nonDeviceArtifactCases.addAll(cases);
303  }
304  }
305  }
306 
307  return new PastCasesResult(
308  getCaseCounts(deviceArtifactCases.stream()),
309  getCaseCounts(nonDeviceArtifactCases.stream())
310  );
311  }
312 }
BlackboardArtifact getParentArtifact(BlackboardArtifact artifact)
PastCasesResult(List< Pair< String, Long >> sameIdsResults, List< Pair< String, Long >> taggedNotable)
static List< Pair< String, Long > > getCaseCounts(Stream< String > cases)
static List< String > getCasesFromArtifact(BlackboardArtifact artifact)
synchronized static Logger getLogger(String name)
Definition: Logger.java:124
PastCasesSummary(SleuthkitCaseProvider provider, java.util.logging.Logger logger)

Copyright © 2012-2021 Basis Technology. Generated on: Thu Sep 30 2021
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.