Autopsy  4.19.1
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 2017-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.eventlisteners;
20 
21 import com.google.common.util.concurrent.ThreadFactoryBuilder;
22 import java.beans.PropertyChangeEvent;
23 import java.beans.PropertyChangeListener;
24 import java.util.ArrayList;
25 import java.util.Arrays;
26 import java.util.Collection;
27 import java.util.EnumSet;
28 import java.util.List;
29 import java.util.Optional;
30 import java.util.Set;
31 import java.util.concurrent.ExecutorService;
32 import java.util.concurrent.Executors;
33 import java.util.logging.Level;
34 import java.util.stream.Collectors;
35 import org.apache.commons.lang.StringUtils;
36 import org.openide.util.NbBundle;
37 import org.openide.util.NbBundle.Messages;
55 import org.sleuthkit.datamodel.AbstractFile;
56 import org.sleuthkit.datamodel.BlackboardArtifact;
57 import org.sleuthkit.datamodel.BlackboardArtifactTag;
58 import org.sleuthkit.datamodel.Content;
59 import org.sleuthkit.datamodel.ContentTag;
60 import org.sleuthkit.datamodel.TagName;
61 import org.sleuthkit.datamodel.TskCoreException;
62 import org.sleuthkit.datamodel.TskData;
65 import org.sleuthkit.datamodel.Tag;
68 import org.sleuthkit.datamodel.AnalysisResult;
69 import org.sleuthkit.datamodel.Blackboard;
70 import org.sleuthkit.datamodel.BlackboardAttribute;
71 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_OTHER_CASES;
72 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME;
73 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CORRELATION_TYPE;
74 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CORRELATION_VALUE;
75 import org.sleuthkit.datamodel.DataArtifact;
76 import org.sleuthkit.datamodel.OsAccount;
77 import org.sleuthkit.datamodel.OsAccountInstance;
78 import org.sleuthkit.datamodel.Score;
79 import org.sleuthkit.datamodel.SleuthkitCase;
80 
85 @Messages({"caseeventlistener.evidencetag=Evidence"})
86 public final class CaseEventListener implements PropertyChangeListener {
87 
88  private static final Logger LOGGER = Logger.getLogger(CaseEventListener.class.getName());
89  private final ExecutorService jobProcessingExecutor;
90  private static final String CASE_EVENT_THREAD_NAME = "Case-Event-Listener-%d";
91 
92  private static final Set<Case.Events> CASE_EVENTS_OF_INTEREST = EnumSet.of(
101 
102  public CaseEventListener() {
103  jobProcessingExecutor = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder().setNameFormat(CASE_EVENT_THREAD_NAME).build());
104  }
105 
106  public void shutdown() {
107  ThreadUtils.shutDownTaskExecutor(jobProcessingExecutor);
108  }
109 
110  @Override
111  public void propertyChange(PropertyChangeEvent evt) {
112  if (!(evt instanceof AutopsyEvent) || (((AutopsyEvent) evt).getSourceType() != AutopsyEvent.SourceType.LOCAL)) {
113  return;
114  }
115 
116  CentralRepository dbManager;
117  try {
118  dbManager = CentralRepository.getInstance();
119  } catch (CentralRepoException ex) {
120  LOGGER.log(Level.SEVERE, "Failed to get instance of db manager.", ex);
121  return;
122  }
123 
124  // If any changes are made to which event types are handled the change
125  // must also be made to CASE_EVENTS_OF_INTEREST.
126  switch (Case.Events.valueOf(evt.getPropertyName())) {
127  case CONTENT_TAG_ADDED:
128  case CONTENT_TAG_DELETED: {
129  jobProcessingExecutor.submit(new ContentTagTask(dbManager, evt));
130  }
131  break;
132 
133  case BLACKBOARD_ARTIFACT_TAG_DELETED:
134  case BLACKBOARD_ARTIFACT_TAG_ADDED: {
135  jobProcessingExecutor.submit(new BlackboardTagTask(dbManager, evt));
136  }
137  break;
138 
139  case DATA_SOURCE_ADDED: {
140  jobProcessingExecutor.submit(new DataSourceAddedTask(dbManager, evt));
141  }
142  break;
143  case TAG_DEFINITION_CHANGED: {
144  jobProcessingExecutor.submit(new TagDefinitionChangeTask(evt));
145  }
146  break;
147  case CURRENT_CASE: {
148  jobProcessingExecutor.submit(new CurrentCaseTask(dbManager, evt));
149  }
150  break;
151  case DATA_SOURCE_NAME_CHANGED: {
152  jobProcessingExecutor.submit(new DataSourceNameChangedTask(dbManager, evt));
153  }
154  break;
155  case OS_ACCT_INSTANCES_ADDED: {
156  if (((AutopsyEvent) evt).getSourceType() == AutopsyEvent.SourceType.LOCAL) {
157  jobProcessingExecutor.submit(new OsAccountInstancesAddedTask(dbManager, evt));
158  }
159  }
160  break;
161  }
162  }
163 
164  /*
165  * Add all of our Case Event Listeners to the case.
166  */
167  public void installListeners() {
168  Case.addEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, this);
169  }
170 
171  /*
172  * Remove all of our Case Event Listeners from the case.
173  */
174  public void uninstallListeners() {
175  Case.removeEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, this);
176  }
177 
185  private static boolean isNotableTag(Tag t) {
186  return (t != null && isNotableTagName(t.getName()));
187  }
188 
196  private static boolean isNotableTagName(TagName t) {
197  return (t != null && TagsManager.getNotableTagDisplayNames().contains(t.getDisplayName()));
198  }
199 
207  private static boolean hasNotableTag(List<? extends Tag> tags) {
208  if (tags == null) {
209  return false;
210  }
211 
212  return tags.stream()
214  .findFirst()
215  .isPresent();
216  }
217 
225  private static void setArtifactKnownStatus(CentralRepository dbManager, BlackboardArtifact bbArtifact, TskData.FileKnown knownStatus) {
226  List<CorrelationAttributeInstance> convertedArtifacts = new ArrayList<>();
227  if (bbArtifact instanceof DataArtifact) {
228  convertedArtifacts.addAll(CorrelationAttributeUtil.makeCorrAttrsForSearch((DataArtifact) bbArtifact));
229  } else if (bbArtifact instanceof AnalysisResult) {
230  convertedArtifacts.addAll(CorrelationAttributeUtil.makeCorrAttrsForSearch((AnalysisResult) bbArtifact));
231  }
232  for (CorrelationAttributeInstance eamArtifact : convertedArtifacts) {
233  try {
234  dbManager.setAttributeInstanceKnownStatus(eamArtifact, knownStatus);
235  } catch (CentralRepoException ex) {
236  LOGGER.log(Level.SEVERE, "Error connecting to Central Repository database while setting artifact known status.", ex); //NON-NLS
237  }
238  }
239  }
240 
241  private final class ContentTagTask implements Runnable {
242 
244  private final PropertyChangeEvent event;
245 
246  private ContentTagTask(CentralRepository db, PropertyChangeEvent evt) {
247  dbManager = db;
248  event = evt;
249  }
250 
251  @Override
252  public void run() {
253  if (!CentralRepository.isEnabled()) {
254  return;
255  }
256 
257  Case.Events curEventType = Case.Events.valueOf(event.getPropertyName());
258  if (curEventType == Case.Events.CONTENT_TAG_ADDED && event instanceof ContentTagAddedEvent) {
259  handleTagAdded((ContentTagAddedEvent) event);
260  } else if (curEventType == Case.Events.CONTENT_TAG_DELETED && event instanceof ContentTagDeletedEvent) {
261  handleTagDeleted((ContentTagDeletedEvent) event);
262  } else {
263  LOGGER.log(Level.SEVERE,
264  String.format("Received an event %s of type %s and was expecting either CONTENT_TAG_ADDED or CONTENT_TAG_DELETED.",
265  event, curEventType));
266  }
267  }
268 
270  // ensure tag deleted event has a valid content id
271  if (evt.getDeletedTagInfo() == null) {
272  LOGGER.log(Level.SEVERE, "ContentTagDeletedEvent did not have valid content to provide a content id.");
273  return;
274  }
275 
276  try {
277  // obtain content
278  Content content = Case.getCurrentCaseThrows().getSleuthkitCase().getContentById(evt.getDeletedTagInfo().getContentID());
279  if (content == null) {
280  LOGGER.log(Level.WARNING,
281  String.format("Unable to get content for item with content id: %d.", evt.getDeletedTagInfo().getContentID()));
282  return;
283  }
284 
285  // then handle the event
286  handleTagChange(content);
287  } catch (NoCurrentCaseException | TskCoreException ex) {
288  LOGGER.log(Level.WARNING, "Error updating non-file object: " + evt.getDeletedTagInfo().getContentID(), ex);
289  }
290  }
291 
293  // ensure tag added event has a valid content id
294  if (evt.getAddedTag() == null || evt.getAddedTag().getContent() == null) {
295  LOGGER.log(Level.SEVERE, "ContentTagAddedEvent did not have valid content to provide a content id.");
296  return;
297  }
298 
299  // then handle the event
300  handleTagChange(evt.getAddedTag().getContent());
301  }
302 
310  private void handleTagChange(Content content) {
311  AbstractFile af = null;
312  try {
313  af = Case.getCurrentCaseThrows().getSleuthkitCase().getAbstractFileById(content.getId());
314  } catch (NoCurrentCaseException | TskCoreException ex) {
315  Long contentID = (content != null) ? content.getId() : null;
316  LOGGER.log(Level.WARNING, "Error updating non-file object: " + contentID, ex);
317  }
318 
319  if (af == null) {
320  return;
321  }
322 
323  try {
324  // Get the tags on the content object
326 
327  if (hasNotableTag(tagsManager.getContentTagsByContent(content))) {
328  // if there is a notable tag on the object, set content known status to bad
329  setContentKnownStatus(af, TskData.FileKnown.BAD);
330  } else {
331  // otherwise, set to unknown
332  setContentKnownStatus(af, TskData.FileKnown.UNKNOWN);
333  }
334  } catch (TskCoreException | NoCurrentCaseException ex) {
335  LOGGER.log(Level.SEVERE, "Failed to obtain tags manager for case.", ex);
336  }
337  }
338 
348  private void setContentKnownStatus(AbstractFile af, TskData.FileKnown knownStatus) {
349  final List<CorrelationAttributeInstance> md5CorrelationAttr = CorrelationAttributeUtil.makeCorrAttrsForSearch(af);
350  if (!md5CorrelationAttr.isEmpty()) {
351  //for an abstract file the 'list' of attributes will be a single attribute or empty and is returning a list for consistency with other makeCorrAttrsForSearch methods per 7852
352  // send update to Central Repository db
353  try {
354  dbManager.setAttributeInstanceKnownStatus(md5CorrelationAttr.get(0), knownStatus);
355  } catch (CentralRepoException ex) {
356  LOGGER.log(Level.SEVERE, "Error connecting to Central Repository database while setting artifact known status.", ex); //NON-NLS
357  }
358  }
359  }
360  }
361 
362  private final class BlackboardTagTask implements Runnable {
363 
365  private final PropertyChangeEvent event;
366 
367  private BlackboardTagTask(CentralRepository db, PropertyChangeEvent evt) {
368  dbManager = db;
369  event = evt;
370  }
371 
372  @Override
373  public void run() {
374  if (!CentralRepository.isEnabled()) {
375  return;
376  }
377 
378  Case.Events curEventType = Case.Events.valueOf(event.getPropertyName());
379  if (curEventType == Case.Events.BLACKBOARD_ARTIFACT_TAG_ADDED && event instanceof BlackBoardArtifactTagAddedEvent) {
380  handleTagAdded((BlackBoardArtifactTagAddedEvent) event);
381  } else if (curEventType == Case.Events.BLACKBOARD_ARTIFACT_TAG_DELETED && event instanceof BlackBoardArtifactTagDeletedEvent) {
382  handleTagDeleted((BlackBoardArtifactTagDeletedEvent) event);
383  } else {
384  LOGGER.log(Level.WARNING,
385  String.format("Received an event %s of type %s and was expecting either CONTENT_TAG_ADDED or CONTENT_TAG_DELETED.",
386  event, curEventType));
387  }
388  }
389 
391  // ensure tag deleted event has a valid content id
392  if (evt.getDeletedTagInfo() == null) {
393  LOGGER.log(Level.SEVERE, "BlackBoardArtifactTagDeletedEvent did not have valid content to provide a content id.");
394  return;
395  }
396 
397  try {
398  Case openCase = Case.getCurrentCaseThrows();
399 
400  // obtain content
401  Content content = openCase.getSleuthkitCase().getContentById(evt.getDeletedTagInfo().getContentID());
402  if (content == null) {
403  LOGGER.log(Level.WARNING,
404  String.format("Unable to get content for item with content id: %d.", evt.getDeletedTagInfo().getContentID()));
405  return;
406  }
407 
408  // obtain blackboard artifact
409  BlackboardArtifact bbArtifact = openCase.getSleuthkitCase().getBlackboardArtifact(evt.getDeletedTagInfo().getArtifactID());
410  if (bbArtifact == null) {
411  LOGGER.log(Level.WARNING,
412  String.format("Unable to get blackboard artifact for item with artifact id: %d.", evt.getDeletedTagInfo().getArtifactID()));
413  return;
414  }
415 
416  // then handle the event
417  handleTagChange(content, bbArtifact);
418  } catch (NoCurrentCaseException | TskCoreException ex) {
419  LOGGER.log(Level.WARNING, "Error updating non-file object.", ex);
420  }
421  }
422 
424  // ensure tag added event has a valid content id
425  if (evt.getAddedTag() == null || evt.getAddedTag().getContent() == null || evt.getAddedTag().getArtifact() == null) {
426  LOGGER.log(Level.SEVERE, "BlackBoardArtifactTagAddedEvent did not have valid content to provide a content id.");
427  return;
428  }
429 
430  // then handle the event
431  handleTagChange(evt.getAddedTag().getContent(), evt.getAddedTag().getArtifact());
432  }
433 
442  private void handleTagChange(Content content, BlackboardArtifact bbArtifact) {
443  Case openCase;
444  try {
445  openCase = Case.getCurrentCaseThrows();
446  } catch (NoCurrentCaseException ex) {
447  LOGGER.log(Level.SEVERE, "Exception while getting open case.", ex);
448  return;
449  }
450 
451  try {
452  if (isKnownFile(content)) {
453  return;
454  }
455 
456  TagsManager tagsManager = openCase.getServices().getTagsManager();
457  List<BlackboardArtifactTag> tags = tagsManager.getBlackboardArtifactTagsByArtifact(bbArtifact);
458  if (hasNotableTag(tags)) {
459  setArtifactKnownStatus(dbManager, bbArtifact, TskData.FileKnown.BAD);
460  } else {
461  setArtifactKnownStatus(dbManager, bbArtifact, TskData.FileKnown.UNKNOWN);
462  }
463  } catch (TskCoreException ex) {
464  LOGGER.log(Level.SEVERE, "Failed to obtain tags manager for case.", ex);
465  }
466  }
467 
475  private boolean isKnownFile(Content content) {
476  return ((content instanceof AbstractFile) && (((AbstractFile) content).getKnown() == TskData.FileKnown.KNOWN));
477  }
478 
479  }
480 
481  private final class TagDefinitionChangeTask implements Runnable {
482 
483  private final PropertyChangeEvent event;
484 
485  private TagDefinitionChangeTask(PropertyChangeEvent evt) {
486  event = evt;
487  }
488 
489  @Override
490  public void run() {
491  if (!CentralRepository.isEnabled()) {
492  return;
493  }
494  //get the display name of the tag that has had it's definition modified
495  String modifiedTagName = (String) event.getOldValue();
496 
497  /*
498  * Set knownBad status for all files/artifacts in the given case
499  * that are tagged with the given tag name.
500  */
501  try {
502  TagName tagName = Case.getCurrentCaseThrows().getServices().getTagsManager().getDisplayNamesToTagNamesMap().get(modifiedTagName);
503  //First update the artifacts
504  //Get all BlackboardArtifactTags with this tag name
505  List<BlackboardArtifactTag> artifactTags = Case.getCurrentCaseThrows().getSleuthkitCase().getBlackboardArtifactTagsByTagName(tagName);
506  for (BlackboardArtifactTag bbTag : artifactTags) {
507  //start with assumption that none of the other tags applied to this Correlation Attribute will prevent it's status from being changed
508  boolean hasTagWithConflictingKnownStatus = false;
509  // if the status of the tag has been changed to TskData.FileKnown.UNKNOWN
510  // we need to check the status of all other tags on this correlation attribute before changing
511  // the status of the correlation attribute in the central repository
512  if (tagName.getKnownStatus() == TskData.FileKnown.UNKNOWN) {
513  Content content = bbTag.getContent();
514  // If the content which this Blackboard Artifact Tag is linked to is an AbstractFile with KNOWN status then
515  // it's status in the central reporsitory should not be changed to UNKNOWN
516  if ((content instanceof AbstractFile) && (((AbstractFile) content).getKnown() == TskData.FileKnown.KNOWN)) {
517  continue;
518  }
519  //Get the BlackboardArtifact which this BlackboardArtifactTag has been applied to.
520  BlackboardArtifact bbArtifact = bbTag.getArtifact();
522  List<BlackboardArtifactTag> tags = tagsManager.getBlackboardArtifactTagsByArtifact(bbArtifact);
523  //get all tags which are on this blackboard artifact
524  for (BlackboardArtifactTag t : tags) {
525  //All instances of the modified tag name will be changed, they can not conflict with each other
526  if (t.getName().equals(tagName)) {
527  continue;
528  }
529  //if any other tags on this artifact are Notable in status then this artifact can not have its status changed
530  if (TskData.FileKnown.BAD == t.getName().getKnownStatus()) {
531  //a tag with a conflicting status has been found, the status of this correlation attribute can not be modified
532  hasTagWithConflictingKnownStatus = true;
533  break;
534  }
535  }
536  }
537  //if the Correlation Attribute will have no tags with a status which would prevent the current status from being changed
538  if (!hasTagWithConflictingKnownStatus) {
539  setArtifactKnownStatus(CentralRepository.getInstance(), bbTag.getArtifact(), tagName.getKnownStatus());
540  }
541  }
542  // Next update the files
543 
544  List<ContentTag> fileTags = Case.getCurrentCaseThrows().getSleuthkitCase().getContentTagsByTagName(tagName);
545  //Get all ContentTags with this tag name
546  for (ContentTag contentTag : fileTags) {
547  //start with assumption that none of the other tags applied to this ContentTag will prevent it's status from being changed
548  boolean hasTagWithConflictingKnownStatus = false;
549  // if the status of the tag has been changed to TskData.FileKnown.UNKNOWN
550  // we need to check the status of all other tags on this file before changing
551  // the status of the file in the central repository
552  if (tagName.getKnownStatus() == TskData.FileKnown.UNKNOWN) {
553  Content content = contentTag.getContent();
555  List<ContentTag> tags = tagsManager.getContentTagsByContent(content);
556  //get all tags which are on this file
557  for (ContentTag t : tags) {
558  //All instances of the modified tag name will be changed, they can not conflict with each other
559  if (t.getName().equals(tagName)) {
560  continue;
561  }
562  //if any other tags on this file are Notable in status then this file can not have its status changed
563  if (TskData.FileKnown.BAD == t.getName().getKnownStatus()) {
564  //a tag with a conflicting status has been found, the status of this file can not be modified
565  hasTagWithConflictingKnownStatus = true;
566  break;
567  }
568  }
569  }
570  //if the file will have no tags with a status which would prevent the current status from being changed
571  if (!hasTagWithConflictingKnownStatus) {
572  Content taggedContent = contentTag.getContent();
573  if (taggedContent instanceof AbstractFile) {
574  final List<CorrelationAttributeInstance> eamArtifact = CorrelationAttributeUtil.makeCorrAttrsForSearch((AbstractFile) taggedContent);
575  if (!eamArtifact.isEmpty()) {
576  //for an abstract file the 'list' of attributes will be a single attribute or empty and is returning a list for consistency with other makeCorrAttrsForSearch methods per 7852
577  CentralRepository.getInstance().setAttributeInstanceKnownStatus(eamArtifact.get(0), tagName.getKnownStatus());
578  }
579  }
580  }
581  }
582  } catch (TskCoreException ex) {
583  LOGGER.log(Level.SEVERE, "Cannot update known status in central repository for tag: " + modifiedTagName, ex); //NON-NLS
584  } catch (CentralRepoException ex) {
585  LOGGER.log(Level.SEVERE, "Cannot get central repository for tag: " + modifiedTagName, ex); //NON-NLS
586  } catch (NoCurrentCaseException ex) {
587  LOGGER.log(Level.SEVERE, "Exception while getting open case.", ex); //NON-NLS
588  }
589  } //TAG_STATUS_CHANGED
590  }
591 
592  private final class DataSourceAddedTask implements Runnable {
593 
595  private final PropertyChangeEvent event;
596 
597  private DataSourceAddedTask(CentralRepository db, PropertyChangeEvent evt) {
598  dbManager = db;
599  event = evt;
600  }
601 
602  @Override
603  public void run() {
604  if (!CentralRepository.isEnabled()) {
605  return;
606  }
607  Case openCase;
608  try {
609  openCase = Case.getCurrentCaseThrows();
610  } catch (NoCurrentCaseException ex) {
611  LOGGER.log(Level.SEVERE, "Exception while getting open case.", ex);
612  return;
613  }
614 
615  final DataSourceAddedEvent dataSourceAddedEvent = (DataSourceAddedEvent) event;
616  Content newDataSource = dataSourceAddedEvent.getDataSource();
617 
618  try {
619  CorrelationCase correlationCase = dbManager.getCase(openCase);
620  if (null == dbManager.getDataSource(correlationCase, newDataSource.getId())) {
621  CorrelationDataSource.fromTSKDataSource(correlationCase, newDataSource);
622  }
623  } catch (CentralRepoException ex) {
624  LOGGER.log(Level.SEVERE, "Error adding new data source to the central repository", ex); //NON-NLS
625  }
626  } // DATA_SOURCE_ADDED
627  }
628 
629  private final class CurrentCaseTask implements Runnable {
630 
632  private final PropertyChangeEvent event;
633 
634  private CurrentCaseTask(CentralRepository db, PropertyChangeEvent evt) {
635  dbManager = db;
636  event = evt;
637  }
638 
639  @Override
640  public void run() {
641  /*
642  * A case has been opened if evt.getOldValue() is null and
643  * evt.getNewValue() is a valid Case.
644  */
645  if ((null == event.getOldValue()) && (event.getNewValue() instanceof Case)) {
646  Case curCase = (Case) event.getNewValue();
647  IngestEventsListener.resetCeModuleInstanceCount();
648 
649  if (!CentralRepository.isEnabled()) {
650  return;
651  }
652 
653  try {
654  // NOTE: Cannot determine if the opened case is a new case or a reopened case,
655  // so check for existing name in DB and insert if missing.
656  if (dbManager.getCase(curCase) == null) {
657  dbManager.newCase(curCase);
658  }
659  } catch (CentralRepoException ex) {
660  LOGGER.log(Level.SEVERE, "Error connecting to Central Repository database.", ex); //NON-NLS
661  }
662  }
663  } // CURRENT_CASE
664  }
665 
666  @NbBundle.Messages({"CaseEventsListener.module.name=Central Repository",
667  "CaseEventsListener.prevCaseComment.text=Users seen in previous cases",
668  "CaseEventsListener.prevExists.text=Previously Seen Users (Central Repository)"})
673  private final class OsAccountInstancesAddedTask implements Runnable {
674 
676  private final PropertyChangeEvent event;
677  private final String MODULE_NAME = Bundle.CaseEventsListener_module_name();
678 
679  private OsAccountInstancesAddedTask(CentralRepository db, PropertyChangeEvent evt) {
680  dbManager = db;
681  event = evt;
682  }
683 
684  @Override
685  public void run() {
686  //Nothing to do here if the central repo is not enabled or if ingest is running but is set to not save data/make artifacts
689  return;
690  }
691 
692  final OsAcctInstancesAddedEvent osAcctInstancesAddedEvent = (OsAcctInstancesAddedEvent) event;
693  List<OsAccountInstance> addedOsAccountNew = osAcctInstancesAddedEvent.getOsAccountInstances();
694  for (OsAccountInstance osAccountInstance : addedOsAccountNew) {
695  try {
696  OsAccount osAccount = osAccountInstance.getOsAccount();
697  List<CorrelationAttributeInstance> correlationAttributeInstances = CorrelationAttributeUtil.makeCorrAttrsForSearch(osAccountInstance);
698  if (correlationAttributeInstances.isEmpty()) {
699  return;
700  }
701 
702  Optional<String> accountAddr = osAccount.getAddr();
703  try {
704  // Save to the database if requested
706  for (CorrelationAttributeInstance correlationAttributeInstance : correlationAttributeInstances) {
707  dbManager.addArtifactInstance(correlationAttributeInstance);
708  }
709  }
710 
711  // Look up and create artifacts for previously seen accounts if requested
714  List<CorrelationAttributeInstance> previousOccurences = dbManager.getArtifactInstancesByTypeValue(osAcctType, correlationAttributeInstances.get(0).getCorrelationValue());
715  for (CorrelationAttributeInstance instance : previousOccurences) {
716  if (!instance.getCorrelationCase().getCaseUUID().equals(correlationAttributeInstances.get(0).getCorrelationCase().getCaseUUID())) {
717  SleuthkitCase tskCase = osAccount.getSleuthkitCase();
718  Blackboard blackboard = tskCase.getBlackboard();
719 
720  List<String> caseDisplayNames = dbManager.getListCasesHavingArtifactInstances(osAcctType, correlationAttributeInstances.get(0).getCorrelationValue());
721 
722  // calculate score
723  Score score;
724  int numCases = caseDisplayNames.size();
725  if (numCases <= IngestEventsListener.MAX_NUM_PREVIOUS_CASES_FOR_LIKELY_NOTABLE_SCORE) {
726  score = Score.SCORE_LIKELY_NOTABLE;
727  } else if (numCases > IngestEventsListener.MAX_NUM_PREVIOUS_CASES_FOR_LIKELY_NOTABLE_SCORE && numCases <= IngestEventsListener.MAX_NUM_PREVIOUS_CASES_FOR_PREV_SEEN_ARTIFACT_CREATION) {
728  score = Score.SCORE_NONE;
729  } else {
730  // don't make an Analysis Result, the artifact is too common.
731  continue;
732  }
733 
734  String prevCases = caseDisplayNames.stream().distinct().collect(Collectors.joining(","));
735  String justification = "Previously seen in cases " + prevCases;
736  Collection<BlackboardAttribute> attributesForNewArtifact = Arrays.asList(
737  new BlackboardAttribute(
738  TSK_SET_NAME, MODULE_NAME,
739  Bundle.CaseEventsListener_prevExists_text()),
740  new BlackboardAttribute(
741  TSK_CORRELATION_TYPE, MODULE_NAME,
742  osAcctType.getDisplayName()),
743  new BlackboardAttribute(
744  TSK_CORRELATION_VALUE, MODULE_NAME,
745  correlationAttributeInstances.get(0).getCorrelationValue()),
746  new BlackboardAttribute(
747  TSK_OTHER_CASES, MODULE_NAME,
748  prevCases));
749  BlackboardArtifact newAnalysisResult = osAccount.newAnalysisResult(
750  BlackboardArtifact.Type.TSK_PREVIOUSLY_SEEN, score,
751  null, Bundle.CaseEventsListener_prevExists_text(), justification, attributesForNewArtifact, osAccountInstance.getDataSource().getId()).getAnalysisResult();
752  try {
753  // index the artifact for keyword search
754  blackboard.postArtifact(newAnalysisResult, MODULE_NAME);
755  break;
756  } catch (Blackboard.BlackboardException ex) {
757  LOGGER.log(Level.SEVERE, "Unable to index blackboard artifact " + newAnalysisResult.getArtifactID(), ex); //NON-NLS
758  }
759  }
760  }
761  }
762 
764  LOGGER.log(Level.SEVERE, "Exception with Correlation Attribute Normalization.", ex); //NON-NLS
765  } catch (CentralRepoException ex) {
766  LOGGER.log(Level.SEVERE, String.format("Cannot get central repository for OsAccount: %s.", accountAddr.get()), ex); //NON-NLS
767  }
768  } catch (TskCoreException ex) {
769  LOGGER.log(Level.SEVERE, "Cannot get central repository for OsAccount: " + "OsAccount", ex);
770  }
771  }
772  }
773  }
774 
775  private final class DataSourceNameChangedTask implements Runnable {
776 
778  private final PropertyChangeEvent event;
779 
780  private DataSourceNameChangedTask(CentralRepository db, PropertyChangeEvent evt) {
781  dbManager = db;
782  event = evt;
783  }
784 
785  @Override
786  public void run() {
787 
788  final DataSourceNameChangedEvent dataSourceNameChangedEvent = (DataSourceNameChangedEvent) event;
789  Content dataSource = dataSourceNameChangedEvent.getDataSource();
790  String newName = (String) event.getNewValue();
791 
792  if (!StringUtils.isEmpty(newName)) {
793 
794  if (!CentralRepository.isEnabled()) {
795  return;
796  }
797 
798  try {
799  CorrelationCase correlationCase = dbManager.getCase(Case.getCurrentCaseThrows());
800  CorrelationDataSource existingEamDataSource = dbManager.getDataSource(correlationCase, dataSource.getId());
801  dbManager.updateDataSourceName(existingEamDataSource, newName);
802  } catch (CentralRepoException ex) {
803  LOGGER.log(Level.SEVERE, "Error updating data source with ID " + dataSource.getId() + " to " + newName, ex); //NON-NLS
804  } catch (NoCurrentCaseException ex) {
805  LOGGER.log(Level.SEVERE, "No open case", ex);
806  }
807  }
808  } // DATA_SOURCE_NAME_CHANGED
809  }
810 }
static synchronized IngestManager getInstance()
List< String > getListCasesHavingArtifactInstances(CorrelationAttributeInstance.Type aType, String value)
List< CorrelationAttributeInstance > getArtifactInstancesByTypeValue(CorrelationAttributeInstance.Type aType, String value)
static CorrelationDataSource fromTSKDataSource(CorrelationCase correlationCase, Content dataSource)
List< ContentTag > getContentTagsByContent(Content content)
void setAttributeInstanceKnownStatus(CorrelationAttributeInstance eamArtifact, TskData.FileKnown knownStatus)
void addArtifactInstance(CorrelationAttributeInstance eamArtifact)
static void shutDownTaskExecutor(ExecutorService executor)
static List< CorrelationAttributeInstance > makeCorrAttrsForSearch(AnalysisResult analysisResult)
void updateDataSourceName(CorrelationDataSource eamDataSource, String newName)
CorrelationDataSource getDataSource(CorrelationCase correlationCase, Long caseDbDataSourceId)
synchronized static Logger getLogger(String name)
Definition: Logger.java:124
CorrelationAttributeInstance.Type getCorrelationTypeById(int typeId)
static void addEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
Definition: Case.java:711
static void setArtifactKnownStatus(CentralRepository dbManager, BlackboardArtifact bbArtifact, TskData.FileKnown knownStatus)
static void removeEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
Definition: Case.java:756
List< BlackboardArtifactTag > getBlackboardArtifactTagsByArtifact(BlackboardArtifact artifact)

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.