diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java b/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java index 6e27d1d831..be7905e010 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java @@ -278,7 +278,7 @@ public class ImageDSProcessor implements DataSourceProcessor, AutoIngestDataSour } @Override - public void process(String deviceId, Path dataSourcePath, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack) throws AutoIngestDataSourceProcessorException { + public void process(String deviceId, Path dataSourcePath, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack) { this.deviceId = deviceId; this.imagePath = dataSourcePath.toString(); this.sectorSize = 0; diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskDSProcessor.java b/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskDSProcessor.java index bc3d2d1f71..38d422585f 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskDSProcessor.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskDSProcessor.java @@ -18,20 +18,15 @@ */ package org.sleuthkit.autopsy.casemodule; -import java.io.File; -import java.nio.file.Path; import java.util.Calendar; import java.util.UUID; import javax.swing.JPanel; import org.openide.util.NbBundle; import org.openide.util.lookup.ServiceProvider; -import org.openide.util.lookup.ServiceProviders; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor; -import org.sleuthkit.autopsy.coreutils.DriveUtils; import org.sleuthkit.autopsy.imagewriter.ImageWriterSettings; -import org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor; /** * A local drive data source processor that implements the DataSourceProcessor @@ -39,11 +34,8 @@ import org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor; * wizard. It also provides a run method overload to allow it to be used * independently of the wizard. */ -@ServiceProviders(value = { - @ServiceProvider(service = DataSourceProcessor.class), - @ServiceProvider(service = AutoIngestDataSourceProcessor.class)} -) -public class LocalDiskDSProcessor implements DataSourceProcessor, AutoIngestDataSourceProcessor { +@ServiceProvider(service = DataSourceProcessor.class) +public class LocalDiskDSProcessor implements DataSourceProcessor { private static final String DATA_SOURCE_TYPE = NbBundle.getMessage(LocalDiskDSProcessor.class, "LocalDiskDSProcessor.dsType.text"); private final LocalDiskPanel configPanel; @@ -230,38 +222,6 @@ public class LocalDiskDSProcessor implements DataSourceProcessor, AutoIngestData setDataSourceOptionsCalled = false; } - @Override - public int canProcess(Path dataSourcePath) throws AutoIngestDataSourceProcessorException { - - // verify that the data source is not a file or a directory - File file = dataSourcePath.toFile(); - // ELTODO this needs to be tested more. should I keep isDirectory or just test for isFile? - if (file.isFile() || file.isDirectory()) { - return 0; - } - - // check whether data source is an existing disk or partition - // ELTODO this needs to be tested more. do these methods actually work correctly? - // or should I use PlatformUtil.getPhysicalDrives() and PlatformUtil.getPartitions() instead? - String path = dataSourcePath.toString(); - if ((DriveUtils.isPhysicalDrive(path) || DriveUtils.isPartition(path)) && DriveUtils.driveExists(path)) { - return 90; - } - - return 0; - } - - @Override - public void process(String deviceId, Path dataSourcePath, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack) throws AutoIngestDataSourceProcessorException { - this.deviceId = deviceId; - this.drivePath = dataSourcePath.toString(); - this.sectorSize = 0; - this.timeZone = Calendar.getInstance().getTimeZone().getID(); - this.ignoreFatOrphanFiles = false; - setDataSourceOptionsCalled = true; - run(deviceId, drivePath, sectorSize, timeZone, ignoreFatOrphanFiles, progressMonitor, callBack); - } - /** * Sets the configuration of the data source processor without using the * configuration panel. diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesDSProcessor.java b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesDSProcessor.java index cfba224f1c..92ca15a27e 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesDSProcessor.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalFilesDSProcessor.java @@ -51,8 +51,7 @@ import org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor; * method overload to allow it to be used independently of the wizard. */ @ServiceProviders(value = { - @ServiceProvider(service = DataSourceProcessor.class) - , + @ServiceProvider(service = DataSourceProcessor.class), @ServiceProvider(service = AutoIngestDataSourceProcessor.class)} ) @Messages({ @@ -369,7 +368,7 @@ public class LocalFilesDSProcessor implements DataSourceProcessor, AutoIngestDat } @Override - public void process(String deviceId, Path dataSourcePath, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack) throws AutoIngestDataSourceProcessorException { + public void process(String deviceId, Path dataSourcePath, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack) { run(deviceId, deviceId, this.localFilePaths, progressMonitor, callBack); } diff --git a/Core/src/org/sleuthkit/autopsy/datasourceprocessors/AutoIngestDataSourceProcessor.java b/Core/src/org/sleuthkit/autopsy/datasourceprocessors/AutoIngestDataSourceProcessor.java index 163d164376..20f3bb59bd 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourceprocessors/AutoIngestDataSourceProcessor.java +++ b/Core/src/org/sleuthkit/autopsy/datasourceprocessors/AutoIngestDataSourceProcessor.java @@ -63,9 +63,8 @@ public interface AutoIngestDataSourceProcessor extends DataSourceProcessor { * background task to report progress. * @param callBack Callback that will be used by the background task * to return results. - * @throws org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException */ - void process(String deviceId, Path dataSourcePath, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack) throws AutoIngestDataSourceProcessorException; + void process(String deviceId, Path dataSourcePath, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack); /** * A custom exception for the use of AutomatedIngestDataSourceProcessor. diff --git a/Core/src/org/sleuthkit/autopsy/datasourceprocessors/RawDSProcessor.java b/Core/src/org/sleuthkit/autopsy/datasourceprocessors/RawDSProcessor.java index 5b9edb5a83..f18e40da1d 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourceprocessors/RawDSProcessor.java +++ b/Core/src/org/sleuthkit/autopsy/datasourceprocessors/RawDSProcessor.java @@ -18,10 +18,18 @@ */ package org.sleuthkit.autopsy.datasourceprocessors; +import java.io.File; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; import java.util.UUID; import javax.swing.JPanel; +import javax.swing.filechooser.FileFilter; import org.openide.util.NbBundle.Messages; import org.openide.util.lookup.ServiceProvider; +import org.openide.util.lookup.ServiceProviders; +import org.sleuthkit.autopsy.casemodule.GeneralFilter; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor; @@ -32,12 +40,25 @@ import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor; * also provides a run method overload to allow it to be used independently of * the wizard. */ -@ServiceProvider(service = DataSourceProcessor.class) -public class RawDSProcessor implements DataSourceProcessor { +@ServiceProviders(value={ + @ServiceProvider(service=DataSourceProcessor.class), + @ServiceProvider(service=AutoIngestDataSourceProcessor.class)} +) +public class RawDSProcessor implements DataSourceProcessor, AutoIngestDataSourceProcessor { private final RawDSInputPanel configPanel; private AddRawImageTask addImageTask; - + private static final GeneralFilter rawFilter = new GeneralFilter(GeneralFilter.RAW_IMAGE_EXTS, GeneralFilter.RAW_IMAGE_DESC); + private static final GeneralFilter encaseFilter = new GeneralFilter(GeneralFilter.ENCASE_IMAGE_EXTS, GeneralFilter.ENCASE_IMAGE_DESC); + private static final List filtersList = new ArrayList<>(); + static { + filtersList.add(rawFilter); + filtersList.add(encaseFilter); + } + + // By default, split image into 2GB unallocated space chunks + private static final long DEFAULT_CHUNK_SIZE = 2000000000L; // 2 GB + /* * Constructs a Raw data source processor that implements the * DataSourceProcessor service provider interface to allow integration with @@ -158,5 +179,29 @@ public class RawDSProcessor implements DataSourceProcessor { public void reset() { configPanel.reset(); } + + private static boolean isAcceptedByFiler(File file, List filters) { + for (FileFilter filter : filters) { + if (filter.accept(file)) { + return true; + } + } + return false; + } + + @Override + public int canProcess(Path dataSourcePath) throws AutoIngestDataSourceProcessorException { + // check file extension for supported types + if (!isAcceptedByFiler(dataSourcePath.toFile(), filtersList)) { + return 0; + } + + return 2; + } + + @Override + public void process(String deviceId, Path dataSourcePath, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack) { + run(deviceId, dataSourcePath.toString(), Calendar.getInstance().getTimeZone().getID(), DEFAULT_CHUNK_SIZE, progressMonitor, callBack); + } } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AddArchiveTask.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AddArchiveTask.java index 6835510e78..3baf91b871 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AddArchiveTask.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AddArchiveTask.java @@ -178,36 +178,30 @@ class AddArchiveTask implements Runnable { logger.log(Level.INFO, "Using {0} to process extracted file {1} ", new Object[]{selectedProcessor.getDataSourceType(), file}); synchronized (archiveDspLock) { - try { - UUID taskId = UUID.randomUUID(); - currentCase.notifyAddingDataSource(taskId); - AutoIngestDataSource internalDataSource = new AutoIngestDataSource(deviceId, newFilePath); - DataSourceProcessorCallback internalArchiveDspCallBack = new AddDataSourceCallback(currentCase, internalDataSource, taskId, archiveDspLock); - selectedProcessor.process(deviceId, newFilePath, progressMonitor, internalArchiveDspCallBack); - archiveDspLock.wait(); + UUID taskId = UUID.randomUUID(); + currentCase.notifyAddingDataSource(taskId); + AutoIngestDataSource internalDataSource = new AutoIngestDataSource(deviceId, newFilePath); + DataSourceProcessorCallback internalArchiveDspCallBack = new AddDataSourceCallback(currentCase, internalDataSource, taskId, archiveDspLock); + selectedProcessor.process(deviceId, newFilePath, progressMonitor, internalArchiveDspCallBack); + archiveDspLock.wait(); - // at this point we got the content object(s) from the current DSP. - // check whether the data source was processed successfully - if ((internalDataSource.getResultDataSourceProcessorResultCode() == CRITICAL_ERRORS) - || internalDataSource.getContent().isEmpty()) { - // move onto the the next DSP that can process this data source - continue; + // at this point we got the content object(s) from the current DSP. + // check whether the data source was processed successfully + if ((internalDataSource.getResultDataSourceProcessorResultCode() == CRITICAL_ERRORS) + || internalDataSource.getContent().isEmpty()) { + // move onto the the next DSP that can process this data source + for (String errorMessage : internalDataSource.getDataSourceProcessorErrorMessages()) { + logger.log(Level.SEVERE, "Data source processor {0} was unable to process {1}: {2}", new Object[]{selectedProcessor.getDataSourceType(), internalDataSource.getPath(), errorMessage}); } - - // if we are here it means the data source was addedd successfully - success = true; - newDataSources.addAll(internalDataSource.getContent()); - - // skip all other DSPs for this data source - break; - } catch (AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException ex) { - // Log that the current DSP failed and set the error flag. We consider it an error - // if a DSP fails even if a later one succeeds since we expected to be able to process - // the data source which each DSP on the list. - criticalErrorOccurred = true; - errorMessages.add(ex.getMessage()); - logger.log(Level.SEVERE, "Exception while processing {0} with data source processor {1}", new Object[]{newFilePath.toString(), selectedProcessor.getDataSourceType()}); + continue; } + + // if we are here it means the data source was addedd successfully + success = true; + newDataSources.addAll(internalDataSource.getContent()); + + // skip all other DSPs for this data source + break; } } @@ -271,7 +265,7 @@ class AddArchiveTask implements Runnable { } /** - * Get a list of data source processors. LocalDisk, LocalFiles, and + * Get a list of data source processors. LocalFiles, and * ArchiveDSP are removed from the list. * * @return List of data source processors @@ -285,10 +279,9 @@ class AddArchiveTask implements Runnable { for (Iterator iterator = validDataSourceProcessors.iterator(); iterator.hasNext();) { AutoIngestDataSourceProcessor selectedProcessor = iterator.next(); - // skip local files and local disk DSPs, only looking for "valid" data sources. + // skip local files, only looking for "valid" data sources. // also skip nested archive files, those will be ingested as logical files and extracted during ingest - if ((selectedProcessor instanceof LocalDiskDSProcessor) - || (selectedProcessor instanceof LocalFilesDSProcessor) + if ((selectedProcessor instanceof LocalFilesDSProcessor) || (selectedProcessor instanceof ArchiveExtractorDSProcessor)) { iterator.remove(); } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/ArchiveExtractorDSProcessor.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/ArchiveExtractorDSProcessor.java index 0eba2b8f95..a30fbf0c75 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/ArchiveExtractorDSProcessor.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/ArchiveExtractorDSProcessor.java @@ -77,7 +77,7 @@ public class ArchiveExtractorDSProcessor implements AutoIngestDataSourceProcesso } @Override - public void process(String deviceId, Path dataSourcePath, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack) throws AutoIngestDataSourceProcessorException { + public void process(String deviceId, Path dataSourcePath, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack) { run(deviceId, dataSourcePath.toString(), progressMonitor, callBack); } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java index 41a5d46192..cc162494ae 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestManager.java @@ -74,6 +74,7 @@ import org.sleuthkit.autopsy.core.ServicesMonitor.ServicesMonitorException; import org.sleuthkit.autopsy.core.UserPreferencesException; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback.DataSourceProcessorResult; +import static org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor; import org.sleuthkit.autopsy.coreutils.NetworkUtils; import org.sleuthkit.autopsy.events.AutopsyEvent; @@ -2486,29 +2487,32 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen caseForJob.notifyAddingDataSource(taskId); jobLogger.logDataSourceProcessorSelected(selectedProcessor.getDataSourceType()); SYS_LOGGER.log(Level.INFO, "Identified data source type for {0} as {1}", new Object[]{manifestPath, selectedProcessor.getDataSourceType()}); - try { - selectedProcessor.process(dataSource.getDeviceId(), dataSource.getPath(), progressMonitor, callBack); - ingestLock.wait(); - return; - } catch (AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException ex) { - // Log that the current DSP failed and set the error flag. We consider it an error - // if a DSP fails even if a later one succeeds since we expected to be able to process - // the data source which each DSP on the list. - setCaseNodeDataErrorsOccurred(caseDirectoryPath); - currentJob.setErrorsOccurred(true); + selectedProcessor.process(dataSource.getDeviceId(), dataSource.getPath(), progressMonitor, callBack); + ingestLock.wait(); + + // at this point we got the content object(s) from the current DSP. + // check whether the data source was processed successfully + if ((dataSource.getResultDataSourceProcessorResultCode() == CRITICAL_ERRORS) + || dataSource.getContent().isEmpty()) { + // move onto the the next DSP that can process this data source jobLogger.logDataSourceProcessorError(selectedProcessor.getDataSourceType()); - SYS_LOGGER.log(Level.SEVERE, "Exception while processing {0} with data source processor {1}", new Object[]{dataSource.getPath(), selectedProcessor.getDataSourceType()}); + logDataSourceProcessorResult(dataSource); + continue; } + + logDataSourceProcessorResult(dataSource); + return; } // If we get to this point, none of the processors were successful SYS_LOGGER.log(Level.SEVERE, "All data source processors failed to process {0}", dataSource.getPath()); jobLogger.logFailedToAddDataSource(); + setCaseNodeDataErrorsOccurred(caseDirectoryPath); + currentJob.setErrorsOccurred(true); // Throw an exception. It will get caught & handled upstream and will result in AIM auto-pause. throw new AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException("Failed to process " + dataSource.getPath() + " with all data source processors"); } } finally { currentJob.setDataSourceProcessor(null); - logDataSourceProcessorResult(dataSource); } } @@ -2537,8 +2541,6 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen case NO_ERRORS: jobLogger.logDataSourceAdded(); if (dataSource.getContent().isEmpty()) { - currentJob.setErrorsOccurred(true); - setCaseNodeDataErrorsOccurred(caseDirectoryPath); jobLogger.logNoDataSourceContent(); } break; @@ -2549,8 +2551,6 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen } jobLogger.logDataSourceAdded(); if (dataSource.getContent().isEmpty()) { - currentJob.setErrorsOccurred(true); - setCaseNodeDataErrorsOccurred(caseDirectoryPath); jobLogger.logNoDataSourceContent(); } break; @@ -2559,8 +2559,6 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen for (String errorMessage : dataSource.getDataSourceProcessorErrorMessages()) { SYS_LOGGER.log(Level.SEVERE, "Critical error running data source processor for {0}: {1}", new Object[]{manifestPath, errorMessage}); } - currentJob.setErrorsOccurred(true); - setCaseNodeDataErrorsOccurred(caseDirectoryPath); jobLogger.logFailedToAddDataSource(); break; } @@ -2573,8 +2571,6 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen * cancelCurrentJob. */ SYS_LOGGER.log(Level.WARNING, "Cancellation while waiting for data source processor for {0}", manifestPath); - currentJob.setErrorsOccurred(true); - setCaseNodeDataErrorsOccurred(caseDirectoryPath); jobLogger.logDataSourceProcessorCancelled(); } }