1
0
mirror of https://github.com/elisspace/autopsy.git synced 2026-09-06 02:24:30 +00:00

Merge pull request #3577 from eugene7646/unalloc_image_add_3590

Ability to add image as unallocated space if other DSPs fail to process it (3590)
This commit is contained in:
Richard Cordovano
2018-03-20 16:48:05 -04:00
committed by GitHub
8 changed files with 95 additions and 103 deletions

View File

@@ -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;

View File

@@ -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.

View File

@@ -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);
}

View File

@@ -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.

View File

@@ -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<FileFilter> 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<FileFilter> 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);
}
}

View File

@@ -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<AutoIngestDataSourceProcessor> 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();
}

View File

@@ -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);
}

View File

@@ -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();
}
}