From 5d527e712c56ed7f0c11c0639c2c2303da73e803 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Thu, 16 Jan 2025 20:24:35 -0500 Subject: [PATCH] updates for auto ingest --- .../CommandLineOptionProcessor.java | 2 +- .../autopsy/coreutils/DataSourceUtils.java | 27 ++++++++++--- .../DataSourceProcessorUtility.java | 2 +- .../autoingest/AutoIngestJob.java | 28 ++++++++++++- .../autoingest/AutoIngestJobNodeData.java | 40 ++++++++++++++++++- 5 files changed, 88 insertions(+), 11 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/commandlineingest/CommandLineOptionProcessor.java b/Core/src/org/sleuthkit/autopsy/commandlineingest/CommandLineOptionProcessor.java index 1d4b55f49a..dc2a84e727 100755 --- a/Core/src/org/sleuthkit/autopsy/commandlineingest/CommandLineOptionProcessor.java +++ b/Core/src/org/sleuthkit/autopsy/commandlineingest/CommandLineOptionProcessor.java @@ -53,7 +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 bitlockerKeyCommandOption = Option.requiredArgument('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"); diff --git a/Core/src/org/sleuthkit/autopsy/coreutils/DataSourceUtils.java b/Core/src/org/sleuthkit/autopsy/coreutils/DataSourceUtils.java index 707c6b6645..5fe577a896 100644 --- a/Core/src/org/sleuthkit/autopsy/coreutils/DataSourceUtils.java +++ b/Core/src/org/sleuthkit/autopsy/coreutils/DataSourceUtils.java @@ -22,13 +22,15 @@ import org.sleuthkit.datamodel.SleuthkitJNI; import java.io.IOException; import java.nio.file.Path; import java.text.MessageFormat; +import java.util.logging.Level; import org.apache.commons.lang3.StringUtils; /** * Utility methods for working with data sources. */ public class DataSourceUtils { - + private static final Logger logger = Logger.getLogger(DataSourceUtils.class.getName()); + /** * Calls TSK to determine whether a * potential data source has a file system. @@ -44,24 +46,37 @@ public class DataSourceUtils { return SleuthkitJNI.isImageSupported(dataSourcePath.toString()); } + /** + * Calls TSK to determine whether a + * potential data source has a file system. + * + * @param dataSourcePath The path to the data source. + * @param password The password to decrypt the image. + * + * @return True or false. + * + * @throws IOException if an error occurs while trying to determine if the + * data source has a file system. + */ public static boolean imageHasFileSystem(Path dataSourcePath, String password) throws IOException { try { -// LOGGER.info("Testing if disk image {} can be opened", hostPath); SleuthkitJNI.TestOpenImageResult openImageResult = SleuthkitJNI.testOpenImage(dataSourcePath.toString(), password); - if (!openImageResult.wasSuccessful()) { + if (openImageResult.wasSuccessful()) { + return true; + } else { String message = MessageFormat.format("An error occurred while opening {0}: {1}", dataSourcePath.toString(), openImageResult == null || StringUtils.isBlank(openImageResult.getMessage()) ? "" : openImageResult.getMessage()); + logger.log(Level.INFO, message); return false; } } catch (Throwable ex) { String message = "An error occurred while opening " + dataSourcePath.toString(); + logger.log(Level.WARNING, message); return false; - } - return SleuthkitJNI.isImageSupported(dataSourcePath.toString()); - + } } } diff --git a/Core/src/org/sleuthkit/autopsy/datasourceprocessors/DataSourceProcessorUtility.java b/Core/src/org/sleuthkit/autopsy/datasourceprocessors/DataSourceProcessorUtility.java index 0d08545e7e..d96a0121a5 100644 --- a/Core/src/org/sleuthkit/autopsy/datasourceprocessors/DataSourceProcessorUtility.java +++ b/Core/src/org/sleuthkit/autopsy/datasourceprocessors/DataSourceProcessorUtility.java @@ -157,7 +157,7 @@ public class DataSourceProcessorUtility { * org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException */ public static List getOrderedListOfDataSourceProcessors(Path dataSourcePath, String password, Collection processorCandidates) throws AutoIngestDataSourceProcessorException { - Map validDataSourceProcessorsMap = getDataSourceProcessorForFile(dataSourcePath, processorCandidates); + Map validDataSourceProcessorsMap = getDataSourceProcessorForFile(dataSourcePath, password, processorCandidates); return orderDataSourceProcessorsByConfidence(validDataSourceProcessorsMap); } diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJob.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJob.java index b03253b984..6b5d5cfb78 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJob.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJob.java @@ -105,6 +105,12 @@ final class AutoIngestJob implements Comparable, IngestProgressSn * Version 4 fields. */ private boolean ocrEnabled; + + /** + * Version 5 fields + */ + @GuardedBy("this") + private String password; /** * Constructs a new automated ingest job. All job state not specified in the @@ -166,7 +172,7 @@ final class AutoIngestJob implements Comparable, IngestProgressSn /* * Version 0 fields. */ - this.manifest = new Manifest(nodeData.getManifestFilePath(), nodeData.getManifestFileDate(), nodeData.getCaseName(), nodeData.getDeviceId(), nodeData.getDataSourcePath(), Collections.emptyMap()); + this.manifest = new Manifest(nodeData.getManifestFilePath(), nodeData.getManifestFileDate(), nodeData.getCaseName(), nodeData.getDeviceId(), nodeData.getDataSourcePath(), nodeData.getPassword(), Collections.emptyMap()); this.nodeName = nodeData.getProcessingHostName(); this.caseDirectoryPath = nodeData.getCaseDirectoryPath().toString(); this.priority = nodeData.getPriority(); @@ -204,6 +210,11 @@ final class AutoIngestJob implements Comparable, IngestProgressSn */ this.ocrEnabled = nodeData.getOcrEnabled(); + /** + * Version 5 fields + */ + this.password = nodeData.getPassword(); + } catch (Exception ex) { throw new AutoIngestJobException(String.format("Error creating automated ingest job"), ex); } @@ -282,6 +293,21 @@ final class AutoIngestJob implements Comparable, IngestProgressSn this.ocrEnabled = enabled; } + /** + * @return The password to decrypt the image. + */ + synchronized String getPassword() { + return password; + } + + /** + * @param password The password to decrypt the image. + */ + synchronized void setPassword(String password) { + this.password = password; + } + + /** * Sets the processing stage of the job. The start date/time for the stage * is set when the stage is set. diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobNodeData.java b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobNodeData.java index 5e9ab8955d..bc4cae3550 100644 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobNodeData.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/autoingest/AutoIngestJobNodeData.java @@ -24,6 +24,7 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.Date; import javax.lang.model.type.TypeKind; +import org.apache.commons.lang3.StringUtils; /** * An object that converts auto ingest job data for an auto ingest job @@ -31,7 +32,7 @@ import javax.lang.model.type.TypeKind; */ final class AutoIngestJobNodeData { - private static final int CURRENT_VERSION = 3; + private static final int CURRENT_VERSION = 4; private static final int DEFAULT_PRIORITY = 0; /* @@ -84,6 +85,12 @@ final class AutoIngestJobNodeData { */ private boolean ocrEnabled; + /** + * Version 4 fields. + */ + private String password; // password to decrypt the image + + /** * Gets the current version of the auto ingest job coordination service node * data. @@ -121,6 +128,7 @@ final class AutoIngestJobNodeData { setProcessingStageDetails(job.getProcessingStageDetails()); setDataSourceSize(job.getDataSourceSize()); setOcrEnabled(job.getOcrEnabled()); + setPassword(manifest.getPassword()); } /** @@ -157,6 +165,7 @@ final class AutoIngestJobNodeData { this.processingStageDetailsStartDate = 0L; this.dataSourceSize = 0L; this.ocrEnabled = false; + this.password = ""; /* * Get fields from node data. @@ -207,6 +216,13 @@ final class AutoIngestJobNodeData { int ocrFlag = buffer.getInt(); this.ocrEnabled = (1 == ocrFlag); } + + if (buffer.hasRemaining()) { + /* + * Get version 4 fields. + */ + setPassword(getStringFromBuffer(buffer, TypeKind.SHORT)); + } } catch (BufferUnderflowException ex) { throw new InvalidDataException("Node data is incomplete", ex); @@ -471,6 +487,22 @@ final class AutoIngestJobNodeData { } } + /** + * @return The password to decrypt the image. Empty indicates no password. + */ + public String getPassword() { + return password; + } + + /** + * @param password The password to decrypt the image. + */ + public void setPassword(String password) { + this.password = StringUtils.defaultString(password); + } + + + /** * Get the processing stage of the job. * @@ -603,7 +635,11 @@ final class AutoIngestJobNodeData { if (this.version >= 3) { buffer.putInt(this.ocrEnabled ? 1 : 0); - } + } + + if (this.version >= 4) { + putStringIntoBuffer(this.password, buffer, TypeKind.SHORT); + } } // Prepare the array