Autopsy  4.20.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
CentralRepoIngestModuleUtils.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2021-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.centralrepository.ingestmodule;
20 
21 import java.util.ArrayList;
22 import java.util.Arrays;
23 import java.util.Collection;
24 import java.util.Iterator;
25 import java.util.List;
26 import java.util.Optional;
27 import java.util.Set;
28 import java.util.logging.Level;
29 import java.util.stream.Collectors;
30 import org.openide.util.NbBundle;
40 import org.sleuthkit.datamodel.AbstractFile;
41 import org.sleuthkit.datamodel.AnalysisResult;
42 import org.sleuthkit.datamodel.Blackboard;
43 import org.sleuthkit.datamodel.BlackboardArtifact;
44 import org.sleuthkit.datamodel.BlackboardAttribute;
45 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CORRELATION_TYPE;
46 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CORRELATION_VALUE;
47 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_OTHER_CASES;
48 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME;
49 import org.sleuthkit.datamodel.Content;
50 import org.sleuthkit.datamodel.DataArtifact;
51 import org.sleuthkit.datamodel.Score;
52 import org.sleuthkit.datamodel.TskCoreException;
53 
57 class CentralRepoIngestModuleUtils {
58 
59  private static final Logger LOGGER = Logger.getLogger(CentralRepoDataArtifactIngestModule.class.getName());
60  private static final int MAX_PREV_CASES_FOR_NOTABLE_SCORE = 10;
61  private static final int MAX_PREV_CASES_FOR_PREV_SEEN = 20;
62  private final static String MODULE_NAME = CentralRepoIngestModuleFactory.getModuleName();
63 
72  static List<CorrelationAttributeInstance> getOccurrencesInOtherCases(CorrelationAttributeInstance corrAttr, long ingestJobId) {
73  List<CorrelationAttributeInstance> previousOccurrences = new ArrayList<>();
74  try {
75  CentralRepository centralRepo = CentralRepository.getInstance();
76  previousOccurrences = centralRepo.getArtifactInstancesByTypeValue(corrAttr.getCorrelationType(), corrAttr.getCorrelationValue());
77  for (Iterator<CorrelationAttributeInstance> iterator = previousOccurrences.iterator(); iterator.hasNext();) {
78  CorrelationAttributeInstance prevOccurrence = iterator.next();
79  if (prevOccurrence.getCorrelationCase().getCaseUUID().equals(corrAttr.getCorrelationCase().getCaseUUID())) {
80  iterator.remove();
81  }
82  }
83  } catch (CorrelationAttributeNormalizationException ex) {
84  LOGGER.log(Level.WARNING, String.format("Error normalizing correlation attribute value for 's' (job ID=%d)", corrAttr, ingestJobId), ex); // NON-NLS
85  } catch (CentralRepoException ex) {
86  LOGGER.log(Level.SEVERE, String.format("Error getting previous occurences of correlation attribute 's' (job ID=%d)", corrAttr, ingestJobId), ex); // NON-NLS
87  }
88  return previousOccurrences;
89  }
90 
102  @NbBundle.Messages({
103  "CentralRepoIngestModule_notableSetName=Previously Tagged As Notable (Central Repository)",
104  "# {0} - list of cases",
105  "CentralRepoIngestModule_notableJustification=Previously marked as notable in cases {0}"
106  })
107  static void makePrevNotableAnalysisResult(Content content, Set<String> previousCases, CorrelationAttributeInstance.Type corrAttrType, String corrAttrValue, long dataSourceObjId, long ingestJobId) {
108  String prevCases = previousCases.stream().collect(Collectors.joining(","));
109  String justification = Bundle.CentralRepoIngestModule_notableJustification(prevCases);
110  Collection<BlackboardAttribute> attributes = Arrays.asList(
111  new BlackboardAttribute(TSK_SET_NAME, MODULE_NAME, Bundle.CentralRepoIngestModule_notableSetName()),
112  new BlackboardAttribute(TSK_CORRELATION_TYPE, MODULE_NAME, corrAttrType.getDisplayName()),
113  new BlackboardAttribute(TSK_CORRELATION_VALUE, MODULE_NAME, corrAttrValue),
114  new BlackboardAttribute(TSK_OTHER_CASES, MODULE_NAME, prevCases));
115  Optional<AnalysisResult> result = makeAndPostAnalysisResult(content, BlackboardArtifact.Type.TSK_PREVIOUSLY_NOTABLE, attributes, "", Score.SCORE_NOTABLE, justification, dataSourceObjId, ingestJobId);
116  if (result.isPresent()) {
117  postNotableMessage(content, previousCases, corrAttrValue, result.get());
118  }
119  }
120 
133  @NbBundle.Messages({
134  "CentralRepoIngestModule_prevSeenSetName=Previously Seen (Central Repository)",
135  "# {0} - list of cases",
136  "CentralRepoIngestModule_prevSeenJustification=Previously seen in cases {0}"
137  })
138  static void makePrevSeenAnalysisResult(Content content, Set<String> previousCases, CorrelationAttributeInstance.Type corrAttrType, String corrAttrValue, long dataSourceObjId, long ingestJobId) {
139  Optional<Score> score = calculateScore(previousCases.size());
140  if (score.isPresent()) {
141  String prevCases = previousCases.stream().collect(Collectors.joining(","));
142  String justification = Bundle.CentralRepoIngestModule_prevSeenJustification(prevCases);
143  Collection<BlackboardAttribute> analysisResultAttributes = Arrays.asList(
144  new BlackboardAttribute(TSK_SET_NAME, MODULE_NAME, Bundle.CentralRepoIngestModule_prevSeenSetName()),
145  new BlackboardAttribute(TSK_CORRELATION_TYPE, MODULE_NAME, corrAttrType.getDisplayName()),
146  new BlackboardAttribute(TSK_CORRELATION_VALUE, MODULE_NAME, corrAttrValue),
147  new BlackboardAttribute(TSK_OTHER_CASES, MODULE_NAME, prevCases));
148  makeAndPostAnalysisResult(content, BlackboardArtifact.Type.TSK_PREVIOUSLY_SEEN, analysisResultAttributes, "", score.get(), justification, dataSourceObjId, ingestJobId);
149  }
150  }
151 
161  @NbBundle.Messages({
162  "CentralRepoIngestModule_prevUnseenJustification=Previously seen in zero cases"
163  })
164  static void makePrevUnseenAnalysisResult(Content content, CorrelationAttributeInstance.Type corrAttrType, String corrAttrValue, long dataSourceObjId, long ingestJobId) {
165  Collection<BlackboardAttribute> attributesForNewArtifact = Arrays.asList(
166  new BlackboardAttribute(TSK_CORRELATION_TYPE, MODULE_NAME, corrAttrType.getDisplayName()),
167  new BlackboardAttribute(TSK_CORRELATION_VALUE, MODULE_NAME, corrAttrValue));
168  makeAndPostAnalysisResult(content, BlackboardArtifact.Type.TSK_PREVIOUSLY_UNSEEN, attributesForNewArtifact, "", Score.SCORE_LIKELY_NOTABLE, Bundle.CentralRepoIngestModule_prevUnseenJustification(), dataSourceObjId, ingestJobId);
169  }
170 
180  static Optional<Score> calculateScore(int numPreviousCases) {
181  Score score = null;
182  if (numPreviousCases <= MAX_PREV_CASES_FOR_NOTABLE_SCORE) {
183  score = Score.SCORE_LIKELY_NOTABLE;
184  } else if (numPreviousCases > MAX_PREV_CASES_FOR_NOTABLE_SCORE && numPreviousCases <= MAX_PREV_CASES_FOR_PREV_SEEN) {
185  score = Score.SCORE_NONE;
186  }
187  return Optional.ofNullable(score);
188  }
189 
206  private static Optional<AnalysisResult> makeAndPostAnalysisResult(Content content, BlackboardArtifact.Type analysisResultType, Collection<BlackboardAttribute> analysisResultAttrs, String configuration, Score score, String justification, long dataSourceObjId, long ingestJobId) {
207  AnalysisResult analysisResult = null;
208  try {
209  Blackboard blackboard = Case.getCurrentCaseThrows().getSleuthkitCase().getBlackboard();
210  if (!blackboard.artifactExists(content, analysisResultType, analysisResultAttrs)) {
211  analysisResult = content.newAnalysisResult(analysisResultType, score, null, configuration, justification, analysisResultAttrs, dataSourceObjId).getAnalysisResult();
212  try {
213  blackboard.postArtifact(analysisResult, MODULE_NAME, ingestJobId);
214  } catch (Blackboard.BlackboardException ex) {
215  LOGGER.log(Level.SEVERE, String.format("Error posting analysis result '%s' to blackboard for content 's' (job ID=%d)", analysisResult, content, ingestJobId), ex); //NON-NLS
216  }
217  }
218  } catch (NoCurrentCaseException | TskCoreException ex) {
219  LOGGER.log(Level.SEVERE, String.format("Error creating %s analysis result for content '%s' (job ID=%d)", analysisResultType, content, ingestJobId), ex); // NON-NLS
220  }
221  return Optional.ofNullable(analysisResult);
222  }
223 
237  @NbBundle.Messages({
238  "# {0} - Name of item that is Notable",
239  "CentralRepoIngestModule_notable_inbox_msg_subject=Notable: {0}"
240  })
241  private static void postNotableMessage(Content content, Set<String> otherCases, String corrAttrValue, AnalysisResult analysisResult) {
242  String msgSubject = null;
243  String msgDetails = null;
244  String msgKey = corrAttrValue;
245  if (content instanceof AbstractFile) {
246  AbstractFile file = (AbstractFile) content;
247  msgSubject = Bundle.CentralRepoIngestModule_notable_inbox_msg_subject(file.getName());
248  msgDetails = makeNotableFileMessage(file, otherCases);
249  } else if (content instanceof DataArtifact) {
250  DataArtifact artifact = (DataArtifact) content;
251  msgSubject = Bundle.CentralRepoIngestModule_notable_inbox_msg_subject(artifact.getDisplayName());
252  msgDetails = makeNotableDataArtifactMessage(artifact, corrAttrValue, otherCases);
253  } else {
254  LOGGER.log(Level.SEVERE, "Unsupported Content, cannot post ingest inbox message");
255  }
256  if (msgSubject != null && msgDetails != null) {
257  IngestServices.getInstance().postMessage(
258  IngestMessage.createDataMessage(
259  MODULE_NAME,
260  msgSubject,
261  msgDetails,
262  msgKey,
263  analysisResult));
264  }
265  }
266 
277  @NbBundle.Messages({
278  "CentralRepoIngestModule_filename_inbox_msg_header=File Name",
279  "CentralRepoIngestModule_md5Hash_inbox_msg_header=MD5 Hash",
280  "CentralRepoIngestModule_prev_cases_inbox_msg_header=Previous Cases"
281  })
282  private static String makeNotableFileMessage(AbstractFile file, Set<String> otherCases) {
283  StringBuilder message = new StringBuilder(1024);
284  message.append("<table border='0' cellpadding='4' width='280'>"); //NON-NLS
285  addTableRowMarkup(message, Bundle.CentralRepoIngestModule_filename_inbox_msg_header(), file.getName());
286  addTableRowMarkup(message, Bundle.CentralRepoIngestModule_md5Hash_inbox_msg_header(), file.getMd5Hash());
287  addTableRowMarkup(message, Bundle.CentralRepoIngestModule_prev_cases_inbox_msg_header(), otherCases.stream().collect(Collectors.joining(",")));
288  return message.toString();
289  }
290 
302  @NbBundle.Messages({
303  "CentralRepoIngestModule_artifact_type_inbox_msg_header=Artifact Type",
304  "CentralRepoIngestModule_notable_attr_inbox_msg_header=Notable Attribute"
305  })
306  private static String makeNotableDataArtifactMessage(DataArtifact artifact, String corrAttrValue, Set<String> otherCases) {
307  StringBuilder message = new StringBuilder(1024);
308  message.append("<table border='0' cellpadding='4' width='280'>"); //NON-NLS
309  addTableRowMarkup(message, Bundle.CentralRepoIngestModule_artifact_type_inbox_msg_header(), artifact.getDisplayName());
310  addTableRowMarkup(message, Bundle.CentralRepoIngestModule_notable_attr_inbox_msg_header(), corrAttrValue);
311  addTableRowMarkup(message, Bundle.CentralRepoIngestModule_prev_cases_inbox_msg_header(), otherCases.stream().collect(Collectors.joining(",")));
312  message.append("</table>"); //NON-NLS
313  return message.toString();
314  }
315 
323  private static void addTableRowMarkup(StringBuilder message, String headerText, String cellText) {
324  message.append("<tr>"); //NON-NLS
325  message.append("<th>").append(headerText).append("</th>"); //NON-NLS
326  message.append("<td>").append(cellText).append("</td>"); //NON-NLS
327  message.append("</tr>"); //NON-NLS
328  }
329 
330  /*
331  * Prevents instatiation of this utility class.
332  */
333  private CentralRepoIngestModuleUtils() {
334  }
335 
336 }

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.