Autopsy 4.22.1
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 */
19package org.sleuthkit.autopsy.centralrepository.ingestmodule;
20
21import java.util.HashSet;
22import java.util.LinkedHashSet;
23import java.util.List;
24import java.util.Set;
25import java.util.logging.Level;
26import org.apache.commons.lang3.StringUtils;
27import org.openide.util.NbBundle;
28import org.sleuthkit.autopsy.casemodule.Case;
29import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
30import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoDbManager;
31import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoException;
32import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoPlatforms;
33import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
34import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance;
35import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeUtil;
36import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationCase;
37import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationDataSource;
38import static org.sleuthkit.autopsy.centralrepository.ingestmodule.CentralRepoIngestModuleUtils.getOccurrencesInOtherCases;
39import static org.sleuthkit.autopsy.centralrepository.ingestmodule.CentralRepoIngestModuleUtils.makePrevNotableAnalysisResult;
40import static org.sleuthkit.autopsy.centralrepository.ingestmodule.CentralRepoIngestModuleUtils.makePrevSeenAnalysisResult;
41import static org.sleuthkit.autopsy.centralrepository.ingestmodule.CentralRepoIngestModuleUtils.makePrevUnseenAnalysisResult;
42import org.sleuthkit.autopsy.coreutils.Logger;
43import org.sleuthkit.autopsy.ingest.DataArtifactIngestModule;
44import org.sleuthkit.autopsy.ingest.IngestJobContext;
45import org.sleuthkit.datamodel.DataArtifact;
46import org.sleuthkit.datamodel.Image;
47import org.sleuthkit.datamodel.OsAccount;
48import org.sleuthkit.datamodel.OsAccountManager;
49import org.sleuthkit.datamodel.TskCoreException;
50import org.sleuthkit.datamodel.TskData;
51
59public class CentralRepoDataArtifactIngestModule implements DataArtifactIngestModule {
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
95 this.context = context;
96
98 throw new IngestModuleException(Bundle.CentralRepoIngestModule_crNotEnabledErrMsg()); // May be displayed to user.
99 }
100
101 try {
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) {
135 if (corrAttrValuesAlreadyProcessed.add(corrAttr.toString())) {
136 makeAnalysisResults(artifact, corrAttr);
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
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
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() {
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() {
247 try {
248 OsAccountManager osAccountMgr = Case.getCurrentCaseThrows().getSleuthkitCase().getOsAccountManager();
249 List<OsAccount> osAccounts = osAccountMgr.getOsAccountsByDataSourceObjId(context.getDataSource().getId());
250 for (OsAccount osAccount : osAccounts) {
251 for (CorrelationAttributeInstance corrAttr : CorrelationAttributeUtil.makeCorrAttrsToSave(osAccount, context.getDataSource())) {
253 makeAnalysisResults(osAccount, corrAttr);
254 }
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) {
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}
static List< CorrelationAttributeInstance > makeCorrAttrsToSave(DataArtifact artifact)
static CorrelationDataSource fromTSKDataSource(CorrelationCase correlationCase, Content dataSource)
synchronized static Logger getLogger(String name)
Definition Logger.java:124

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