Autopsy  4.19.3
Graphical digital forensics platform for The Sleuth Kit and other tools.
CentralRepoDataArtifactIngestModule.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.HashSet;
22 import java.util.LinkedHashSet;
23 import java.util.List;
24 import java.util.Set;
25 import java.util.logging.Level;
26 import org.apache.commons.lang3.StringUtils;
27 import org.openide.util.NbBundle;
38 import static org.sleuthkit.autopsy.centralrepository.ingestmodule.CentralRepoIngestModuleUtils.getOccurrencesInOtherCases;
39 import static org.sleuthkit.autopsy.centralrepository.ingestmodule.CentralRepoIngestModuleUtils.makePrevNotableAnalysisResult;
40 import static org.sleuthkit.autopsy.centralrepository.ingestmodule.CentralRepoIngestModuleUtils.makePrevSeenAnalysisResult;
41 import static org.sleuthkit.autopsy.centralrepository.ingestmodule.CentralRepoIngestModuleUtils.makePrevUnseenAnalysisResult;
45 import org.sleuthkit.datamodel.DataArtifact;
46 import org.sleuthkit.datamodel.Image;
47 import org.sleuthkit.datamodel.OsAccount;
48 import org.sleuthkit.datamodel.OsAccountManager;
49 import org.sleuthkit.datamodel.TskCoreException;
50 import org.sleuthkit.datamodel.TskData;
51 
60 
61  private static final Logger LOGGER = Logger.getLogger(CentralRepoDataArtifactIngestModule.class.getName());
62  private final boolean flagNotableItems;
63  private final boolean flagPrevSeenDevices;
64  private final boolean flagUniqueArtifacts;
65  private final boolean saveCorrAttrInstances;
66  private final Set<String> corrAttrValuesAlreadyProcessed;
69 
79  CentralRepoDataArtifactIngestModule(IngestSettings settings) {
80  flagNotableItems = settings.isFlagTaggedNotableItems();
81  flagPrevSeenDevices = settings.isFlagPreviousDevices();
82  flagUniqueArtifacts = settings.isFlagUniqueArtifacts();
83  saveCorrAttrInstances = settings.shouldCreateCorrelationProperties();
84  corrAttrValuesAlreadyProcessed = new LinkedHashSet<>();
85  }
86 
87  @NbBundle.Messages({
88  "CentralRepoIngestModule_crNotEnabledErrMsg=Central repository required, but not enabled",
89  "CentralRepoIngestModule_crInaccessibleErrMsg=Error accessing central repository",
90  "CentralRepoIngestModule_noCurrentCaseErrMsg=Error getting current case",
91  "CentralRepoIngestModule_crDatabaseTypeMismatch=Mulit-user cases require a PostgreSQL central repository"
92  })
93  @Override
94  public void startUp(IngestJobContext context) throws IngestModuleException {
95  this.context = context;
96 
98  throw new IngestModuleException(Bundle.CentralRepoIngestModule_crNotEnabledErrMsg()); // May be displayed to user.
99  }
100 
101  try {
102  centralRepo = CentralRepository.getInstance();
103  } catch (CentralRepoException ex) {
104  throw new IngestModuleException(Bundle.CentralRepoIngestModule_crInaccessibleErrMsg(), ex);
105  }
106 
107  /*
108  * Don't allow a SQLite central repository to be used for a multi-user
109  * case.
110  */
111  try {
112  Case currentCase = Case.getCurrentCaseThrows();
114  throw new IngestModuleException(Bundle.CentralRepoIngestModule_crDatabaseTypeMismatch());
115  }
116  } catch (NoCurrentCaseException ex) {
117  throw new IngestModuleException(Bundle.CentralRepoIngestModule_noCurrentCaseErrMsg(), ex);
118  }
119  }
120 
131  @Override
132  public ProcessResult process(DataArtifact artifact) {
133  if (flagNotableItems || flagPrevSeenDevices || flagUniqueArtifacts || saveCorrAttrInstances) {
135  if (corrAttrValuesAlreadyProcessed.add(corrAttr.toString())) {
136  makeAnalysisResults(artifact, corrAttr);
137  if (saveCorrAttrInstances) {
138  try {
139  centralRepo.addAttributeInstanceBulk(corrAttr);
140  } catch (CentralRepoException ex) {
141  LOGGER.log(Level.SEVERE, String.format("Error adding correlation attribute '%s' to central repository for '%s' (job ID=%d)", corrAttr, artifact, context.getJobId()), ex); //NON-NLS
142  }
143  }
144  }
145  }
146  }
147  return ProcessResult.OK;
148  }
149 
157  private void makeAnalysisResults(DataArtifact artifact, CorrelationAttributeInstance corrAttr) {
158  List<CorrelationAttributeInstance> previousOccurrences = null;
159  if (flagNotableItems) {
160  previousOccurrences = getOccurrencesInOtherCases(corrAttr, context.getJobId());
161  if (!previousOccurrences.isEmpty()) {
162  Set<String> previousCases = new HashSet<>();
163  for (CorrelationAttributeInstance occurrence : previousOccurrences) {
164  if (occurrence.getKnownStatus() == TskData.FileKnown.BAD) {
165  previousCases.add(occurrence.getCorrelationCase().getDisplayName());
166  }
167  }
168  if (!previousCases.isEmpty()) {
169  makePrevNotableAnalysisResult(artifact, previousCases, corrAttr.getCorrelationType(), corrAttr.getCorrelationValue(), context.getDataSource().getId(), context.getJobId());
170  }
171  }
172  }
173 
174  if (flagPrevSeenDevices
182  if (previousOccurrences == null) {
183  previousOccurrences = getOccurrencesInOtherCases(corrAttr, context.getJobId());
184  }
185  if (!previousOccurrences.isEmpty()) {
186  Set<String> previousCases = getPreviousCases(previousOccurrences);
187  if (!previousCases.isEmpty()) {
188  makePrevSeenAnalysisResult(artifact, previousCases, corrAttr.getCorrelationType(), corrAttr.getCorrelationValue(), context.getDataSource().getId(), context.getJobId());
189  }
190  }
191  }
192 
193  if (flagUniqueArtifacts
196  if (previousOccurrences == null) {
197  previousOccurrences = getOccurrencesInOtherCases(corrAttr, context.getJobId());
198  }
199  if (previousOccurrences.isEmpty()) {
200  makePrevUnseenAnalysisResult(artifact, corrAttr.getCorrelationType(), corrAttr.getCorrelationValue(), context.getDataSource().getId(), context.getJobId());
201  }
202  }
203  }
204 
213  private Set<String> getPreviousCases(List<CorrelationAttributeInstance> previousOccurrences) {
214  Set<String> previousCases = new HashSet<>();
215  for (CorrelationAttributeInstance occurrence : previousOccurrences) {
216  previousCases.add(occurrence.getCorrelationCase().getDisplayName());
217  }
218  return previousCases;
219  }
220 
221  @Override
222  public void shutDown() {
224  if (saveCorrAttrInstances) {
225  try {
226  centralRepo.commitAttributeInstancesBulk();
227  } catch (CentralRepoException ex) {
228  LOGGER.log(Level.SEVERE, String.format("Error doing final bulk commit of correlation attributes (job ID=%d)", context.getJobId()), ex); // NON-NLS
229  }
230  }
232  }
233 
241  @NbBundle.Messages({
242  "CentralRepoIngestModule_prevSeenOsAcctSetName=Users seen in previous cases",
243  "CentralRepoIngestModule_prevSeenOsAcctConfig=Previously Seen Users (Central Repository)"
244  })
245  private void analyzeOsAccounts() {
246  if (saveCorrAttrInstances || flagPrevSeenDevices) {
247  try {
248  OsAccountManager osAccountMgr = Case.getCurrentCaseThrows().getSleuthkitCase().getOsAccountManager();
249  List<OsAccount> osAccounts = osAccountMgr.getOsAccountsByDataSourceObjId(context.getDataSource().getId());
250  for (OsAccount osAccount : osAccounts) {
252  if (flagPrevSeenDevices) {
253  makeAnalysisResults(osAccount, corrAttr);
254  }
255  if (saveCorrAttrInstances) {
256  try {
257  centralRepo.addAttributeInstanceBulk(corrAttr);
258  } catch (CentralRepoException ex) {
259  LOGGER.log(Level.SEVERE, String.format("Error adding correlation attribute '%s' to central repository for '%s'(job ID=%d)", corrAttr, osAccount, context.getJobId()), ex); //NON-NLS
260  }
261  }
262  }
263  }
264  } catch (NoCurrentCaseException | TskCoreException ex) {
265  LOGGER.log(Level.SEVERE, String.format("Error getting OS accounts for data source '%s' (job ID=%d)", context.getDataSource(), context.getJobId()), ex);
266  }
267  }
268  }
269 
277  private void makeAnalysisResults(OsAccount osAccount, CorrelationAttributeInstance corrAttr) {
278  if (flagPrevSeenDevices) {
279  List<CorrelationAttributeInstance> previousOccurrences = getOccurrencesInOtherCases(corrAttr, context.getJobId());
280  if (!previousOccurrences.isEmpty()) {
281  Set<String> previousCases = getPreviousCases(previousOccurrences);
282  if (!previousCases.isEmpty()) {
283  makePrevSeenAnalysisResult(osAccount, previousCases, corrAttr.getCorrelationType(), corrAttr.getCorrelationValue(), context.getDataSource().getId(), context.getJobId());
284  }
285  }
286  }
287  }
288 
293  private void syncDataSourceHashes() {
294  if (!(context.getDataSource() instanceof Image)) {
295  return;
296  }
297 
298  try {
299  Case currentCase = Case.getCurrentCaseThrows();
300  CorrelationCase correlationCase = centralRepo.getCase(currentCase);
301  if (correlationCase == null) {
302  correlationCase = centralRepo.newCase(currentCase);
303  }
304 
305  CorrelationDataSource correlationDataSource = centralRepo.getDataSource(correlationCase, context.getDataSource().getId());
306  if (correlationDataSource == null) {
307  correlationDataSource = CorrelationDataSource.fromTSKDataSource(correlationCase, context.getDataSource());
308  }
309 
310  Image image = (Image) context.getDataSource();
311  String imageMd5Hash = image.getMd5();
312  if (imageMd5Hash == null) {
313  imageMd5Hash = "";
314  }
315  String crMd5Hash = correlationDataSource.getMd5();
316  if (StringUtils.equals(imageMd5Hash, crMd5Hash) == false) {
317  correlationDataSource.setMd5(imageMd5Hash);
318  }
319 
320  String imageSha1Hash = image.getSha1();
321  if (imageSha1Hash == null) {
322  imageSha1Hash = "";
323  }
324  String crSha1Hash = correlationDataSource.getSha1();
325  if (StringUtils.equals(imageSha1Hash, crSha1Hash) == false) {
326  correlationDataSource.setSha1(imageSha1Hash);
327  }
328 
329  String imageSha256Hash = image.getSha256();
330  if (imageSha256Hash == null) {
331  imageSha256Hash = "";
332  }
333  String crSha256Hash = correlationDataSource.getSha256();
334  if (StringUtils.equals(imageSha256Hash, crSha256Hash) == false) {
335  correlationDataSource.setSha256(imageSha256Hash);
336  }
337 
338  } catch (CentralRepoException ex) {
339  LOGGER.log(Level.SEVERE, String.format("Error fetching data from the central repository for data source '%s' (job ID=%d)", context.getDataSource().getName(), context.getJobId()), ex);
340  } catch (NoCurrentCaseException | TskCoreException ex) {
341  LOGGER.log(Level.SEVERE, String.format("Error fetching data from the case database for data source '%s' (job ID=%d)", context.getDataSource().getName(), context.getJobId()), ex);
342  }
343  }
344 
345 }
void addAttributeInstanceBulk(CorrelationAttributeInstance eamArtifact)
Set< String > getPreviousCases(List< CorrelationAttributeInstance > previousOccurrences)
static CorrelationDataSource fromTSKDataSource(CorrelationCase correlationCase, Content dataSource)
static List< CorrelationAttributeInstance > makeCorrAttrsToSave(DataArtifact artifact)
CorrelationDataSource getDataSource(CorrelationCase correlationCase, Long caseDbDataSourceId)
synchronized static Logger getLogger(String name)
Definition: Logger.java:124

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