Autopsy  4.5.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
CaseEventListener.java
Go to the documentation of this file.
1 /*
2  * Central Repository
3  *
4  * Copyright 2015-2017 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.eventlisteners;
20 
21 import com.google.common.util.concurrent.ThreadFactoryBuilder;
22 import java.beans.PropertyChangeEvent;
23 import java.beans.PropertyChangeListener;
24 import java.util.List;
25 import java.util.concurrent.ExecutorService;
26 import java.util.concurrent.Executors;
27 import java.util.logging.Level;
28 import java.util.stream.Collectors;
29 import org.openide.util.NbBundle.Messages;
46 import org.sleuthkit.datamodel.AbstractFile;
47 import org.sleuthkit.datamodel.BlackboardArtifact;
48 import org.sleuthkit.datamodel.BlackboardArtifactTag;
49 import org.sleuthkit.datamodel.Content;
50 import org.sleuthkit.datamodel.ContentTag;
51 import org.sleuthkit.datamodel.TagName;
52 import org.sleuthkit.datamodel.TskCoreException;
53 import org.sleuthkit.datamodel.TskData;
54 import org.sleuthkit.datamodel.TskDataException;
55 
60 @Messages({"caseeventlistener.evidencetag=Evidence"})
61 final class CaseEventListener implements PropertyChangeListener {
62 
63  private static final Logger LOGGER = Logger.getLogger(CaseEventListener.class.getName());
64  private final ExecutorService jobProcessingExecutor;
65  private static final String CASE_EVENT_THREAD_NAME = "Case-Event-Listener-%d";
66 
67  CaseEventListener() {
68  jobProcessingExecutor = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder().setNameFormat(CASE_EVENT_THREAD_NAME).build());
69  }
70 
71  void shutdown() {
72  ThreadUtils.shutDownTaskExecutor(jobProcessingExecutor);
73  }
74 
75  @Override
76  public void propertyChange(PropertyChangeEvent evt) {
77  EamDb dbManager;
78  try {
79  dbManager = EamDb.getInstance();
80  } catch (EamDbException ex) {
81  LOGGER.log(Level.SEVERE, "Failed to get instance of db manager.", ex);
82  return;
83  }
84  switch (Case.Events.valueOf(evt.getPropertyName())) {
85  case CONTENT_TAG_ADDED:
86  case CONTENT_TAG_DELETED: {
87  jobProcessingExecutor.submit(new ContentTagTask(dbManager, evt));
88  }
89  break;
90 
91  case BLACKBOARD_ARTIFACT_TAG_DELETED:
92  case BLACKBOARD_ARTIFACT_TAG_ADDED: {
93  jobProcessingExecutor.submit(new BlackboardTagTask(dbManager, evt));
94  }
95  break;
96 
97  case DATA_SOURCE_ADDED: {
98  jobProcessingExecutor.submit(new DataSourceAddedTask(dbManager, evt));
99  }
100  break;
101  case TAG_DEFINITION_CHANGED: {
102  jobProcessingExecutor.submit(new TagDefinitionChangeTask(evt));
103  }
104  break;
105  case CURRENT_CASE: {
106  jobProcessingExecutor.submit(new CurrentCaseTask(dbManager, evt));
107  }
108  break;
109  }
110  }
111 
112  private final class ContentTagTask implements Runnable {
113 
114  private final EamDb dbManager;
115  private final PropertyChangeEvent event;
116 
117  private ContentTagTask(EamDb db, PropertyChangeEvent evt) {
118  dbManager = db;
119  event = evt;
120  }
121 
122  @Override
123  public void run() {
124  if (!EamDb.isEnabled()) {
125  return;
126  }
127 
128  AbstractFile af;
129  TskData.FileKnown knownStatus;
130  String comment;
131  if (Case.Events.valueOf(event.getPropertyName()) == Case.Events.CONTENT_TAG_ADDED) {
132  // For added tags, we want to change the known status to BAD if the
133  // tag that was just added is in the list of central repo tags.
134  final ContentTagAddedEvent tagAddedEvent = (ContentTagAddedEvent) event;
135  final ContentTag tagAdded = tagAddedEvent.getAddedTag();
136 
137  if (TagsManager.getNotableTagDisplayNames().contains(tagAdded.getName().getDisplayName())) {
138  if (tagAdded.getContent() instanceof AbstractFile) {
139  af = (AbstractFile) tagAdded.getContent();
140  knownStatus = TskData.FileKnown.BAD;
141  comment = tagAdded.getComment();
142  } else {
143  LOGGER.log(Level.WARNING, "Error updating non-file object");
144  return;
145  }
146  } else {
147  // The added tag isn't flagged as bad in central repo, so do nothing
148  return;
149  }
150  } else { // CONTENT_TAG_DELETED
151  // For deleted tags, we want to set the file status to UNKNOWN if:
152  // - The tag that was just removed is notable in central repo
153  // - There are no remaining tags that are notable
154  final ContentTagDeletedEvent tagDeletedEvent = (ContentTagDeletedEvent) event;
155  long contentID = tagDeletedEvent.getDeletedTagInfo().getContentID();
156 
157  String tagName = tagDeletedEvent.getDeletedTagInfo().getName().getDisplayName();
158  if (!TagsManager.getNotableTagDisplayNames().contains(tagName)) {
159  // If the tag that got removed isn't on the list of central repo tags, do nothing
160  return;
161  }
162 
163  try {
164  // Get the remaining tags on the content object
165  Content content = Case.getCurrentCase().getSleuthkitCase().getContentById(contentID);
167  List<ContentTag> tags = tagsManager.getContentTagsByContent(content);
168 
169  if (tags.stream()
170  .map(tag -> tag.getName().getDisplayName())
171  .filter(TagsManager.getNotableTagDisplayNames()::contains)
172  .collect(Collectors.toList())
173  .isEmpty()) {
174 
175  // There are no more bad tags on the object
176  if (content instanceof AbstractFile) {
177  af = (AbstractFile) content;
178  knownStatus = TskData.FileKnown.UNKNOWN;
179  comment = "";
180  } else {
181  LOGGER.log(Level.WARNING, "Error updating non-file object");
182  return;
183  }
184  } else {
185  // There's still at least one bad tag, so leave the known status as is
186  return;
187  }
188  } catch (TskCoreException ex) {
189  LOGGER.log(Level.SEVERE, "Failed to find content", ex);
190  return;
191  }
192  }
193 
195  knownStatus, comment);
196 
197  if (eamArtifact != null) {
198  // send update to Central Repository db
199  try {
200  dbManager.setArtifactInstanceKnownStatus(eamArtifact, knownStatus);
201  } catch (EamDbException ex) {
202  LOGGER.log(Level.SEVERE, "Error connecting to Central Repository database while setting artifact known status.", ex); //NON-NLS
203  }
204  }
205  } // CONTENT_TAG_ADDED, CONTENT_TAG_DELETED
206  }
207 
208  private final class BlackboardTagTask implements Runnable {
209 
210  private final EamDb dbManager;
211  private final PropertyChangeEvent event;
212 
213  private BlackboardTagTask(EamDb db, PropertyChangeEvent evt) {
214  dbManager = db;
215  event = evt;
216  }
217 
218  @Override
219  public void run() {
220  if (!EamDb.isEnabled()) {
221  return;
222  }
223 
224  Content content;
225  BlackboardArtifact bbArtifact;
226  TskData.FileKnown knownStatus;
227  String comment;
228  if (Case.Events.valueOf(event.getPropertyName()) == Case.Events.BLACKBOARD_ARTIFACT_TAG_ADDED) {
229  // For added tags, we want to change the known status to BAD if the
230  // tag that was just added is in the list of central repo tags.
232  final BlackboardArtifactTag tagAdded = tagAddedEvent.getAddedTag();
233 
234  if (TagsManager.getNotableTagDisplayNames().contains(tagAdded.getName().getDisplayName())) {
235  content = tagAdded.getContent();
236  bbArtifact = tagAdded.getArtifact();
237  knownStatus = TskData.FileKnown.BAD;
238  comment = tagAdded.getComment();
239  } else {
240  // The added tag isn't flagged as bad in central repo, so do nothing
241  return;
242  }
243  } else { //BLACKBOARD_ARTIFACT_TAG_DELETED
244  // For deleted tags, we want to set the file status to UNKNOWN if:
245  // - The tag that was just removed is notable in central repo
246  // - There are no remaining tags that are notable
248  long contentID = tagDeletedEvent.getDeletedTagInfo().getContentID();
249  long artifactID = tagDeletedEvent.getDeletedTagInfo().getArtifactID();
250 
251  String tagName = tagDeletedEvent.getDeletedTagInfo().getName().getDisplayName();
252  if (!TagsManager.getNotableTagDisplayNames().contains(tagName)) {
253  // If the tag that got removed isn't on the list of central repo tags, do nothing
254  return;
255  }
256 
257  try {
258  // Get the remaining tags on the artifact
259  content = Case.getCurrentCase().getSleuthkitCase().getContentById(contentID);
260  bbArtifact = Case.getCurrentCase().getSleuthkitCase().getBlackboardArtifact(artifactID);
262  List<BlackboardArtifactTag> tags = tagsManager.getBlackboardArtifactTagsByArtifact(bbArtifact);
263 
264  if (tags.stream()
265  .map(tag -> tag.getName().getDisplayName())
266  .filter(TagsManager.getNotableTagDisplayNames()::contains)
267  .collect(Collectors.toList())
268  .isEmpty()) {
269 
270  // There are no more bad tags on the object
271  knownStatus = TskData.FileKnown.UNKNOWN;
272  comment = "";
273 
274  } else {
275  // There's still at least one bad tag, so leave the known status as is
276  return;
277  }
278  } catch (TskCoreException ex) {
279  LOGGER.log(Level.SEVERE, "Failed to find content", ex);
280  return;
281  }
282  }
283 
284  if ((content instanceof AbstractFile) && (((AbstractFile) content).getKnown() == TskData.FileKnown.KNOWN)) {
285  return;
286  }
287 
288  List<CorrelationAttribute> convertedArtifacts = EamArtifactUtil.getCorrelationAttributeFromBlackboardArtifact(bbArtifact, true, true);
289  for (CorrelationAttribute eamArtifact : convertedArtifacts) {
290  eamArtifact.getInstances().get(0).setComment(comment);
291  try {
292  dbManager.setArtifactInstanceKnownStatus(eamArtifact, knownStatus);
293  } catch (EamDbException ex) {
294  LOGGER.log(Level.SEVERE, "Error connecting to Central Repository database while setting artifact known status.", ex); //NON-NLS
295  }
296  }
297  } // BLACKBOARD_ARTIFACT_TAG_ADDED, BLACKBOARD_ARTIFACT_TAG_DELETED
298 
299  }
300 
301  private final class TagDefinitionChangeTask implements Runnable {
302 
303  private final PropertyChangeEvent event;
304 
305  private TagDefinitionChangeTask(PropertyChangeEvent evt) {
306  event = evt;
307  }
308 
309  @Override
310  public void run() {
311  if (!EamDb.isEnabled()) {
312  return;
313  }
314  //get the display name of the tag that has had it's definition modified
315  String modifiedTagName = (String) event.getOldValue();
316 
317  /*
318  * Set knownBad status for all files/artifacts in the given case
319  * that are tagged with the given tag name.
320  */
321  try {
322  TagName tagName = Case.getCurrentCase().getServices().getTagsManager().getDisplayNamesToTagNamesMap().get(modifiedTagName);
323  //First update the artifacts
324  //Get all BlackboardArtifactTags with this tag name
325  List<BlackboardArtifactTag> artifactTags = Case.getCurrentCase().getSleuthkitCase().getBlackboardArtifactTagsByTagName(tagName);
326  for (BlackboardArtifactTag bbTag : artifactTags) {
327  //start with assumption that none of the other tags applied to this Correlation Attribute will prevent it's status from being changed
328  boolean hasTagWithConflictingKnownStatus = false;
329  // if the status of the tag has been changed to TskData.FileKnown.UNKNOWN
330  // we need to check the status of all other tags on this correlation attribute before changing
331  // the status of the correlation attribute in the central repository
332  if (tagName.getKnownStatus() == TskData.FileKnown.UNKNOWN) {
333  Content content = bbTag.getContent();
334  // If the content which this Blackboard Artifact Tag is linked to is an AbstractFile with KNOWN status then
335  // it's status in the central reporsitory should not be changed to UNKNOWN
336  if ((content instanceof AbstractFile) && (((AbstractFile) content).getKnown() == TskData.FileKnown.KNOWN)) {
337  continue;
338  }
339  //Get the BlackboardArtifact which this BlackboardArtifactTag has been applied to.
340  BlackboardArtifact bbArtifact = bbTag.getArtifact();
342  List<BlackboardArtifactTag> tags = tagsManager.getBlackboardArtifactTagsByArtifact(bbArtifact);
343  //get all tags which are on this blackboard artifact
344  for (BlackboardArtifactTag t : tags) {
345  //All instances of the modified tag name will be changed, they can not conflict with each other
346  if (t.getName().equals(tagName)) {
347  continue;
348  }
349  //if any other tags on this artifact are Notable in status then this artifact can not have its status changed
350  if (TskData.FileKnown.BAD == t.getName().getKnownStatus()) {
351  //a tag with a conflicting status has been found, the status of this correlation attribute can not be modified
352  hasTagWithConflictingKnownStatus = true;
353  break;
354  }
355  }
356  }
357  //if the Correlation Attribute will have no tags with a status which would prevent the current status from being changed
358  if (!hasTagWithConflictingKnownStatus) {
359  //Get the correlation atttributes that correspond to the current BlackboardArtifactTag if their status should be changed
360  //with the initial set of correlation attributes this should be a single correlation attribute
361  List<CorrelationAttribute> convertedArtifacts = EamArtifactUtil.getCorrelationAttributeFromBlackboardArtifact(bbTag.getArtifact(), true, true);
362  for (CorrelationAttribute eamArtifact : convertedArtifacts) {
363  EamDb.getInstance().setArtifactInstanceKnownStatus(eamArtifact, tagName.getKnownStatus());
364  }
365  }
366  }
367  // Next update the files
368 
369  List<ContentTag> fileTags = Case.getCurrentCase().getSleuthkitCase().getContentTagsByTagName(tagName);
370  //Get all ContentTags with this tag name
371  for (ContentTag contentTag : fileTags) {
372  //start with assumption that none of the other tags applied to this ContentTag will prevent it's status from being changed
373  boolean hasTagWithConflictingKnownStatus = false;
374  // if the status of the tag has been changed to TskData.FileKnown.UNKNOWN
375  // we need to check the status of all other tags on this file before changing
376  // the status of the file in the central repository
377  if (tagName.getKnownStatus() == TskData.FileKnown.UNKNOWN) {
378  Content content = contentTag.getContent();
380  List<ContentTag> tags = tagsManager.getContentTagsByContent(content);
381  //get all tags which are on this file
382  for (ContentTag t : tags) {
383  //All instances of the modified tag name will be changed, they can not conflict with each other
384  if (t.getName().equals(tagName)) {
385  continue;
386  }
387  //if any other tags on this file are Notable in status then this file can not have its status changed
388  if (TskData.FileKnown.BAD == t.getName().getKnownStatus()) {
389  //a tag with a conflicting status has been found, the status of this file can not be modified
390  hasTagWithConflictingKnownStatus = true;
391  break;
392  }
393  }
394  }
395  //if the file will have no tags with a status which would prevent the current status from being changed
396  if (!hasTagWithConflictingKnownStatus) {
397  final CorrelationAttribute eamArtifact = EamArtifactUtil.getCorrelationAttributeFromContent(contentTag.getContent(),
398  tagName.getKnownStatus(), "");
399  if (eamArtifact != null) {
400  EamDb.getInstance().setArtifactInstanceKnownStatus(eamArtifact, tagName.getKnownStatus());
401  }
402  }
403  }
404  } catch (TskCoreException ex) {
405  LOGGER.log(Level.SEVERE, "Cannot update known status in central repository for tag: " + modifiedTagName, ex); //NON-NLS
406  } catch (EamDbException ex) {
407  LOGGER.log(Level.SEVERE, "Cannot get central repository for tag: " + modifiedTagName, ex); //NON-NLS
408  }
409  } //TAG_STATUS_CHANGED
410  }
411 
412  private final class DataSourceAddedTask implements Runnable {
413 
414  private final EamDb dbManager;
415  private final PropertyChangeEvent event;
416 
417  private DataSourceAddedTask(EamDb db, PropertyChangeEvent evt) {
418  dbManager = db;
419  event = evt;
420  }
421 
422  @Override
423  public void run() {
424  if (!EamDb.isEnabled()) {
425  return;
426  }
427 
428  final DataSourceAddedEvent dataSourceAddedEvent = (DataSourceAddedEvent) event;
429  Content newDataSource = dataSourceAddedEvent.getDataSource();
430 
431  try {
432  String deviceId = Case.getCurrentCase().getSleuthkitCase().getDataSource(newDataSource.getId()).getDeviceId();
433  CorrelationCase correlationCase = dbManager.getCase(Case.getCurrentCase());
434  if (null == correlationCase) {
435  correlationCase = dbManager.newCase(Case.getCurrentCase());
436  }
437  if (null == dbManager.getDataSource(correlationCase, deviceId)) {
438  dbManager.newDataSource(CorrelationDataSource.fromTSKDataSource(correlationCase, newDataSource));
439  }
440  } catch (EamDbException ex) {
441  LOGGER.log(Level.SEVERE, "Error connecting to Central Repository database.", ex); //NON-NLS
442  } catch (TskCoreException | TskDataException ex) {
443  LOGGER.log(Level.SEVERE, "Error getting data source from DATA_SOURCE_ADDED event content.", ex); //NON-NLS
444  }
445  } // DATA_SOURCE_ADDED
446  }
447 
448  private final class CurrentCaseTask implements Runnable {
449 
450  private final EamDb dbManager;
451  private final PropertyChangeEvent event;
452 
453  private CurrentCaseTask(EamDb db, PropertyChangeEvent evt) {
454  dbManager = db;
455  event = evt;
456  }
457 
458  @Override
459  public void run() {
460  /*
461  * A case has been opened if evt.getOldValue() is null and
462  * evt.getNewValue() is a valid Case.
463  */
464  if ((null == event.getOldValue()) && (event.getNewValue() instanceof Case)) {
465  Case curCase = (Case) event.getNewValue();
466  IngestEventsListener.resetCeModuleInstanceCount();
467 
468  if (!EamDb.isEnabled()) {
469  return;
470  }
471 
472  try {
473  // NOTE: Cannot determine if the opened case is a new case or a reopened case,
474  // so check for existing name in DB and insert if missing.
475  if (dbManager.getCase(curCase) == null) {
476  dbManager.newCase(curCase);
477  }
478  } catch (EamDbException ex) {
479  LOGGER.log(Level.SEVERE, "Error connecting to Central Repository database.", ex); //NON-NLS
480  }
481  }
482  } // CURRENT_CASE
483  }
484 }
CorrelationDataSource getDataSource(CorrelationCase correlationCase, String dataSourceDeviceId)
static CorrelationAttribute getCorrelationAttributeFromContent(Content content, TskData.FileKnown knownStatus, String comment)
CorrelationCase newCase(CorrelationCase eamCase)
static CorrelationDataSource fromTSKDataSource(CorrelationCase correlationCase, Content dataSource)
List< ContentTag > getContentTagsByContent(Content content)
static void shutDownTaskExecutor(ExecutorService executor)
void setArtifactInstanceKnownStatus(CorrelationAttribute eamArtifact, TskData.FileKnown knownStatus)
synchronized static Logger getLogger(String name)
Definition: Logger.java:124
void newDataSource(CorrelationDataSource eamDataSource)
static List< CorrelationAttribute > getCorrelationAttributeFromBlackboardArtifact(BlackboardArtifact bbArtifact, boolean addInstanceDetails, boolean checkEnabled)
List< BlackboardArtifactTag > getBlackboardArtifactTagsByArtifact(BlackboardArtifact artifact)

Copyright © 2012-2016 Basis Technology. Generated on: Tue Feb 20 2018
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.