Autopsy  4.20.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-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.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.Host;
43 import org.sleuthkit.datamodel.Image;
44 import org.sleuthkit.datamodel.SleuthkitJNI;
45 import org.sleuthkit.datamodel.TskCoreException;
46 
53 @ServiceProviders(value = {
54  @ServiceProvider(service = DataSourceProcessor.class),
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 Host host = null;
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  run(null, progressMonitor, callback);
185  }
186 
202  @Override
203  public void run(Host host, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
204  ingestStream = new DefaultIngestStream();
205  readConfigSettings();
206  this.host = host;
207  try {
208  image = SleuthkitJNI.addImageToDatabase(Case.getCurrentCase().getSleuthkitCase(),
209  new String[]{imagePath}, sectorSize, timeZone, md5, sha1, sha256, deviceId, this.host);
210  } catch (TskCoreException ex) {
211  logger.log(Level.SEVERE, "Error adding data source with path " + imagePath + " to database", ex);
212  final List<String> errors = new ArrayList<>();
213  errors.add(ex.getMessage());
214  callback.done(DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS, errors, new ArrayList<>());
215  return;
216  }
217 
218  doAddImageProcess(deviceId, imagePath, sectorSize, timeZone, ignoreFatOrphanFiles, md5, sha1, sha256, progressMonitor, callback);
219  }
220 
238  @Override
240  DataSourceProcessorCallback callBack) {
241  runWithIngestStream(null, settings, progress, callBack);
242  }
243 
262  @Override
264  DataSourceProcessorCallback callBack) {
265 
266  // Read the settings from the wizard
267  readConfigSettings();
268  this.host = host;
269 
270  // Set up the data source before creating the ingest stream
271  try {
272  image = SleuthkitJNI.addImageToDatabase(Case.getCurrentCase().getSleuthkitCase(),
273  new String[]{imagePath}, sectorSize, timeZone, md5, sha1, sha256, deviceId, this.host);
274  } catch (TskCoreException ex) {
275  logger.log(Level.SEVERE, "Error adding data source with path " + imagePath + " to database", ex);
276  final List<String> errors = new ArrayList<>();
277  errors.add(ex.getMessage());
278  callBack.done(DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS, errors, new ArrayList<>());
279  return;
280  }
281 
282  // Now initialize the ingest stream
283  try {
284  ingestStream = IngestManager.getInstance().openIngestStream(image, settings);
285  } catch (TskCoreException ex) {
286  logger.log(Level.SEVERE, "Error starting ingest modules", ex);
287  // There was an error with ingest, but the data source has already been added
288  // so proceed with the defaultIngestStream. Code in openIngestStream
289  // should have caused a dialog to popup with the errors.
290  ingestStream = new DefaultIngestStream();
291  }
292 
293  doAddImageProcess(deviceId, imagePath, sectorSize, timeZone, ignoreFatOrphanFiles, md5, sha1, sha256, progress, callBack);
294  }
295 
299  private void readConfigSettings() {
300  configPanel.storeSettings();
301  deviceId = UUID.randomUUID().toString();
302  imagePath = configPanel.getContentPaths();
303  sectorSize = configPanel.getSectorSize();
304  timeZone = configPanel.getTimeZone();
305  ignoreFatOrphanFiles = configPanel.getNoFatOrphans();
306  md5 = configPanel.getMd5();
307  if (md5.isEmpty()) {
308  md5 = null;
309  }
310  sha1 = configPanel.getSha1();
311  if (sha1.isEmpty()) {
312  sha1 = null;
313  }
314  sha256 = configPanel.getSha256();
315  if (sha256.isEmpty()) {
316  sha256 = null;
317  }
318  }
319 
325  @Override
326  public boolean supportsIngestStream() {
327  return true;
328  }
329 
351  public void run(String deviceId, String imagePath, String timeZone, boolean ignoreFatOrphanFiles, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
352  ingestStream = new DefaultIngestStream();
353  try {
354  image = SleuthkitJNI.addImageToDatabase(Case.getCurrentCase().getSleuthkitCase(),
355  new String[]{imagePath}, sectorSize, timeZone, "", "", "", deviceId);
356  } catch (TskCoreException ex) {
357  logger.log(Level.SEVERE, "Error adding data source with path " + imagePath + " to database", ex);
358  final List<String> errors = new ArrayList<>();
359  errors.add(ex.getMessage());
360  callback.done(DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS, errors, new ArrayList<>());
361  return;
362  }
363 
364  doAddImageProcess(deviceId, imagePath, 0, timeZone, ignoreFatOrphanFiles, null, null, null, progressMonitor, callback);
365  }
366 
396  private void doAddImageProcess(String deviceId, String imagePath, int sectorSize, String timeZone, boolean ignoreFatOrphanFiles, String md5, String sha1, String sha256, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
397 
398  // If the data source or ingest stream haven't been initialized, stop processing
399  if (ingestStream == null) {
400  String message = "Ingest stream was not initialized before running the add image process on " + imagePath;
401  logger.log(Level.SEVERE, message);
402  final List<String> errors = new ArrayList<>();
403  errors.add(message);
404  callback.done(DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS, errors, new ArrayList<>());
405  return;
406  }
407  if (image == null) {
408  String message = "Image was not added to database before running the add image process on " + imagePath;
409  logger.log(Level.SEVERE, message);
410  final List<String> errors = new ArrayList<>();
411  errors.add(message);
412  callback.done(DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS, errors, new ArrayList<>());
413  return;
414  }
415 
416  AddImageTask.ImageDetails imageDetails = new AddImageTask.ImageDetails(deviceId, image, sectorSize, timeZone, ignoreFatOrphanFiles, md5, sha1, sha256, null);
417  addImageTask = new AddImageTask(imageDetails,
418  progressMonitor,
419  new StreamingAddDataSourceCallbacks(ingestStream),
420  new StreamingAddImageTaskCallback(ingestStream, callback));
421  new Thread(addImageTask).start();
422  }
423 
431  @Override
432  public void cancel() {
433  if (null != addImageTask) {
434  addImageTask.cancelTask();
435  }
436  if (ingestStream != null) {
437  ingestStream.stop();
438  }
439  }
440 
445  @Override
446  public void reset() {
447  deviceId = null;
448  imagePath = null;
449  timeZone = null;
450  ignoreFatOrphanFiles = false;
451  host = null;
452  configPanel.reset();
453  }
454 
455  private static boolean isAcceptedByFiler(File file, List<FileFilter> filters) {
456  for (FileFilter filter : filters) {
457  if (filter.accept(file)) {
458  return true;
459  }
460  }
461  return false;
462  }
463 
464  @Override
465  public int canProcess(Path dataSourcePath) throws AutoIngestDataSourceProcessorException {
466 
467  // check file extension for supported types
468  if (!isAcceptedByFiler(dataSourcePath.toFile(), filtersList)) {
469  return 0;
470  }
471 
472  try {
473  // verify that the image has a file system that TSK can process
474  if (!DataSourceUtils.imageHasFileSystem(dataSourcePath)) {
475  // image does not have a file system that TSK can process
476  return 0;
477  }
478  } catch (Exception ex) {
479  throw new AutoIngestDataSourceProcessorException("Exception inside canProcess() method", ex);
480  }
481 
482  // able to process the data source
483  return 100;
484  }
485 
486  @Override
487  public void process(String deviceId, Path dataSourcePath, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack) {
488  process(deviceId, dataSourcePath, null, progressMonitor, callBack);
489  }
490 
491  @Override
492  public void process(String deviceId, Path dataSourcePath, Host host, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack) {
493  // this method does not use the config panel
494  this.deviceId = deviceId;
495  this.imagePath = dataSourcePath.toString();
496  this.sectorSize = 0;
497  this.timeZone = Calendar.getInstance().getTimeZone().getID();
498  this.host = host;
499  this.ignoreFatOrphanFiles = false;
500 
501  ingestStream = new DefaultIngestStream();
502  try {
503  image = SleuthkitJNI.addImageToDatabase(Case.getCurrentCase().getSleuthkitCase(),
504  new String[]{imagePath}, sectorSize, timeZone, "", "", "", deviceId, host);
505  } catch (TskCoreException ex) {
506  logger.log(Level.SEVERE, "Error adding data source with path " + imagePath + " to database", ex);
507  final List<String> errors = new ArrayList<>();
508  errors.add(ex.getMessage());
509  callBack.done(DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS, errors, new ArrayList<>());
510  return;
511  }
512 
513  doAddImageProcess(deviceId, dataSourcePath.toString(), sectorSize, timeZone, ignoreFatOrphanFiles, null, null, null, progressMonitor, callBack);
514  }
515 
516  @Override
517  public IngestStream processWithIngestStream(String deviceId, Path dataSourcePath, IngestJobSettings settings, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack) {
518  return processWithIngestStream(deviceId, dataSourcePath, null, settings, progressMonitor, callBack);
519  }
520 
521  @Override
522  public IngestStream processWithIngestStream(String deviceId, Path dataSourcePath, Host host, IngestJobSettings settings, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack) {
523  // this method does not use the config panel
524  this.deviceId = deviceId;
525  this.imagePath = dataSourcePath.toString();
526  this.sectorSize = 0;
527  this.timeZone = Calendar.getInstance().getTimeZone().getID();
528  this.host = host;
529  this.ignoreFatOrphanFiles = false;
530 
531  // Set up the data source before creating the ingest stream
532  try {
533  image = SleuthkitJNI.addImageToDatabase(Case.getCurrentCase().getSleuthkitCase(),
534  new String[]{imagePath}, sectorSize, timeZone, md5, sha1, sha256, deviceId, host);
535  } catch (TskCoreException ex) {
536  logger.log(Level.SEVERE, "Error adding data source with path " + imagePath + " to database", ex);
537  final List<String> errors = new ArrayList<>();
538  errors.add(ex.getMessage());
539  callBack.done(DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS, errors, new ArrayList<>());
540  return null;
541  }
542 
543  // Now initialize the ingest stream
544  try {
545  ingestStream = IngestManager.getInstance().openIngestStream(image, settings);
546  } catch (TskCoreException ex) {
547  logger.log(Level.SEVERE, "Error starting ingest modules", ex);
548  final List<String> errors = new ArrayList<>();
549  errors.add(ex.getMessage());
550  callBack.done(DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS, errors, new ArrayList<>());
551  return null;
552  }
553 
554  doAddImageProcess(deviceId, dataSourcePath.toString(), sectorSize, timeZone, ignoreFatOrphanFiles, null, null, null, progressMonitor, callBack);
555 
556  return ingestStream;
557  }
558 }
IngestStream openIngestStream(DataSource dataSource, IngestJobSettings settings)
static synchronized IngestManager getInstance()
void run(Host host, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback)
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)
IngestStream processWithIngestStream(String deviceId, Path dataSourcePath, Host host, IngestJobSettings settings, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack)
static final List< String > VIRTUAL_MACHINE_EXTS
static final List< String > ENCASE_IMAGE_EXTS
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 process(String deviceId, Path dataSourcePath, Host host, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack)
void run(DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback)
synchronized static Logger getLogger(String name)
Definition: Logger.java:124
void runWithIngestStream(IngestJobSettings settings, DataSourceProcessorProgressMonitor progress, DataSourceProcessorCallback callBack)
void runWithIngestStream(Host host, IngestJobSettings settings, DataSourceProcessorProgressMonitor progress, DataSourceProcessorCallback callBack)

Copyright © 2012-2022 Basis Technology. Generated on: Tue Aug 1 2023
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.