Autopsy  4.21.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.apache.commons.lang3.StringUtils;
31 import org.openide.util.NbBundle;
32 import org.openide.util.lookup.ServiceProvider;
33 import org.openide.util.lookup.ServiceProviders;
47 
54 @ServiceProviders(value = {
55  @ServiceProvider(service = DataSourceProcessor.class),
56  @ServiceProvider(service = AutoIngestDataSourceProcessor.class)}
57 )
59 
60  private final static String DATA_SOURCE_TYPE = NbBundle.getMessage(ImageDSProcessor.class, "ImageDSProcessor.dsType.text");
61  private final Logger logger = Logger.getLogger(ImageDSProcessor.class.getName());
62  private static final List<String> allExt = new ArrayList<>();
66  private static final String ALL_DESC = NbBundle.getMessage(ImageDSProcessor.class, "ImageDSProcessor.allDesc.text");
67  private static final GeneralFilter allFilter = new GeneralFilter(allExt, ALL_DESC);
68  private static final List<FileFilter> filtersList = new ArrayList<>();
69  private final ImageFilePanel configPanel;
70  private AddImageTask addImageTask;
71  private IngestStream ingestStream = null;
72  private Image image = null;
73  /*
74  * TODO: Remove the setDataSourceOptionsCalled flag and the settings fields
75  * when the deprecated method setDataSourceOptions is removed.
76  */
77  private String deviceId;
78  private String imagePath;
79  private int sectorSize;
80  private String timeZone;
81  private boolean ignoreFatOrphanFiles;
82  private String md5;
83  private String sha1;
84  private String sha256;
85  private Host host = null;
86  private String password;
87 
88  static {
89  filtersList.add(allFilter);
90  filtersList.add(rawFilter);
91  filtersList.add(encaseFilter);
92  allExt.addAll(GeneralFilter.RAW_IMAGE_EXTS);
93  allExt.addAll(GeneralFilter.ENCASE_IMAGE_EXTS);
94  if (!System.getProperty("os.name").toLowerCase().contains("mac")) {
95  filtersList.add(virtualMachineFilter);
96  allExt.addAll(GeneralFilter.VIRTUAL_MACHINE_EXTS);
97  }
98  }
99 
106  public ImageDSProcessor() {
107  configPanel = ImageFilePanel.createInstance(ImageDSProcessor.class.getName(), filtersList);
108  }
109 
115  static List<FileFilter> getFileFiltersList() {
116  return filtersList;
117  }
118 
126  public static String getType() {
127  return DATA_SOURCE_TYPE;
128  }
129 
137  @Override
138  public String getDataSourceType() {
139  return getType();
140  }
141 
150  @Override
151  public JPanel getPanel() {
152  configPanel.reset();
153  configPanel.readSettings();
154  configPanel.select();
155  return configPanel;
156  }
157 
165  @Override
166  public boolean isPanelValid() {
167  // before attempting to validate the panel (a potentially long running operation),
168  // check if the validation is loading or on delay.
169  return !configPanel.isValidationLoading() && configPanel.validatePanel();
170  }
171 
186  @Override
187  public void run(DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
188  run(null, null, progressMonitor, callback);
189  }
190 
206  @Override
207  public void run(Host host, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
208  run(null, host, progressMonitor, callback);
209  }
210 
211 
212  @Override
213  public void run(String password, Host host, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
214  ingestStream = new DefaultIngestStream();
215  readConfigSettings();
216  this.host = host;
217  this.password = StringUtils.defaultString(password, this.password);
218  try {
220  new String[]{imagePath}, sectorSize, timeZone, md5, sha1, sha256, deviceId, this.password, this.host);
221  } catch (TskCoreException ex) {
222  logger.log(Level.SEVERE, "Error adding data source with path " + imagePath + " to database", ex);
223  final List<String> errors = new ArrayList<>();
224  errors.add(ex.getMessage());
225  callback.done(DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS, errors, new ArrayList<>());
226  return;
227  }
228 
229  doAddImageProcess(deviceId, imagePath, sectorSize, timeZone, ignoreFatOrphanFiles, md5, sha1, sha256, this.password, progressMonitor, callback);
230  }
231 
232 
254  public void run(String deviceId, String imagePath, String timeZone, boolean ignoreFatOrphanFiles, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
255  ingestStream = new DefaultIngestStream();
256  try {
258  new String[]{imagePath}, sectorSize, timeZone, "", "", "", deviceId, null, null);
259  } catch (TskCoreException ex) {
260  logger.log(Level.SEVERE, "Error adding data source with path " + imagePath + " to database", ex);
261  final List<String> errors = new ArrayList<>();
262  errors.add(ex.getMessage());
263  callback.done(DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS, errors, new ArrayList<>());
264  return;
265  }
266 
267  doAddImageProcess(deviceId, imagePath, 0, timeZone, ignoreFatOrphanFiles, null, null, null, this.password, progressMonitor, callback);
268  }
269 
270 
271 
289  @Override
291  DataSourceProcessorCallback callBack) {
292  runWithIngestStream(null, null, settings, progress, callBack);
293  }
294 
313  @Override
315  DataSourceProcessorCallback callBack) {
316  runWithIngestStream(null, host, settings, progress, callBack);
317  }
318 
319 
320  @Override
321  public void runWithIngestStream(String password, Host host, IngestJobSettings settings,
323 
324  // Read the settings from the wizard
325  readConfigSettings();
326  this.host = host;
327  this.password = StringUtils.defaultString(password, this.password);
328 
329  // Set up the data source before creating the ingest stream
330  try {
332  new String[]{imagePath}, sectorSize, timeZone, md5, sha1, sha256, deviceId, this.password, this.host);
333  } catch (TskCoreException ex) {
334  logger.log(Level.SEVERE, "Error adding data source with path " + imagePath + " to database", ex);
335  final List<String> errors = new ArrayList<>();
336  errors.add(ex.getMessage());
337  callBack.done(DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS, errors, new ArrayList<>());
338  return;
339  }
340 
341  // Now initialize the ingest stream
342  try {
343  ingestStream = IngestManager.getInstance().openIngestStream(image, settings);
344  } catch (TskCoreException ex) {
345  logger.log(Level.SEVERE, "Error starting ingest modules", ex);
346  // There was an error with ingest, but the data source has already been added
347  // so proceed with the defaultIngestStream. Code in openIngestStream
348  // should have caused a dialog to popup with the errors.
349  ingestStream = new DefaultIngestStream();
350  }
351 
352  doAddImageProcess(deviceId, imagePath, sectorSize, timeZone, ignoreFatOrphanFiles, md5, sha1, sha256, this.password, progress, callBack);
353  }
354 
355 
359  private void readConfigSettings() {
360  configPanel.storeSettings();
361  deviceId = UUID.randomUUID().toString();
362  imagePath = configPanel.getContentPaths();
363  sectorSize = configPanel.getSectorSize();
364  timeZone = configPanel.getTimeZone();
365  ignoreFatOrphanFiles = configPanel.getNoFatOrphans();
366  md5 = configPanel.getMd5();
367  if (md5.isEmpty()) {
368  md5 = null;
369  }
370  sha1 = configPanel.getSha1();
371  if (sha1.isEmpty()) {
372  sha1 = null;
373  }
374  sha256 = configPanel.getSha256();
375  if (sha256.isEmpty()) {
376  sha256 = null;
377  }
378  this.password = configPanel.getPassword();
379  if (this.password.isEmpty()) {
380  password = null;
381  }
382  }
383 
389  @Override
390  public boolean supportsIngestStream() {
391  return true;
392  }
393 
394 
425  private void doAddImageProcess(String deviceId, String imagePath, int sectorSize, String timeZone, boolean ignoreFatOrphanFiles, String md5, String sha1, String sha256, String password, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
426 
427  // If the data source or ingest stream haven't been initialized, stop processing
428  if (ingestStream == null) {
429  String message = "Ingest stream was not initialized before running the add image process on " + imagePath;
430  logger.log(Level.SEVERE, message);
431  final List<String> errors = new ArrayList<>();
432  errors.add(message);
433  callback.done(DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS, errors, new ArrayList<>());
434  return;
435  }
436  if (image == null) {
437  String message = "Image was not added to database before running the add image process on " + imagePath;
438  logger.log(Level.SEVERE, message);
439  final List<String> errors = new ArrayList<>();
440  errors.add(message);
441  callback.done(DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS, errors, new ArrayList<>());
442  return;
443  }
444 
445  AddImageTask.ImageDetails imageDetails = new AddImageTask.ImageDetails(deviceId, image, sectorSize, timeZone, ignoreFatOrphanFiles, md5, sha1, sha256, null, password);
446  addImageTask = new AddImageTask(imageDetails,
447  progressMonitor,
448  new StreamingAddDataSourceCallbacks(ingestStream),
449  new StreamingAddImageTaskCallback(ingestStream, callback));
450  new Thread(addImageTask).start();
451  }
452 
460  @Override
461  public void cancel() {
462  if (null != addImageTask) {
463  addImageTask.cancelTask();
464  }
465  if (ingestStream != null) {
466  ingestStream.stop();
467  }
468  }
469 
474  @Override
475  public void reset() {
476  deviceId = null;
477  imagePath = null;
478  timeZone = null;
479  ignoreFatOrphanFiles = false;
480  host = null;
481  password = null;
482  configPanel.reset();
483  }
484 
485  private static boolean isAcceptedByFiler(File file, List<FileFilter> filters) {
486  for (FileFilter filter : filters) {
487  if (filter.accept(file)) {
488  return true;
489  }
490  }
491  return false;
492  }
493 
494  @Override
495  public int canProcess(Path dataSourcePath) throws AutoIngestDataSourceProcessorException {
496  return canProcess(dataSourcePath, null);
497  }
498 
499 
500 
501  @Override
502  public int canProcess(Path dataSourcePath, String password) throws AutoIngestDataSourceProcessorException {
503 
504  // check file extension for supported types
505  if (!isAcceptedByFiler(dataSourcePath.toFile(), filtersList)) {
506  return 0;
507  }
508 
509  try {
510  if (password == null) {
511 
512  // verify that the image has a file system that TSK can process
513  if (!DataSourceUtils.imageHasFileSystem(dataSourcePath)) {
514  // image does not have a file system that TSK can process
515  return 0;
516  }
517  } else {
518  // verify that the image has a file system that TSK can process
519  if (!DataSourceUtils.imageHasFileSystem(dataSourcePath, password)) {
520  // image does not have a file system that TSK can process
521  return 0;
522  }
523 
524  }
525  } catch (Exception ex) {
526  throw new AutoIngestDataSourceProcessorException("Exception inside canProcess() method", ex);
527  }
528 
529  // able to process the data source
530  return 100;
531  }
532 
533  @Override
534  public void process(String deviceId, Path dataSourcePath, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack) {
535  process(deviceId, dataSourcePath, null, null, progressMonitor, callBack);
536  }
537 
538  @Override
539  public void process(String deviceId, Path dataSourcePath, Host host, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack) {
540  process(deviceId, dataSourcePath, null, host, progressMonitor, callBack);
541  }
542 
543  @Override
544  public void process(String deviceId, Path dataSourcePath, String password, Host host, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack) {
545  // this method does not use the config panel
546  this.deviceId = deviceId;
547  this.imagePath = dataSourcePath.toString();
548  this.sectorSize = 0;
549  this.timeZone = Calendar.getInstance().getTimeZone().getID();
550  this.password = StringUtils.defaultString(password, this.password);
551  this.host = host;
552  this.ignoreFatOrphanFiles = false;
553 
554  ingestStream = new DefaultIngestStream();
555  try {
557  new String[]{imagePath}, sectorSize, timeZone, "", "", "", deviceId, this.password, host);
558  } catch (TskCoreException ex) {
559  logger.log(Level.SEVERE, "Error adding data source with path " + imagePath + " to database", ex);
560  final List<String> errors = new ArrayList<>();
561  errors.add(ex.getMessage());
562  callBack.done(DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS, errors, new ArrayList<>());
563  return;
564  }
565 
566  doAddImageProcess(deviceId, dataSourcePath.toString(), sectorSize, timeZone, ignoreFatOrphanFiles, null, null, null, this.password, progressMonitor, callBack);
567  }
568 
569 
570 
571  @Override
572  public IngestStream processWithIngestStream(String deviceId, Path dataSourcePath, IngestJobSettings settings, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack) {
573  return processWithIngestStream(deviceId, dataSourcePath, null, null, settings, progressMonitor, callBack);
574  }
575 
576  @Override
577  public IngestStream processWithIngestStream(String deviceId, Path dataSourcePath, Host host, IngestJobSettings settings, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack) {
578  return processWithIngestStream(deviceId, dataSourcePath, null, host, settings, progressMonitor, callBack);
579  }
580 
581  @Override
582  public IngestStream processWithIngestStream(String deviceId, Path dataSourcePath, String password, Host host, IngestJobSettings settings, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack) {
583  // this method does not use the config panel
584  this.deviceId = deviceId;
585  this.imagePath = dataSourcePath.toString();
586  this.sectorSize = 0;
587  this.timeZone = Calendar.getInstance().getTimeZone().getID();
588  this.host = host;
589  this.password = password;
590  this.ignoreFatOrphanFiles = false;
591 
592  // Set up the data source before creating the ingest stream
593  try {
595  new String[]{imagePath}, sectorSize, timeZone, md5, sha1, sha256, deviceId, password, host);
596  } catch (TskCoreException ex) {
597  logger.log(Level.SEVERE, "Error adding data source with path " + imagePath + " to database", ex);
598  final List<String> errors = new ArrayList<>();
599  errors.add(ex.getMessage());
600  callBack.done(DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS, errors, new ArrayList<>());
601  return null;
602  }
603 
604  // Now initialize the ingest stream
605  try {
606  ingestStream = IngestManager.getInstance().openIngestStream(image, settings);
607  } catch (TskCoreException ex) {
608  logger.log(Level.SEVERE, "Error starting ingest modules", ex);
609  final List<String> errors = new ArrayList<>();
610  errors.add(ex.getMessage());
611  callBack.done(DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS, errors, new ArrayList<>());
612  return null;
613  }
614 
615  doAddImageProcess(deviceId, dataSourcePath.toString(), sectorSize, timeZone, ignoreFatOrphanFiles, null, null, null, password, progressMonitor, callBack);
616 
617  return ingestStream;
618  }
619 
620 
621 }
IngestStream openIngestStream(DataSource dataSource, IngestJobSettings settings)
void doAddImageProcess(String deviceId, String imagePath, int sectorSize, String timeZone, boolean ignoreFatOrphanFiles, String md5, String sha1, String sha256, String password, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback)
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)
void run(String password, Host host, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback)
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)
IngestStream processWithIngestStream(String deviceId, Path dataSourcePath, String password, Host host, IngestJobSettings settings, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack)
int canProcess(Path dataSourcePath, String password)
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 Image addImageToDatabase(SleuthkitCase skCase, String[] imagePaths, int sectorSize, String timeZone, String md5fromSettings, String sha1fromSettings, String sha256fromSettings, String deviceId)
void runWithIngestStream(String password, Host host, IngestJobSettings settings, DataSourceProcessorProgressMonitor progress, 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 process(String deviceId, Path dataSourcePath, String password, Host host, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack)
void runWithIngestStream(Host host, IngestJobSettings settings, DataSourceProcessorProgressMonitor progress, DataSourceProcessorCallback callBack)

Copyright © 2012-2024 Sleuth Kit Labs. Generated on: Mon Feb 17 2025
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.