Autopsy  4.8.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
IngestEventsListener.java
Go to the documentation of this file.
1 /*
2  * Central Repository
3  *
4  * Copyright 2015-2018 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 static java.lang.Boolean.FALSE;
25 import java.util.ArrayList;
26 import java.util.Collection;
27 import java.util.LinkedHashSet;
28 import java.util.List;
29 import java.util.concurrent.ExecutorService;
30 import java.util.concurrent.Executors;
31 import java.util.logging.Level;
32 import java.util.stream.Collectors;
33 import org.openide.util.NbBundle;
45 import org.sleuthkit.datamodel.AbstractFile;
46 import org.sleuthkit.datamodel.BlackboardArtifact;
47 import org.sleuthkit.datamodel.BlackboardAttribute;
48 import org.sleuthkit.datamodel.TskCoreException;
51 
56 public class IngestEventsListener {
57 
58  private static final Logger LOGGER = Logger.getLogger(CorrelationAttributeInstance.class.getName());
59 
60  final Collection<String> recentlyAddedCeArtifacts = new LinkedHashSet<>();
61  private static int correlationModuleInstanceCount;
62  private static boolean flagNotableItems;
63  private final ExecutorService jobProcessingExecutor;
64  private static final String INGEST_EVENT_THREAD_NAME = "Ingest-Event-Listener-%d";
65  private final PropertyChangeListener pcl1 = new IngestModuleEventListener();
66  private final PropertyChangeListener pcl2 = new IngestJobEventListener();
67 
69  jobProcessingExecutor = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder().setNameFormat(INGEST_EVENT_THREAD_NAME).build());
70  }
71 
72  void shutdown() {
73  ThreadUtils.shutDownTaskExecutor(jobProcessingExecutor);
74  }
75 
76  /*
77  * Add all of our Ingest Event Listeners to the IngestManager Instance.
78  */
79  public void installListeners() {
82  }
83 
84  /*
85  * Remove all of our Ingest Event Listeners from the IngestManager Instance.
86  */
87  public void uninstallListeners() {
90  }
91 
96  public synchronized static void incrementCorrelationEngineModuleCount() {
97  correlationModuleInstanceCount++; //Should be called once in the Correlation Engine module's startup method.
98  }
99 
104  public synchronized static void decrementCorrelationEngineModuleCount() {
105  if (getCeModuleInstanceCount() > 0) { //prevent it ingestJobCounter from going negative
106  correlationModuleInstanceCount--; //Should be called once in the Correlation Engine module's shutdown method.
107  }
108  }
109 
114  synchronized static void resetCeModuleInstanceCount() {
115  correlationModuleInstanceCount = 0; //called when a case is opened in case for some reason counter was not reset
116  }
117 
124  public synchronized static int getCeModuleInstanceCount() {
126  }
127 
133  public synchronized static boolean isFlagNotableItems() {
134  return flagNotableItems;
135  }
136 
142  public synchronized static void setFlagNotableItems(boolean value) {
143  flagNotableItems = value;
144  }
145 
146  @NbBundle.Messages({"IngestEventsListener.prevTaggedSet.text=Previously Tagged As Notable (Central Repository)",
147  "IngestEventsListener.prevCaseComment.text=Previous Case: ",
148  "IngestEventsListener.ingestmodule.name=Correlation Engine"})
149  static private void postCorrelatedBadArtifactToBlackboard(BlackboardArtifact bbArtifact, List<String> caseDisplayNames) {
150 
151  try {
152  AbstractFile af = bbArtifact.getSleuthkitCase().getAbstractFileById(bbArtifact.getObjectID());
153  Collection<BlackboardAttribute> attributes = new ArrayList<>();
154  String MODULE_NAME = Bundle.IngestEventsListener_ingestmodule_name();
155  BlackboardArtifact tifArtifact = af.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT);
156  BlackboardAttribute att = new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME, MODULE_NAME,
157  Bundle.IngestEventsListener_prevTaggedSet_text());
158  BlackboardAttribute att2 = new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT, MODULE_NAME,
159  Bundle.IngestEventsListener_prevCaseComment_text() + caseDisplayNames.stream().distinct().collect(Collectors.joining(",", "", "")));
160  attributes.add(att);
161  attributes.add(att2);
162  attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT, MODULE_NAME, bbArtifact.getArtifactID()));
163 
164  tifArtifact.addAttributes(attributes);
165  try {
166  // index the artifact for keyword search
168  blackboard.indexArtifact(tifArtifact);
170  LOGGER.log(Level.SEVERE, "Unable to index blackboard artifact " + tifArtifact.getArtifactID(), ex); //NON-NLS
171  }
172 
173  // fire event to notify UI of this new artifact
174  IngestServices.getInstance().fireModuleDataEvent(new ModuleDataEvent(MODULE_NAME, BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT));
175  } catch (TskCoreException ex) {
176  LOGGER.log(Level.SEVERE, "Failed to create BlackboardArtifact.", ex); // NON-NLS
177  } catch (IllegalStateException ex) {
178  LOGGER.log(Level.SEVERE, "Failed to create BlackboardAttribute.", ex); // NON-NLS
179  }
180  }
181 
182  private class IngestModuleEventListener implements PropertyChangeListener {
183 
184  @Override
185  public void propertyChange(PropertyChangeEvent evt) {
186  if (getCeModuleInstanceCount() > 0) {
187  EamDb dbManager;
188  try {
189  dbManager = EamDb.getInstance();
190  } catch (EamDbException ex) {
191  LOGGER.log(Level.SEVERE, "Failed to connect to Central Repository database.", ex);
192  return;
193  }
194  switch (IngestManager.IngestModuleEvent.valueOf(evt.getPropertyName())) {
195  case DATA_ADDED: {
196  jobProcessingExecutor.submit(new DataAddedTask(dbManager, evt, isFlagNotableItems()));
197  break;
198  }
199  }
200  }
201  }
202  }
203 
204  private class IngestJobEventListener implements PropertyChangeListener {
205 
206  @Override
207  public void propertyChange(PropertyChangeEvent evt) {
208  switch (IngestManager.IngestJobEvent.valueOf(evt.getPropertyName())) {
209  case DATA_SOURCE_ANALYSIS_COMPLETED: {
210  jobProcessingExecutor.submit(new AnalysisCompleteTask());
211  break;
212  }
213  }
214  }
215 
216  }
217 
218  private final class AnalysisCompleteTask implements Runnable {
219 
220  @Override
221  public void run() {
222  // clear the tracker to reduce memory usage
223  if (getCeModuleInstanceCount() == 0) {
224  recentlyAddedCeArtifacts.clear();
225  }
226  //else another instance of the Correlation Engine Module is still being run.
227  } // DATA_SOURCE_ANALYSIS_COMPLETED
228  }
229 
230  private final class DataAddedTask implements Runnable {
231 
232  private final EamDb dbManager;
233  private final PropertyChangeEvent event;
234  private final boolean flagNotableItemsEnabled;
235 
236  private DataAddedTask(EamDb db, PropertyChangeEvent evt, boolean flagNotableItemsEnabled) {
237  dbManager = db;
238  event = evt;
239  this.flagNotableItemsEnabled = flagNotableItemsEnabled;
240  }
241 
242  @Override
243  public void run() {
244  if (!EamDb.isEnabled()) {
245  return;
246  }
247  final ModuleDataEvent mde = (ModuleDataEvent) event.getOldValue();
248  Collection<BlackboardArtifact> bbArtifacts = mde.getArtifacts();
249  if (null == bbArtifacts) { //the ModuleDataEvents don't always have a collection of artifacts set
250  return;
251  }
252  List<CorrelationAttributeInstance> eamArtifacts = new ArrayList<>();
253 
254  for (BlackboardArtifact bbArtifact : bbArtifacts) {
255  // eamArtifact will be null OR a EamArtifact containing one EamArtifactInstance.
256  List<CorrelationAttributeInstance> convertedArtifacts = EamArtifactUtil.makeInstancesFromBlackboardArtifact(bbArtifact, true);
257  for (CorrelationAttributeInstance eamArtifact : convertedArtifacts) {
258  try {
259  // Only do something with this artifact if it's unique within the job
260  if (recentlyAddedCeArtifacts.add(eamArtifact.toString())) {
261  // Was it previously marked as bad?
262  // query db for artifact instances having this TYPE/VALUE and knownStatus = "Bad".
263  // if getKnownStatus() is "Unknown" and this artifact instance was marked bad in a previous case,
264  // create TSK_INTERESTING_ARTIFACT_HIT artifact on BB.
265  if (flagNotableItemsEnabled) {
266  List<String> caseDisplayNames;
267  try {
268  caseDisplayNames = dbManager.getListCasesHavingArtifactInstancesKnownBad(eamArtifact.getCorrelationType(), eamArtifact.getCorrelationValue());
269  if (!caseDisplayNames.isEmpty()) {
271  caseDisplayNames);
272  }
274  LOGGER.log(Level.INFO, String.format("Unable to flag notable item: %s.", eamArtifact.toString()), ex);
275  }
276  }
277  eamArtifacts.add(eamArtifact);
278  }
279  } catch (EamDbException ex) {
280  LOGGER.log(Level.SEVERE, "Error counting notable artifacts.", ex);
281  }
282  }
283  }
284  if (FALSE == eamArtifacts.isEmpty()) {
285  for (CorrelationAttributeInstance eamArtifact : eamArtifacts) {
286  try {
287  dbManager.addArtifactInstance(eamArtifact);
288  } catch (EamDbException ex) {
289  LOGGER.log(Level.SEVERE, "Error adding artifact to database.", ex); //NON-NLS
290  }
291  }
292  } // DATA_ADDED
293  }
294  }
295 }
Collection< BlackboardArtifact > getArtifacts()
void removeIngestModuleEventListener(final PropertyChangeListener listener)
static synchronized IngestManager getInstance()
List< String > getListCasesHavingArtifactInstancesKnownBad(CorrelationAttributeInstance.Type aType, String value)
void removeIngestJobEventListener(final PropertyChangeListener listener)
static List< CorrelationAttributeInstance > makeInstancesFromBlackboardArtifact(BlackboardArtifact bbArtifact, boolean checkEnabled)
static void shutDownTaskExecutor(ExecutorService executor)
void addIngestJobEventListener(final PropertyChangeListener listener)
DataAddedTask(EamDb db, PropertyChangeEvent evt, boolean flagNotableItemsEnabled)
void fireModuleDataEvent(ModuleDataEvent moduleDataEvent)
void addIngestModuleEventListener(final PropertyChangeListener listener)
synchronized void indexArtifact(BlackboardArtifact artifact)
Definition: Blackboard.java:58
synchronized static Logger getLogger(String name)
Definition: Logger.java:124
static void postCorrelatedBadArtifactToBlackboard(BlackboardArtifact bbArtifact, List< String > caseDisplayNames)
void addArtifactInstance(CorrelationAttributeInstance eamArtifact)
static synchronized IngestServices getInstance()

Copyright © 2012-2018 Basis Technology. Generated on: Thu Oct 4 2018
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.