Autopsy  4.16.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
ImageDSProcessor.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2013-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.casemodule;
20 
21 import java.io.File;
22 import java.nio.file.Path;
23 import javax.swing.JPanel;
24 import java.util.ArrayList;
25 import java.util.Calendar;
26 import java.util.List;
27 import java.util.logging.Level;
28 import java.util.UUID;
29 import javax.swing.filechooser.FileFilter;
30 import org.openide.util.NbBundle;
31 import org.openide.util.lookup.ServiceProvider;
32 import org.openide.util.lookup.ServiceProviders;
42 import org.sleuthkit.datamodel.Image;
43 import org.sleuthkit.datamodel.SleuthkitJNI;
44 import org.sleuthkit.datamodel.TskCoreException;
45 
52 @ServiceProviders(value = {
53  @ServiceProvider(service = DataSourceProcessor.class)
54  ,
55  @ServiceProvider(service = AutoIngestDataSourceProcessor.class)}
56 )
58 
59  private final static String DATA_SOURCE_TYPE = NbBundle.getMessage(ImageDSProcessor.class, "ImageDSProcessor.dsType.text");
60  private final Logger logger = Logger.getLogger(ImageDSProcessor.class.getName());
61  private static final List<String> allExt = new ArrayList<>();
65  private static final String ALL_DESC = NbBundle.getMessage(ImageDSProcessor.class, "ImageDSProcessor.allDesc.text");
66  private static final GeneralFilter allFilter = new GeneralFilter(allExt, ALL_DESC);
67  private static final List<FileFilter> filtersList = new ArrayList<>();
68  private final ImageFilePanel configPanel;
69  private AddImageTask addImageTask;
70  private IngestStream ingestStream = null;
71  private Image image = null;
72  /*
73  * TODO: Remove the setDataSourceOptionsCalled flag and the settings fields
74  * when the deprecated method setDataSourceOptions is removed.
75  */
76  private String deviceId;
77  private String imagePath;
78  private int sectorSize;
79  private String timeZone;
80  private boolean ignoreFatOrphanFiles;
81  private String md5;
82  private String sha1;
83  private String sha256;
84  private boolean setDataSourceOptionsCalled;
85 
86  static {
87  filtersList.add(allFilter);
88  filtersList.add(rawFilter);
89  filtersList.add(encaseFilter);
90  allExt.addAll(GeneralFilter.RAW_IMAGE_EXTS);
91  allExt.addAll(GeneralFilter.ENCASE_IMAGE_EXTS);
92  if (!System.getProperty("os.name").toLowerCase().contains("mac")) {
93  filtersList.add(virtualMachineFilter);
94  allExt.addAll(GeneralFilter.VIRTUAL_MACHINE_EXTS);
95  }
96  }
97 
104  public ImageDSProcessor() {
105  configPanel = ImageFilePanel.createInstance(ImageDSProcessor.class.getName(), filtersList);
106  }
107 
113  static List<FileFilter> getFileFiltersList() {
114  return filtersList;
115  }
116 
124  public static String getType() {
125  return DATA_SOURCE_TYPE;
126  }
127 
135  @Override
136  public String getDataSourceType() {
137  return getType();
138  }
139 
148  @Override
149  public JPanel getPanel() {
150  configPanel.reset();
151  configPanel.readSettings();
152  configPanel.select();
153  return configPanel;
154  }
155 
163  @Override
164  public boolean isPanelValid() {
165  return configPanel.validatePanel();
166  }
167 
182  @Override
183  public void run(DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
184  ingestStream = new DefaultIngestStream();
185  readConfigSettings();
186  try {
187  image = SleuthkitJNI.addImageToDatabase(Case.getCurrentCase().getSleuthkitCase(),
188  new String[]{imagePath}, sectorSize, timeZone, md5, sha1, sha256, deviceId);
189  } catch (TskCoreException ex) {
190  logger.log(Level.SEVERE, "Error adding data source with path " + imagePath + " to database", ex);
191  final List<String> errors = new ArrayList<>();
192  errors.add(ex.getMessage());
193  callback.done(DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS, errors, new ArrayList<>());
194  return;
195  }
196 
197  doAddImageProcess(deviceId, imagePath, sectorSize, timeZone, ignoreFatOrphanFiles, md5, sha1, sha256, progressMonitor, callback);
198  }
199 
217  @Override
219  DataSourceProcessorCallback callBack) {
220 
221  // Read the settings from the wizard
222  readConfigSettings();
223 
224  // Set up the data source before creating the ingest stream
225  try {
226  image = SleuthkitJNI.addImageToDatabase(Case.getCurrentCase().getSleuthkitCase(),
227  new String[]{imagePath}, sectorSize, timeZone, md5, sha1, sha256, deviceId);
228  } catch (TskCoreException ex) {
229  logger.log(Level.SEVERE, "Error adding data source with path " + imagePath + " to database", ex);
230  final List<String> errors = new ArrayList<>();
231  errors.add(ex.getMessage());
232  callBack.done(DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS, errors, new ArrayList<>());
233  return;
234  }
235 
236  // Now initialize the ingest stream
237  try {
238  ingestStream = IngestManager.getInstance().openIngestStream(image, settings);
239  } catch (TskCoreException ex) {
240  logger.log(Level.SEVERE, "Error starting ingest modules", ex);
241  final List<String> errors = new ArrayList<>();
242  errors.add(ex.getMessage());
243  callBack.done(DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS, errors, new ArrayList<>());
244  return;
245  }
246 
247 
248  doAddImageProcess(deviceId, imagePath, sectorSize, timeZone, ignoreFatOrphanFiles, md5, sha1, sha256, progress, callBack);
249  }
250 
254  private void readConfigSettings() {
255  if (!setDataSourceOptionsCalled) {
256  configPanel.storeSettings();
257  deviceId = UUID.randomUUID().toString();
258  imagePath = configPanel.getContentPaths();
259  sectorSize = configPanel.getSectorSize();
260  timeZone = configPanel.getTimeZone();
261  ignoreFatOrphanFiles = configPanel.getNoFatOrphans();
262  md5 = configPanel.getMd5();
263  if (md5.isEmpty()) {
264  md5 = null;
265  }
266  sha1 = configPanel.getSha1();
267  if (sha1.isEmpty()) {
268  sha1 = null;
269  }
270  sha256 = configPanel.getSha256();
271  if (sha256.isEmpty()) {
272  sha256 = null;
273  }
274  }
275  }
276 
282  @Override
283  public boolean supportsIngestStream() {
284  return true;
285  }
286 
308  public void run(String deviceId, String imagePath, String timeZone, boolean ignoreFatOrphanFiles, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
309  ingestStream = new DefaultIngestStream();
310  try {
311  image = SleuthkitJNI.addImageToDatabase(Case.getCurrentCase().getSleuthkitCase(),
312  new String[]{imagePath}, sectorSize, timeZone, "", "", "", deviceId);
313  } catch (TskCoreException ex) {
314  logger.log(Level.SEVERE, "Error adding data source with path " + imagePath + " to database", ex);
315  final List<String> errors = new ArrayList<>();
316  errors.add(ex.getMessage());
317  callback.done(DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS, errors, new ArrayList<>());
318  return;
319  }
320 
321  doAddImageProcess(deviceId, imagePath, 0, timeZone, ignoreFatOrphanFiles, null, null, null, progressMonitor, callback);
322  }
323 
353  private void doAddImageProcess(String deviceId, String imagePath, int sectorSize, String timeZone, boolean ignoreFatOrphanFiles, String md5, String sha1, String sha256, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
354 
355  // If the data source or ingest stream haven't been initialized, stop processing
356  if (ingestStream == null) {
357  String message = "Ingest stream was not initialized before running the add image process on " + imagePath;
358  logger.log(Level.SEVERE, message);
359  final List<String> errors = new ArrayList<>();
360  errors.add(message);
361  callback.done(DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS, errors, new ArrayList<>());
362  return;
363  }
364  if (image == null) {
365  String message = "Image was not added to database before running the add image process on " + imagePath;
366  logger.log(Level.SEVERE, message);
367  final List<String> errors = new ArrayList<>();
368  errors.add(message);
369  callback.done(DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS, errors, new ArrayList<>());
370  return;
371  }
372 
373  AddImageTask.ImageDetails imageDetails = new AddImageTask.ImageDetails(deviceId, image, sectorSize, timeZone, ignoreFatOrphanFiles, md5, sha1, sha256, null);
374  addImageTask = new AddImageTask(imageDetails,
375  progressMonitor,
376  new StreamingAddDataSourceCallbacks(ingestStream),
377  new StreamingAddImageTaskCallback(ingestStream, callback));
378  new Thread(addImageTask).start();
379  }
380 
388  @Override
389  public void cancel() {
390  if (null != addImageTask) {
391  addImageTask.cancelTask();
392  }
393  if (ingestStream != null) {
394  ingestStream.stop();
395  }
396  }
397 
402  @Override
403  public void reset() {
404  deviceId = null;
405  imagePath = null;
406  timeZone = null;
407  ignoreFatOrphanFiles = false;
408  configPanel.reset();
409  setDataSourceOptionsCalled = false;
410  }
411 
412  private static boolean isAcceptedByFiler(File file, List<FileFilter> filters) {
413  for (FileFilter filter : filters) {
414  if (filter.accept(file)) {
415  return true;
416  }
417  }
418  return false;
419  }
420 
421  @Override
422  public int canProcess(Path dataSourcePath) throws AutoIngestDataSourceProcessorException {
423 
424  // check file extension for supported types
425  if (!isAcceptedByFiler(dataSourcePath.toFile(), filtersList)) {
426  return 0;
427  }
428 
429  try {
430  // verify that the image has a file system that TSK can process
431  Case currentCase = Case.getCurrentCaseThrows();
432  if (!DataSourceUtils.imageHasFileSystem(dataSourcePath)) {
433  // image does not have a file system that TSK can process
434  return 0;
435  }
436  } catch (Exception ex) {
437  throw new AutoIngestDataSourceProcessorException("Exception inside canProcess() method", ex);
438  }
439 
440  // able to process the data source
441  return 100;
442  }
443 
444  @Override
445  public void process(String deviceId, Path dataSourcePath, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack) {
446  this.deviceId = deviceId;
447  this.imagePath = dataSourcePath.toString();
448  this.sectorSize = 0;
449  this.timeZone = Calendar.getInstance().getTimeZone().getID();
450  this.ignoreFatOrphanFiles = false;
451  setDataSourceOptionsCalled = true;
452 
453  ingestStream = new DefaultIngestStream();
454  try {
455  image = SleuthkitJNI.addImageToDatabase(Case.getCurrentCase().getSleuthkitCase(),
456  new String[]{imagePath}, sectorSize, timeZone, "", "", "", deviceId);
457  } catch (TskCoreException ex) {
458  logger.log(Level.SEVERE, "Error adding data source with path " + imagePath + " to database", ex);
459  final List<String> errors = new ArrayList<>();
460  errors.add(ex.getMessage());
461  callBack.done(DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS, errors, new ArrayList<>());
462  return;
463  }
464 
465  doAddImageProcess(deviceId, dataSourcePath.toString(), sectorSize, timeZone, ignoreFatOrphanFiles, null, null, null, progressMonitor, callBack);
466  }
467 
468  @Override
469  public IngestStream processWithIngestStream(String deviceId, Path dataSourcePath, IngestJobSettings settings, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack) {
470  this.deviceId = deviceId;
471  this.imagePath = dataSourcePath.toString();
472  this.sectorSize = 0;
473  this.timeZone = Calendar.getInstance().getTimeZone().getID();
474  this.ignoreFatOrphanFiles = false;
475  setDataSourceOptionsCalled = true;
476 
477  // Set up the data source before creating the ingest stream
478  try {
479  image = SleuthkitJNI.addImageToDatabase(Case.getCurrentCase().getSleuthkitCase(),
480  new String[]{imagePath}, sectorSize, timeZone, md5, sha1, sha256, deviceId);
481  } catch (TskCoreException ex) {
482  logger.log(Level.SEVERE, "Error adding data source with path " + imagePath + " to database", ex);
483  final List<String> errors = new ArrayList<>();
484  errors.add(ex.getMessage());
485  callBack.done(DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS, errors, new ArrayList<>());
486  return null;
487  }
488 
489  // Now initialize the ingest stream
490  try {
491  ingestStream = IngestManager.getInstance().openIngestStream(image, settings);
492  } catch (TskCoreException ex) {
493  logger.log(Level.SEVERE, "Error starting ingest modules", ex);
494  final List<String> errors = new ArrayList<>();
495  errors.add(ex.getMessage());
496  callBack.done(DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS, errors, new ArrayList<>());
497  return null;
498  }
499 
500  doAddImageProcess(deviceId, dataSourcePath.toString(), sectorSize, timeZone, ignoreFatOrphanFiles, null, null, null, progressMonitor, callBack);
501  return ingestStream;
502  }
503 
517  @Deprecated
518  public void setDataSourceOptions(String imagePath, String timeZone, boolean ignoreFatOrphanFiles) {
519  this.deviceId = UUID.randomUUID().toString();
520  this.imagePath = imagePath;
521  this.sectorSize = 0;
522  this.timeZone = Calendar.getInstance().getTimeZone().getID();
523  this.ignoreFatOrphanFiles = ignoreFatOrphanFiles;
524  setDataSourceOptionsCalled = true;
525  }
526 
527 }
IngestStream openIngestStream(DataSource dataSource, IngestJobSettings settings)
static synchronized IngestManager getInstance()
void process(String deviceId, Path dataSourcePath, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack)
static boolean isAcceptedByFiler(File file, List< FileFilter > filters)
static synchronized ImageFilePanel createInstance(String context, List< FileFilter > fileChooserFilters)
IngestStream processWithIngestStream(String deviceId, Path dataSourcePath, IngestJobSettings settings, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack)
void run(String deviceId, String imagePath, String timeZone, boolean ignoreFatOrphanFiles, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback)
void done(DataSourceProcessorResult result, List< String > errList, List< Content > newDataSources)
static final List< String > VIRTUAL_MACHINE_EXTS
static final List< String > ENCASE_IMAGE_EXTS
void setDataSourceOptions(String imagePath, String timeZone, boolean ignoreFatOrphanFiles)
void doAddImageProcess(String deviceId, String imagePath, int sectorSize, String timeZone, boolean ignoreFatOrphanFiles, String md5, String sha1, String sha256, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback)
static boolean imageHasFileSystem(Path dataSourcePath)
void run(DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback)
synchronized static Logger getLogger(String name)
Definition: Logger.java:124
void runWithIngestStream(IngestJobSettings settings, DataSourceProcessorProgressMonitor progress, DataSourceProcessorCallback callBack)

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