mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-06 21:00:22 +00:00
updates for auto ingest
This commit is contained in:
parent
b0a26d14c6
commit
f875da5c12
@ -27,6 +27,7 @@ import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.UUID;
|
||||
import javax.swing.filechooser.FileFilter;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.lookup.ServiceProvider;
|
||||
import org.openide.util.lookup.ServiceProviders;
|
||||
@ -184,7 +185,7 @@ public class ImageDSProcessor implements DataSourceProcessor, AutoIngestDataSour
|
||||
*/
|
||||
@Override
|
||||
public void run(DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
|
||||
run(null, progressMonitor, callback);
|
||||
run(null, null, progressMonitor, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -204,9 +205,16 @@ public class ImageDSProcessor implements DataSourceProcessor, AutoIngestDataSour
|
||||
*/
|
||||
@Override
|
||||
public void run(Host host, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
|
||||
run(null, host, progressMonitor, callback);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void run(String password, Host host, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
|
||||
ingestStream = new DefaultIngestStream();
|
||||
readConfigSettings();
|
||||
this.host = host;
|
||||
this.password = StringUtils.defaultString(password, this.password);
|
||||
try {
|
||||
image = SleuthkitJNI.addImageToDatabase(Case.getCurrentCase().getSleuthkitCase(),
|
||||
new String[]{imagePath}, sectorSize, timeZone, md5, sha1, sha256, deviceId, this.password, this.host);
|
||||
@ -221,6 +229,46 @@ public class ImageDSProcessor implements DataSourceProcessor, AutoIngestDataSour
|
||||
doAddImageProcess(deviceId, imagePath, sectorSize, timeZone, ignoreFatOrphanFiles, md5, sha1, sha256, this.password, progressMonitor, callback);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds a data source to the case database using a background task in a
|
||||
* separate thread and the given settings instead of those provided by the
|
||||
* selection and configuration panel. Returns as soon as the background task
|
||||
* is started and uses the callback object to signal task completion and
|
||||
* return results.
|
||||
*
|
||||
* @param deviceId An ASCII-printable identifier for the device
|
||||
* associated with the data source that is
|
||||
* intended to be unique across multiple cases
|
||||
* (e.g., a UUID).
|
||||
* @param imagePath Path to the image file.
|
||||
* @param timeZone The time zone to use when processing dates
|
||||
* and times for the image, obtained from
|
||||
* java.util.TimeZone.getID.
|
||||
* @param ignoreFatOrphanFiles Whether to parse orphans if the image has a
|
||||
* FAT filesystem.
|
||||
* @param progressMonitor Progress monitor for reporting progress
|
||||
* during processing.
|
||||
* @param callback Callback to call when processing is done.
|
||||
*/
|
||||
public void run(String deviceId, String imagePath, String timeZone, boolean ignoreFatOrphanFiles, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
|
||||
ingestStream = new DefaultIngestStream();
|
||||
try {
|
||||
image = SleuthkitJNI.addImageToDatabase(Case.getCurrentCase().getSleuthkitCase(),
|
||||
new String[]{imagePath}, sectorSize, timeZone, "", "", "", deviceId, null, null);
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Error adding data source with path " + imagePath + " to database", ex);
|
||||
final List<String> errors = new ArrayList<>();
|
||||
errors.add(ex.getMessage());
|
||||
callback.done(DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS, errors, new ArrayList<>());
|
||||
return;
|
||||
}
|
||||
|
||||
doAddImageProcess(deviceId, imagePath, 0, timeZone, ignoreFatOrphanFiles, null, null, null, this.password, progressMonitor, callback);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Adds a data source to the case database using a background task in a
|
||||
* separate thread and the settings provided by the selection and
|
||||
@ -241,7 +289,7 @@ public class ImageDSProcessor implements DataSourceProcessor, AutoIngestDataSour
|
||||
@Override
|
||||
public void runWithIngestStream(IngestJobSettings settings, DataSourceProcessorProgressMonitor progress,
|
||||
DataSourceProcessorCallback callBack) {
|
||||
runWithIngestStream(null, settings, progress, callBack);
|
||||
runWithIngestStream(null, null, settings, progress, callBack);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -265,10 +313,18 @@ public class ImageDSProcessor implements DataSourceProcessor, AutoIngestDataSour
|
||||
@Override
|
||||
public void runWithIngestStream(Host host, IngestJobSettings settings, DataSourceProcessorProgressMonitor progress,
|
||||
DataSourceProcessorCallback callBack) {
|
||||
runWithIngestStream(null, host, settings, progress, callBack);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void runWithIngestStream(String password, Host host, IngestJobSettings settings,
|
||||
DataSourceProcessorProgressMonitor progress, DataSourceProcessorCallback callBack) {
|
||||
|
||||
// Read the settings from the wizard
|
||||
readConfigSettings();
|
||||
this.host = host;
|
||||
this.password = StringUtils.defaultIfEmpty(password, this.password);
|
||||
|
||||
// Set up the data source before creating the ingest stream
|
||||
try {
|
||||
@ -296,6 +352,7 @@ public class ImageDSProcessor implements DataSourceProcessor, AutoIngestDataSour
|
||||
doAddImageProcess(deviceId, imagePath, sectorSize, timeZone, ignoreFatOrphanFiles, md5, sha1, sha256, this.password, progress, callBack);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Store the options from the config panel.
|
||||
*/
|
||||
@ -334,42 +391,6 @@ public class ImageDSProcessor implements DataSourceProcessor, AutoIngestDataSour
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a data source to the case database using a background task in a
|
||||
* separate thread and the given settings instead of those provided by the
|
||||
* selection and configuration panel. Returns as soon as the background task
|
||||
* is started and uses the callback object to signal task completion and
|
||||
* return results.
|
||||
*
|
||||
* @param deviceId An ASCII-printable identifier for the device
|
||||
* associated with the data source that is
|
||||
* intended to be unique across multiple cases
|
||||
* (e.g., a UUID).
|
||||
* @param imagePath Path to the image file.
|
||||
* @param timeZone The time zone to use when processing dates
|
||||
* and times for the image, obtained from
|
||||
* java.util.TimeZone.getID.
|
||||
* @param ignoreFatOrphanFiles Whether to parse orphans if the image has a
|
||||
* FAT filesystem.
|
||||
* @param progressMonitor Progress monitor for reporting progress
|
||||
* during processing.
|
||||
* @param callback Callback to call when processing is done.
|
||||
*/
|
||||
public void run(String deviceId, String imagePath, String timeZone, boolean ignoreFatOrphanFiles, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
|
||||
ingestStream = new DefaultIngestStream();
|
||||
try {
|
||||
image = SleuthkitJNI.addImageToDatabase(Case.getCurrentCase().getSleuthkitCase(),
|
||||
new String[]{imagePath}, sectorSize, timeZone, "", "", "", deviceId, this.password, null);
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Error adding data source with path " + imagePath + " to database", ex);
|
||||
final List<String> errors = new ArrayList<>();
|
||||
errors.add(ex.getMessage());
|
||||
callback.done(DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS, errors, new ArrayList<>());
|
||||
return;
|
||||
}
|
||||
|
||||
doAddImageProcess(deviceId, imagePath, 0, timeZone, ignoreFatOrphanFiles, null, null, null, this.password, progressMonitor, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a data source to the case database using a background task in a
|
||||
@ -472,6 +493,13 @@ public class ImageDSProcessor implements DataSourceProcessor, AutoIngestDataSour
|
||||
|
||||
@Override
|
||||
public int canProcess(Path dataSourcePath) throws AutoIngestDataSourceProcessorException {
|
||||
return canProcess(dataSourcePath, null);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public int canProcess(Path dataSourcePath, String password) throws AutoIngestDataSourceProcessorException {
|
||||
|
||||
// check file extension for supported types
|
||||
if (!isAcceptedByFiler(dataSourcePath.toFile(), filtersList)) {
|
||||
@ -504,23 +532,29 @@ public class ImageDSProcessor implements DataSourceProcessor, AutoIngestDataSour
|
||||
|
||||
@Override
|
||||
public void process(String deviceId, Path dataSourcePath, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack) {
|
||||
process(deviceId, dataSourcePath, null, progressMonitor, callBack);
|
||||
process(deviceId, dataSourcePath, this.password, null, progressMonitor, callBack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void process(String deviceId, Path dataSourcePath, Host host, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack) {
|
||||
process(deviceId, dataSourcePath, this.password, host, progressMonitor, callBack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void process(String deviceId, Path dataSourcePath, String password, Host host, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack) {
|
||||
// this method does not use the config panel
|
||||
this.deviceId = deviceId;
|
||||
this.imagePath = dataSourcePath.toString();
|
||||
this.sectorSize = 0;
|
||||
this.timeZone = Calendar.getInstance().getTimeZone().getID();
|
||||
this.password = password;
|
||||
this.host = host;
|
||||
this.ignoreFatOrphanFiles = false;
|
||||
|
||||
ingestStream = new DefaultIngestStream();
|
||||
try {
|
||||
image = SleuthkitJNI.addImageToDatabase(Case.getCurrentCase().getSleuthkitCase(),
|
||||
new String[]{imagePath}, sectorSize, timeZone, "", "", "", deviceId, this.password, host);
|
||||
new String[]{imagePath}, sectorSize, timeZone, "", "", "", deviceId, password, host);
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Error adding data source with path " + imagePath + " to database", ex);
|
||||
final List<String> errors = new ArrayList<>();
|
||||
@ -529,28 +563,36 @@ public class ImageDSProcessor implements DataSourceProcessor, AutoIngestDataSour
|
||||
return;
|
||||
}
|
||||
|
||||
doAddImageProcess(deviceId, dataSourcePath.toString(), sectorSize, timeZone, ignoreFatOrphanFiles, null, null, null, null, progressMonitor, callBack);
|
||||
doAddImageProcess(deviceId, dataSourcePath.toString(), sectorSize, timeZone, ignoreFatOrphanFiles, null, null, null, password, progressMonitor, callBack);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public IngestStream processWithIngestStream(String deviceId, Path dataSourcePath, IngestJobSettings settings, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack) {
|
||||
return processWithIngestStream(deviceId, dataSourcePath, null, settings, progressMonitor, callBack);
|
||||
return processWithIngestStream(deviceId, dataSourcePath, this.password, null, settings, progressMonitor, callBack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IngestStream processWithIngestStream(String deviceId, Path dataSourcePath, Host host, IngestJobSettings settings, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack) {
|
||||
return processWithIngestStream(deviceId, dataSourcePath, this.password, host, settings, progressMonitor, callBack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IngestStream processWithIngestStream(String deviceId, Path dataSourcePath, String password, Host host, IngestJobSettings settings, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack) {
|
||||
// this method does not use the config panel
|
||||
this.deviceId = deviceId;
|
||||
this.imagePath = dataSourcePath.toString();
|
||||
this.sectorSize = 0;
|
||||
this.timeZone = Calendar.getInstance().getTimeZone().getID();
|
||||
this.host = host;
|
||||
this.password = password;
|
||||
this.ignoreFatOrphanFiles = false;
|
||||
|
||||
// Set up the data source before creating the ingest stream
|
||||
try {
|
||||
image = SleuthkitJNI.addImageToDatabase(Case.getCurrentCase().getSleuthkitCase(),
|
||||
new String[]{imagePath}, sectorSize, timeZone, md5, sha1, sha256, deviceId, this.password, host);
|
||||
new String[]{imagePath}, sectorSize, timeZone, md5, sha1, sha256, deviceId, password, host);
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Error adding data source with path " + imagePath + " to database", ex);
|
||||
final List<String> errors = new ArrayList<>();
|
||||
@ -570,8 +612,10 @@ public class ImageDSProcessor implements DataSourceProcessor, AutoIngestDataSour
|
||||
return null;
|
||||
}
|
||||
|
||||
doAddImageProcess(deviceId, dataSourcePath.toString(), sectorSize, timeZone, ignoreFatOrphanFiles, null, null, null, null, progressMonitor, callBack);
|
||||
doAddImageProcess(deviceId, dataSourcePath.toString(), sectorSize, timeZone, ignoreFatOrphanFiles, null, null, null, password, progressMonitor, callBack);
|
||||
|
||||
return ingestStream;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -136,7 +136,12 @@ public class LocalDiskDSProcessor implements DataSourceProcessor {
|
||||
*/
|
||||
@Override
|
||||
public void run(DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
|
||||
run(null, progressMonitor, callback);
|
||||
run(null, null, progressMonitor, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(Host host, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
|
||||
run(null, host, progressMonitor, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -155,7 +160,7 @@ public class LocalDiskDSProcessor implements DataSourceProcessor {
|
||||
* to return results.
|
||||
*/
|
||||
@Override
|
||||
public void run(Host host, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
|
||||
public void run(String password, Host host, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
|
||||
deviceId = UUID.randomUUID().toString();
|
||||
drivePath = configPanel.getContentPath();
|
||||
sectorSize = configPanel.getSectorSize();
|
||||
@ -168,12 +173,13 @@ public class LocalDiskDSProcessor implements DataSourceProcessor {
|
||||
}
|
||||
|
||||
this.host = host;
|
||||
this.password = password;
|
||||
|
||||
Image image;
|
||||
try {
|
||||
image = SleuthkitJNI.addImageToDatabase(Case.getCurrentCase().getSleuthkitCase(),
|
||||
new String[]{drivePath}, sectorSize,
|
||||
timeZone, null, null, null, deviceId, this.host);
|
||||
timeZone, null, null, null, deviceId, this.password, this.host);
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Error adding local disk with path " + drivePath + " to database", ex);
|
||||
final List<String> errors = new ArrayList<>();
|
||||
@ -183,7 +189,7 @@ public class LocalDiskDSProcessor implements DataSourceProcessor {
|
||||
}
|
||||
|
||||
addDiskTask = new AddImageTask(
|
||||
new AddImageTask.ImageDetails(deviceId, image, sectorSize, timeZone, ignoreFatOrphanFiles, null, null, null, imageWriterSettings, password),
|
||||
new AddImageTask.ImageDetails(deviceId, image, sectorSize, timeZone, ignoreFatOrphanFiles, null, null, null, imageWriterSettings, this.password),
|
||||
progressMonitor,
|
||||
new StreamingAddDataSourceCallbacks(new DefaultIngestStream()),
|
||||
new StreamingAddImageTaskCallback(new DefaultIngestStream(), callback));
|
||||
@ -242,7 +248,7 @@ public class LocalDiskDSProcessor implements DataSourceProcessor {
|
||||
try {
|
||||
image = SleuthkitJNI.addImageToDatabase(Case.getCurrentCase().getSleuthkitCase(),
|
||||
new String[]{drivePath}, sectorSize,
|
||||
timeZone, null, null, null, deviceId);
|
||||
timeZone, null, null, null, deviceId, this.password, null);
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Error adding local disk with path " + drivePath + " to database", ex);
|
||||
final List<String> errors = new ArrayList<>();
|
||||
@ -251,7 +257,7 @@ public class LocalDiskDSProcessor implements DataSourceProcessor {
|
||||
return;
|
||||
}
|
||||
|
||||
addDiskTask = new AddImageTask(new AddImageTask.ImageDetails(deviceId, image, sectorSize, timeZone, ignoreFatOrphanFiles, null, null, null, imageWriterSettings, password),
|
||||
addDiskTask = new AddImageTask(new AddImageTask.ImageDetails(deviceId, image, sectorSize, timeZone, ignoreFatOrphanFiles, null, null, null, imageWriterSettings, this.password),
|
||||
progressMonitor,
|
||||
new StreamingAddDataSourceCallbacks(new DefaultIngestStream()),
|
||||
new StreamingAddImageTaskCallback(new DefaultIngestStream(), callback));
|
||||
|
@ -49,7 +49,9 @@ class CommandLineCommand {
|
||||
DATA_SOURCE_PATH,
|
||||
DATA_SOURCE_ID,
|
||||
INGEST_PROFILE_NAME,
|
||||
REPORT_PROFILE_NAME;
|
||||
REPORT_PROFILE_NAME,
|
||||
BITLOCKER_KEY,
|
||||
;
|
||||
}
|
||||
|
||||
private final CommandType type;
|
||||
|
@ -198,7 +198,8 @@ public class CommandLineIngestManager extends CommandLineManager {
|
||||
}
|
||||
|
||||
String dataSourcePath = inputs.get(CommandLineCommand.InputType.DATA_SOURCE_PATH.name());
|
||||
dataSource = new AutoIngestDataSource(UUID.randomUUID().toString(), Paths.get(dataSourcePath));
|
||||
String password = inputs.get(CommandLineCommand.InputType.BITLOCKER_KEY.name());
|
||||
dataSource = new AutoIngestDataSource(UUID.randomUUID().toString(), Paths.get(dataSourcePath), password);
|
||||
runDataSourceProcessor(caseForJob, dataSource);
|
||||
|
||||
String outputDirPath = getOutputDirPath(caseForJob);
|
||||
@ -406,7 +407,7 @@ public class CommandLineIngestManager extends CommandLineManager {
|
||||
// Get an ordered list of data source processors to try
|
||||
List<AutoIngestDataSourceProcessor> validDataSourceProcessors;
|
||||
try {
|
||||
validDataSourceProcessors = DataSourceProcessorUtility.getOrderedListOfDataSourceProcessors(dataSource.getPath());
|
||||
validDataSourceProcessors = DataSourceProcessorUtility.getOrderedListOfDataSourceProcessors(dataSource.getPath(), dataSource.getPassword());
|
||||
} catch (AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Exception while determining best data source processor for {0}", dataSource.getPath());
|
||||
// rethrow the exception.
|
||||
@ -429,7 +430,7 @@ public class CommandLineIngestManager extends CommandLineManager {
|
||||
DataSourceProcessorCallback callBack = new AddDataSourceCallback(caseForJob, dataSource, taskId, ingestLock);
|
||||
caseForJob.notifyAddingDataSource(taskId);
|
||||
LOGGER.log(Level.INFO, "Identified data source type for {0} as {1}", new Object[]{dataSource.getPath(), selectedProcessor.getDataSourceType()});
|
||||
selectedProcessor.process(dataSource.getDeviceId(), dataSource.getPath(), progressMonitor, callBack);
|
||||
selectedProcessor.process(dataSource.getDeviceId(), dataSource.getPath(), dataSource.getPassword(), null, progressMonitor, callBack);
|
||||
ingestLock.wait();
|
||||
|
||||
// at this point we got the content object(s) from the current DSP.
|
||||
|
@ -30,6 +30,7 @@ import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.netbeans.api.sendopts.CommandException;
|
||||
import org.netbeans.spi.sendopts.Env;
|
||||
@ -52,6 +53,7 @@ public class CommandLineOptionProcessor extends OptionProcessor {
|
||||
private final Option dataSourcePathOption = Option.requiredArgument('s', "dataSourcePath");
|
||||
private final Option dataSourceObjectIdOption = Option.requiredArgument('i', "dataSourceObjectId");
|
||||
private final Option addDataSourceCommandOption = Option.withoutArgument('a', "addDataSource");
|
||||
private final Option bitlockerKeyCommandOption = Option.withoutArgument('k', "key");
|
||||
private final Option runIngestCommandOption = Option.optionalArgument('r', "runIngest");
|
||||
private final Option listAllDataSourcesCommandOption = Option.withoutArgument('l', "listAllDataSources");
|
||||
private final Option generateReportsOption = Option.optionalArgument('g', "generateReports");
|
||||
@ -81,20 +83,21 @@ public class CommandLineOptionProcessor extends OptionProcessor {
|
||||
|
||||
@Override
|
||||
protected Set<Option> getOptions() {
|
||||
Set<Option> set = new HashSet<>();
|
||||
set.add(createCaseCommandOption);
|
||||
set.add(caseNameOption);
|
||||
set.add(caseTypeOption);
|
||||
set.add(caseBaseDirOption);
|
||||
set.add(dataSourcePathOption);
|
||||
set.add(addDataSourceCommandOption);
|
||||
set.add(dataSourceObjectIdOption);
|
||||
set.add(runIngestCommandOption);
|
||||
set.add(listAllDataSourcesCommandOption);
|
||||
set.add(generateReportsOption);
|
||||
set.add(listAllIngestProfileOption);
|
||||
set.add(defaultArgument);
|
||||
return set;
|
||||
return Set.of(
|
||||
createCaseCommandOption,
|
||||
caseNameOption,
|
||||
caseTypeOption,
|
||||
caseBaseDirOption,
|
||||
dataSourcePathOption,
|
||||
addDataSourceCommandOption,
|
||||
bitlockerKeyCommandOption,
|
||||
dataSourceObjectIdOption,
|
||||
runIngestCommandOption,
|
||||
listAllDataSourcesCommandOption,
|
||||
generateReportsOption,
|
||||
listAllIngestProfileOption,
|
||||
defaultArgument
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -203,6 +206,9 @@ public class CommandLineOptionProcessor extends OptionProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
String[] keysArgs = values.get(bitlockerKeyCommandOption);
|
||||
String bitlockerKey = ArrayUtils.isNotEmpty(keysArgs) ? keysArgs[0] : null;
|
||||
|
||||
String dataSourceId = "";
|
||||
if (values.containsKey(dataSourceObjectIdOption)) {
|
||||
|
||||
@ -247,6 +253,11 @@ public class CommandLineOptionProcessor extends OptionProcessor {
|
||||
newCommand.addInputValue(CommandLineCommand.InputType.CASE_NAME.name(), inputCaseName);
|
||||
newCommand.addInputValue(CommandLineCommand.InputType.CASES_BASE_DIR_PATH.name(), caseBaseDir);
|
||||
newCommand.addInputValue(CommandLineCommand.InputType.DATA_SOURCE_PATH.name(), dataSourcePath);
|
||||
|
||||
if (bitlockerKey != null) {
|
||||
newCommand.addInputValue(CommandLineCommand.InputType.BITLOCKER_KEY.name(), bitlockerKey);
|
||||
}
|
||||
|
||||
commands.add(newCommand);
|
||||
runFromCommandLine(true);
|
||||
}
|
||||
|
@ -129,6 +129,27 @@ public interface DataSourceProcessor {
|
||||
run(progressMonitor, callback);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds a data source to the case database using a background task in a
|
||||
* separate thread and the settings provided by the selection and
|
||||
* configuration panel. Returns as soon as the background task is started.
|
||||
* The background task uses a callback object to signal task completion and
|
||||
* return results.
|
||||
*
|
||||
* This method should not be called unless isPanelValid returns true.
|
||||
*
|
||||
* @param password The password
|
||||
* @param host Host for the data source.
|
||||
* @param progressMonitor Progress monitor that will be used by the
|
||||
* background task to report progress.
|
||||
* @param callback Callback that will be used by the background task
|
||||
* to return results.
|
||||
*/
|
||||
default void run(String password, Host host, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
|
||||
run(host, progressMonitor, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a data source to the case database using a background task in a
|
||||
* separate thread and the settings provided by the selection and
|
||||
@ -176,6 +197,31 @@ public interface DataSourceProcessor {
|
||||
runWithIngestStream(settings, progress, callBack);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a data source to the case database using a background task in a
|
||||
* separate thread and the settings provided by the selection and
|
||||
* configuration panel. Files found during ingest will be sent directly to
|
||||
* the IngestStream provided. Returns as soon as the background task is
|
||||
* started. The background task uses a callback object to signal task
|
||||
* completion and return results.
|
||||
*
|
||||
* This method should not be called unless isPanelValid returns true, and
|
||||
* should only be called for DSPs that support ingest streams. The ingest
|
||||
* settings must be complete before calling this method.
|
||||
*
|
||||
* @param password The password to decrypt the data source.
|
||||
* @param host Host for this data source.
|
||||
* @param settings The ingest job settings.
|
||||
* @param progress Progress monitor that will be used by the background task
|
||||
* to report progress.
|
||||
* @param callBack Callback that will be used by the background task to
|
||||
* return results.
|
||||
*/
|
||||
default void runWithIngestStream(String password, Host host, IngestJobSettings settings, DataSourceProcessorProgressMonitor progress,
|
||||
DataSourceProcessorCallback callBack) {
|
||||
runWithIngestStream(host, settings, progress, callBack);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this DSP supports ingest streams.
|
||||
*
|
||||
|
@ -30,13 +30,20 @@ public class AutoIngestDataSource {
|
||||
|
||||
private final String deviceId;
|
||||
private final Path path;
|
||||
private final String password;
|
||||
private DataSourceProcessorResult resultCode;
|
||||
private List<String> errorMessages;
|
||||
private List<Content> content;
|
||||
|
||||
public AutoIngestDataSource(String deviceId, Path path) {
|
||||
|
||||
public AutoIngestDataSource(String deviceId, Path path, String password) {
|
||||
this.deviceId = deviceId;
|
||||
this.path = path;
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public AutoIngestDataSource(String deviceId, Path path) {
|
||||
this(deviceId, path, null);
|
||||
}
|
||||
|
||||
public String getDeviceId() {
|
||||
@ -47,6 +54,13 @@ public class AutoIngestDataSource {
|
||||
return this.path;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The password to decrypt the data source.
|
||||
*/
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public synchronized void setDataSourceProcessorOutput(DataSourceProcessorResult result, List<String> errorMessages, List<Content> content) {
|
||||
this.resultCode = result;
|
||||
this.errorMessages = new ArrayList<>(errorMessages);
|
||||
|
@ -50,6 +50,25 @@ public interface AutoIngestDataSourceProcessor extends DataSourceProcessor {
|
||||
*/
|
||||
int canProcess(Path dataSourcePath) throws AutoIngestDataSourceProcessorException;
|
||||
|
||||
/**
|
||||
* Indicates whether the DataSourceProcessor is capable of processing the
|
||||
* data source. Returns a confidence value. Method can throw an exception
|
||||
* for a system level problem. The exception should not be thrown for an issue
|
||||
* related to bad input data.
|
||||
*
|
||||
* @param dataSourcePath Path to the data source.
|
||||
* @param password The password to decrypt the data source.
|
||||
* @return Confidence value. Values between 0 and 100 are recommended. Zero
|
||||
* or less means the data source is not supported by the
|
||||
* DataSourceProcessor. Value of 100 indicates high certainty in
|
||||
* being able to process the data source.
|
||||
* @throws org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException
|
||||
*/
|
||||
default int canProcess(Path dataSourcePath, String password) throws AutoIngestDataSourceProcessorException {
|
||||
return canProcess(dataSourcePath);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds a data source to the case database using a background task in a
|
||||
* separate thread by calling DataSourceProcessor.run() method. Returns as
|
||||
@ -91,6 +110,30 @@ public interface AutoIngestDataSourceProcessor extends DataSourceProcessor {
|
||||
process(deviceId, dataSourcePath, progressMonitor, callBack);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a data source to the case database using a background task in a
|
||||
* separate thread by calling DataSourceProcessor.run() method. Returns as
|
||||
* soon as the background task is started. The background task uses a
|
||||
* callback object to signal task completion and return results. Method can
|
||||
* throw an exception for a system level problem. The exception should not
|
||||
* be thrown for an issue related to bad input data.
|
||||
*
|
||||
* @param deviceId An ASCII-printable identifier for the device
|
||||
* associated with the data source that is intended
|
||||
* to be unique across multiple cases (e.g., a UUID).
|
||||
* @param dataSourcePath Path to the data source.
|
||||
* @param password The password to decrypt the datasource.
|
||||
* @param host Host for this data source.
|
||||
* @param progressMonitor Progress monitor that will be used by the
|
||||
* background task to report progress.
|
||||
* @param callBack Callback that will be used by the background task
|
||||
* to return results.
|
||||
*/
|
||||
default void process(String deviceId, Path dataSourcePath, String password, Host host, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack) {
|
||||
process(deviceId, dataSourcePath, progressMonitor, callBack);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds a data source to the case database using a background task in a
|
||||
* separate thread by calling DataSourceProcessor.run() method. Returns as
|
||||
@ -140,6 +183,33 @@ public interface AutoIngestDataSourceProcessor extends DataSourceProcessor {
|
||||
return processWithIngestStream(deviceId, dataSourcePath, settings, progressMonitor, callBack);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a data source to the case database using a background task in a
|
||||
* separate thread by calling DataSourceProcessor.run() method. Returns as
|
||||
* soon as the background task is started. The background task uses a
|
||||
* callback object to signal task completion and return results. Method can
|
||||
* throw an exception for a system level problem. The exception should not
|
||||
* be thrown for an issue related to bad input data.
|
||||
*
|
||||
* @param deviceId An ASCII-printable identifier for the device
|
||||
* associated with the data source that is intended
|
||||
* to be unique across multiple cases (e.g., a UUID).
|
||||
* @param dataSourcePath Path to the data source.
|
||||
* @param password The password to decrypt the datasource.
|
||||
* @param host The host for this data source.
|
||||
* @param settings The ingest job settings.
|
||||
* @param progressMonitor Progress monitor that will be used by the
|
||||
* background task to report progress.
|
||||
* @param callBack Callback that will be used by the background task
|
||||
* to return results.
|
||||
*
|
||||
* @return The new ingest stream or null if an error occurred. Errors will be handled by the callback.
|
||||
*/
|
||||
default IngestStream processWithIngestStream(String deviceId, Path dataSourcePath, String password, Host host, IngestJobSettings settings, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack) {
|
||||
return processWithIngestStream(deviceId, dataSourcePath, settings, progressMonitor, callBack);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A custom exception for the use of AutomatedIngestDataSourceProcessor.
|
||||
*/
|
||||
|
@ -49,9 +49,27 @@ public class DataSourceProcessorUtility {
|
||||
* org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException
|
||||
*/
|
||||
public static Map<AutoIngestDataSourceProcessor, Integer> getDataSourceProcessorForFile(Path dataSourcePath, Collection<? extends AutoIngestDataSourceProcessor> processorCandidates) throws AutoIngestDataSourceProcessorException {
|
||||
return getDataSourceProcessorForFile(dataSourcePath, null, processorCandidates);
|
||||
}
|
||||
|
||||
/**
|
||||
* A utility method to find all Data Source Processors (DSP) that are able
|
||||
* to process the input data source. Only the DSPs that implement
|
||||
* AutoIngestDataSourceProcessor interface are used.
|
||||
*
|
||||
* @param dataSourcePath Full path to the data source
|
||||
* @param password The password to decrypt the data source.
|
||||
* @param processorCandidates Possible DSPs that can handle the data source
|
||||
*
|
||||
* @return Hash map of all DSPs that can process the data source along with
|
||||
* their confidence score
|
||||
* @throws
|
||||
* org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException
|
||||
*/
|
||||
public static Map<AutoIngestDataSourceProcessor, Integer> getDataSourceProcessorForFile(Path dataSourcePath, String password, Collection<? extends AutoIngestDataSourceProcessor> processorCandidates) throws AutoIngestDataSourceProcessorException {
|
||||
Map<AutoIngestDataSourceProcessor, Integer> validDataSourceProcessorsMap = new HashMap<>();
|
||||
for (AutoIngestDataSourceProcessor processor : processorCandidates) {
|
||||
int confidence = processor.canProcess(dataSourcePath);
|
||||
int confidence = processor.canProcess(dataSourcePath, password);
|
||||
if (confidence > 0) {
|
||||
validDataSourceProcessorsMap.put(processor, confidence);
|
||||
}
|
||||
@ -76,9 +94,29 @@ public class DataSourceProcessorUtility {
|
||||
* org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException
|
||||
*/
|
||||
public static List<AutoIngestDataSourceProcessor> getOrderedListOfDataSourceProcessors(Path dataSourcePath) throws AutoIngestDataSourceProcessorException {
|
||||
return getOrderedListOfDataSourceProcessors(dataSourcePath, (String) null);
|
||||
}
|
||||
|
||||
/**
|
||||
* A utility method to find all Data Source Processors (DSP) that are able
|
||||
* to process the input data source. Only the DSPs that implement
|
||||
* AutoIngestDataSourceProcessor interface are used. Returns ordered list of
|
||||
* data source processors. DSPs are ordered in descending order from highest
|
||||
* confidence to lowest.
|
||||
*
|
||||
* @param dataSourcePath Full path to the data source
|
||||
* @param password The password to decrypt the data source.
|
||||
*
|
||||
* @return Ordered list of data source processors. DSPs are ordered in
|
||||
* descending order from highest confidence to lowest.
|
||||
*
|
||||
* @throws
|
||||
* org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException
|
||||
*/
|
||||
public static List<AutoIngestDataSourceProcessor> getOrderedListOfDataSourceProcessors(Path dataSourcePath, String password) throws AutoIngestDataSourceProcessorException {
|
||||
// lookup all AutomatedIngestDataSourceProcessors
|
||||
Collection<? extends AutoIngestDataSourceProcessor> processorCandidates = Lookup.getDefault().lookupAll(AutoIngestDataSourceProcessor.class);
|
||||
return getOrderedListOfDataSourceProcessors(dataSourcePath, processorCandidates);
|
||||
return getOrderedListOfDataSourceProcessors(dataSourcePath, password, processorCandidates);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -98,6 +136,27 @@ public class DataSourceProcessorUtility {
|
||||
* org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException
|
||||
*/
|
||||
public static List<AutoIngestDataSourceProcessor> getOrderedListOfDataSourceProcessors(Path dataSourcePath, Collection<? extends AutoIngestDataSourceProcessor> processorCandidates) throws AutoIngestDataSourceProcessorException {
|
||||
return getOrderedListOfDataSourceProcessors(dataSourcePath, null, processorCandidates);
|
||||
}
|
||||
|
||||
/**
|
||||
* A utility method to find all Data Source Processors (DSP) that are able
|
||||
* to process the input data source. Only the DSPs that implement
|
||||
* AutoIngestDataSourceProcessor interface are used. Returns ordered list of
|
||||
* data source processors. DSPs are ordered in descending order from highest
|
||||
* confidence to lowest.
|
||||
*
|
||||
* @param dataSourcePath Full path to the data source
|
||||
* @param password The password to decrypt the data source.
|
||||
* @param processorCandidates Collection of AutoIngestDataSourceProcessor objects to use
|
||||
*
|
||||
* @return Ordered list of data source processors. DSPs are ordered in
|
||||
* descending order from highest confidence to lowest.
|
||||
*
|
||||
* @throws
|
||||
* org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException
|
||||
*/
|
||||
public static List<AutoIngestDataSourceProcessor> getOrderedListOfDataSourceProcessors(Path dataSourcePath, String password, Collection<? extends AutoIngestDataSourceProcessor> processorCandidates) throws AutoIngestDataSourceProcessorException {
|
||||
Map<AutoIngestDataSourceProcessor, Integer> validDataSourceProcessorsMap = getDataSourceProcessorForFile(dataSourcePath, processorCandidates);
|
||||
return orderDataSourceProcessorsByConfidence(validDataSourceProcessorsMap);
|
||||
}
|
||||
|
@ -2573,7 +2573,8 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen
|
||||
return null;
|
||||
}
|
||||
String deviceId = manifest.getDeviceId();
|
||||
return new AutoIngestDataSource(deviceId, dataSourcePath);
|
||||
String password = manifest.getPassword();
|
||||
return new AutoIngestDataSource(deviceId, dataSourcePath, password);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2603,7 +2604,7 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen
|
||||
// Get an ordered list of data source processors to try
|
||||
List<AutoIngestDataSourceProcessor> validDataSourceProcessors;
|
||||
try {
|
||||
validDataSourceProcessors = DataSourceProcessorUtility.getOrderedListOfDataSourceProcessors(dataSource.getPath());
|
||||
validDataSourceProcessors = DataSourceProcessorUtility.getOrderedListOfDataSourceProcessors(dataSource.getPath(), dataSource.getPassword());
|
||||
} catch (AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException ex) {
|
||||
sysLogger.log(Level.SEVERE, "Exception while determining best data source processor for {0}", dataSource.getPath());
|
||||
// rethrow the exception. It will get caught & handled upstream and will result in AIM auto-pause.
|
||||
@ -2641,7 +2642,7 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen
|
||||
jobLogger.logIngestJobSettingsErrors();
|
||||
throw new AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException("Error(s) in ingest job settings for " + manifestPath);
|
||||
}
|
||||
currentIngestStream = selectedProcessor.processWithIngestStream(dataSource.getDeviceId(), dataSource.getPath(), ingestJobSettings, progressMonitor, callBack);
|
||||
currentIngestStream = selectedProcessor.processWithIngestStream(dataSource.getDeviceId(), dataSource.getPath(), dataSource.getPassword(), null, ingestJobSettings, progressMonitor, callBack);
|
||||
if (currentIngestStream == null) {
|
||||
// Either there was a failure to add the data source object to the database or the ingest settings were bad.
|
||||
// An error in the ingest settings is the more likely scenario.
|
||||
@ -2651,7 +2652,7 @@ final class AutoIngestManager extends Observable implements PropertyChangeListen
|
||||
throw new AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException("Error initializing processing for " + manifestPath + ", probably due to an ingest settings error");
|
||||
}
|
||||
} else {
|
||||
selectedProcessor.process(dataSource.getDeviceId(), dataSource.getPath(), progressMonitor, callBack);
|
||||
selectedProcessor.process(dataSource.getDeviceId(), dataSource.getPath(), dataSource.getPassword(), null, progressMonitor, callBack);
|
||||
}
|
||||
ingestLock.wait();
|
||||
|
||||
|
@ -45,6 +45,7 @@ public final class AutopsyManifestFileParser implements ManifestFileParser {
|
||||
private static final String MANIFEST_FILE_NAME_SIGNATURE = "_MANIFEST.XML";
|
||||
private static final String ROOT_ELEM_TAG_NAME = "AutopsyManifest";
|
||||
private static final String CASE_NAME_XPATH = "/AutopsyManifest/CaseName/text()";
|
||||
private static final String PASSWORD_XPATH = "/AutopsyManifest/Password/text()";
|
||||
private static final String DEVICE_ID_XPATH = "/AutopsyManifest/DeviceId/text()";
|
||||
private static final String DATA_SOURCE_NAME_XPATH = "/AutopsyManifest/DataSource/text()";
|
||||
private static final Logger logger = Logger.getLogger(AutopsyManifestFileParser.class.getName());
|
||||
@ -102,7 +103,10 @@ public final class AutopsyManifestFileParser implements ManifestFileParser {
|
||||
}
|
||||
Path dataSourcePath = filePath.getParent().resolve(dataSourceName);
|
||||
|
||||
return new Manifest(filePath, dateFileCreated, caseName, deviceId, dataSourcePath, new HashMap<>());
|
||||
expr = xpath.compile(PASSWORD_XPATH);
|
||||
String password = (String) expr.evaluate(doc, XPathConstants.STRING);
|
||||
|
||||
return new Manifest(filePath, dateFileCreated, caseName, deviceId, dataSourcePath, password, new HashMap<>());
|
||||
} catch (Exception ex) {
|
||||
throw new ManifestFileParserException(String.format("Error parsing manifest %s", filePath), ex);
|
||||
} finally {
|
||||
|
@ -42,9 +42,14 @@ public final class Manifest implements Serializable {
|
||||
private final String caseName;
|
||||
private final String deviceId;
|
||||
private final String dataSourceFileName;
|
||||
private final String password;
|
||||
private final Map<String, String> manifestProperties;
|
||||
|
||||
public Manifest(Path manifestFilePath, Date dateFileCreated, String caseName, String deviceId, Path dataSourcePath, Map<String, String> manifestProperties) {
|
||||
this(manifestFilePath, dateFileCreated, caseName, deviceId, dataSourcePath, null, manifestProperties);
|
||||
}
|
||||
|
||||
public Manifest(Path manifestFilePath, Date dateFileCreated, String caseName, String deviceId, Path dataSourcePath, String password, Map<String, String> manifestProperties) {
|
||||
this.filePathString = manifestFilePath.toString();
|
||||
this.filePath = Paths.get(filePathString);
|
||||
|
||||
@ -60,6 +65,7 @@ public final class Manifest implements Serializable {
|
||||
this.dataSourcePath = Paths.get("");
|
||||
dataSourceFileName = "";
|
||||
}
|
||||
this.password = password;
|
||||
this.manifestProperties = new HashMap<>(manifestProperties);
|
||||
}
|
||||
|
||||
@ -91,6 +97,13 @@ public final class Manifest implements Serializable {
|
||||
return dataSourcePath;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The password to decrypt the data source (may be null).
|
||||
*/
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public String getDataSourceFileName() {
|
||||
return dataSourceFileName;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user