/* * Autopsy Forensic Browser * * Copyright 2015 Basis Technology Corp. * Contact: carrier <at> sleuthkit <dot> org * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.sleuthkit.autopsy.experimental.configuration; import java.util.Base64; import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.PBEKeySpec; import javax.crypto.spec.PBEParameterSpec; import org.sleuthkit.autopsy.core.UserPreferencesException; import org.sleuthkit.autopsy.coreutils.ModuleSettings; /** * Provides convenient access to a Preferences node for auto ingest user preferences * with default values. */ public final class AutoIngestUserPreferences { public enum SelectedMode { STANDALONE, AUTOMATED, REVIEW }; private static final String SETTINGS_PROPERTIES = "AutoIngest"; private static final String MODE = "AutopsyMode"; // NON-NLS private static final String JOIN_AUTO_MODE_CLUSTER = "JoinAutoModeCluster"; // NON-NLS private static final String AUTO_MODE_IMAGES_FOLDER = "AutoModeImageFolder"; // NON-NLS private static final String AUTO_MODE_RESULTS_FOLDER = "AutoModeResultsFolder"; // NON-NLS private static final String SHARED_CONFIG_FOLDER = "SharedSettingsFolder"; // NON-NLS private static final String SHARED_CONFIG_ENABLED = "SharedSettingsEnabled"; // NON-NLS private static final String SHARED_CONFIG_MASTER = "SharedSettingsMaster"; // NON-NLS private static final String AUTO_MODE_CONTEXT_STRING = "AutoModeContext"; // NON-NLS private static final String SLEEP_BETWEEN_CASES_TIME = "SleepBetweenCasesTime"; // NON-NLS private static final String SHOW_TOOLS_WARNING = "ShowToolsWarning"; // NON-NLS private static final String MAX_NUM_TIMES_TO_PROCESS_IMAGE = "MaxNumTimesToAttemptToProcessImage"; // NON-NLS private static final String MAX_CONCURRENT_NODES_FOR_ONE_CASE = "MaxConcurrentNodesForOneCase"; // NON-NLS private static final String STATUS_DATABASE_LOGGING_ENABLED = "StatusDatabaseLoggingEnabled"; // NON-NLS private static final String LOGGING_DB_HOSTNAME_OR_IP = "LoggingHostnameOrIP"; // NON-NLS private static final String LOGGING_PORT = "LoggingPort"; // NON-NLS private static final String LOGGING_USERNAME = "LoggingUsername"; // NON-NLS private static final String LOGGING_PASSWORD = "LoggingPassword"; // NON-NLS private static final String LOGGING_DATABASE_NAME = "LoggingDatabaseName"; // NON-NLS private static final String INPUT_SCAN_INTERVAL_TIME = "IntervalBetweenInputScan"; // NON-NLS // Prevent instantiation. private AutoIngestUserPreferences() { } /** * Get mode from persistent storage. * * @return SelectedMode Selected mode. */ public static SelectedMode getMode() { if (ModuleSettings.settingExists(SETTINGS_PROPERTIES, MODE)) { int ordinal = Integer.parseInt(ModuleSettings.getConfigSetting(SETTINGS_PROPERTIES, MODE)); return SelectedMode.values()[ordinal]; } return SelectedMode.STANDALONE; } /** * Set mode to persistent storage. * * @param mode Selected mode. */ public static void setMode(SelectedMode mode) { ModuleSettings.setConfigSetting(SETTINGS_PROPERTIES, MODE, Integer.toString(mode.ordinal())); } /** * Get "Join Automated Ingest Cluster" setting from persistent storage. * * @return SelectedMode Selected setting. */ public static boolean getJoinAutoModeCluster() { if (ModuleSettings.settingExists(SETTINGS_PROPERTIES, JOIN_AUTO_MODE_CLUSTER)) { return Boolean.parseBoolean(ModuleSettings.getConfigSetting(SETTINGS_PROPERTIES, JOIN_AUTO_MODE_CLUSTER)); } return false; } /** * Set "Join Automated Ingest Cluster" setting to persistent storage. * * @param join boolean value of whether to join auto ingest cluster or not */ public static void setJoinAutoModeCluster(boolean join) { ModuleSettings.setConfigSetting(SETTINGS_PROPERTIES, JOIN_AUTO_MODE_CLUSTER, Boolean.toString(join)); } /** * Get input folder for automated mode from persistent storage. * * @return String Selected input folder. */ public static String getAutoModeImageFolder() { if (ModuleSettings.settingExists(SETTINGS_PROPERTIES, AUTO_MODE_IMAGES_FOLDER)) { return ModuleSettings.getConfigSetting(SETTINGS_PROPERTIES, AUTO_MODE_IMAGES_FOLDER); } return ""; } /** * Set input image folder for automated mode from persistent storage. * * @param folder Selected input folder. */ public static void setAutoModeImageFolder(String folder) { ModuleSettings.setConfigSetting(SETTINGS_PROPERTIES, AUTO_MODE_IMAGES_FOLDER, folder); } /** * Get results folder for automated mode from persistent storage. * * @return String Selected output folder. */ public static String getAutoModeResultsFolder() { if (ModuleSettings.settingExists(SETTINGS_PROPERTIES, AUTO_MODE_RESULTS_FOLDER)) { return ModuleSettings.getConfigSetting(SETTINGS_PROPERTIES, AUTO_MODE_RESULTS_FOLDER); } return ""; } /** * Set results folder for automated mode from persistent storage. * * @param folder Selected output folder. */ public static void setAutoModeResultsFolder(String folder) { ModuleSettings.setConfigSetting(SETTINGS_PROPERTIES, AUTO_MODE_RESULTS_FOLDER, folder); } /** * Get shared config folder for automated mode from persistent * storage. * * @return String Selected settings folder. */ public static String getSharedConfigFolder() { if (ModuleSettings.settingExists(SETTINGS_PROPERTIES, SHARED_CONFIG_FOLDER)) { return ModuleSettings.getConfigSetting(SETTINGS_PROPERTIES, SHARED_CONFIG_FOLDER); } return ""; } /** * Set shared config folder for automated mode from persistent * storage. */ public static void setSharedConfigFolder(String folder) { ModuleSettings.setConfigSetting(SETTINGS_PROPERTIES, SHARED_CONFIG_FOLDER, folder); } /** * Get shared config checkbox state for automated mode from * persistent storage. * * @return Boolean true if shared settings are enabled. */ public static Boolean getSharedConfigEnabled() { if (ModuleSettings.settingExists(SETTINGS_PROPERTIES, SHARED_CONFIG_ENABLED)) { return Boolean.parseBoolean(ModuleSettings.getConfigSetting(SETTINGS_PROPERTIES, SHARED_CONFIG_ENABLED)); } return false; } /** * Save shared config checkbox state for automated mode to persistent * storage. * * @param sharedSettingsEnabled true = use shared settings in auto-ingest * mode */ public static void setSharedConfigEnabled(boolean sharedSettingsEnabled) { ModuleSettings.setConfigSetting(SETTINGS_PROPERTIES, SHARED_CONFIG_ENABLED, Boolean.toString(sharedSettingsEnabled)); } /** * Get shared config master checkbox state for automated mode from * persistent storage. * * @return true if this node is set as a shared configuration master */ public static Boolean getSharedConfigMaster() { if (ModuleSettings.settingExists(SETTINGS_PROPERTIES, SHARED_CONFIG_MASTER)) { return Boolean.parseBoolean(ModuleSettings.getConfigSetting(SETTINGS_PROPERTIES, SHARED_CONFIG_MASTER)); } return false; } /** * Save shared config master checkbox state to persistent storage. * * @param sharedSettingsMaster true = this node can upload configuration */ public static void setSharedConfigMaster(boolean sharedSettingsMaster) { ModuleSettings.setConfigSetting(SETTINGS_PROPERTIES, SHARED_CONFIG_MASTER, Boolean.toString(sharedSettingsMaster)); } /** * Get context string for automated mode ingest module settings. * * @return String Context string for automated mode ingest module * settings. */ public static String getAutoModeIngestModuleContextString() { return AUTO_MODE_CONTEXT_STRING; } /** * Save whether tools warning dialog should be shown on startup. * * @param showToolsWarning true = show warning dialog, false = don't show */ public static void setShowToolsWarning(boolean showToolsWarning) { ModuleSettings.setConfigSetting(SETTINGS_PROPERTIES, SHOW_TOOLS_WARNING, Boolean.toString(showToolsWarning)); } /** * Retrieve tools warning dialog setting. * * @return */ public static boolean getShowToolsWarning() { if (ModuleSettings.settingExists(SETTINGS_PROPERTIES, SHOW_TOOLS_WARNING)) { return Boolean.parseBoolean(ModuleSettings.getConfigSetting(SETTINGS_PROPERTIES, SHOW_TOOLS_WARNING)); } return true; } /** * Get the configured time to sleep between cases to prevent * database locks * * @return int the value in seconds, default is 30 seconds. */ public static int getSecondsToSleepBetweenCases() { if (ModuleSettings.settingExists(SETTINGS_PROPERTIES, SLEEP_BETWEEN_CASES_TIME)) { return Integer.parseInt(ModuleSettings.getConfigSetting(SETTINGS_PROPERTIES, SLEEP_BETWEEN_CASES_TIME)); } return 30; } /** * Sets the wait time used by auto ingest nodes to ensure proper * synchronization of node operations in circumstances where delays may * occur, e.g., network file system latency effects on the visibility of * newly created shared directories and files. * * @param value value the number of seconds to sleep between cases */ public static void setSecondsToSleepBetweenCases(int value) { ModuleSettings.setConfigSetting(SETTINGS_PROPERTIES, SLEEP_BETWEEN_CASES_TIME, Integer.toString(value)); } /** * Get maximum number of times to attempt processing an image folder. This * is used to avoid endless attempts to process an image folder with corrupt * data that causes a crash. * * @return int maximum number of attempts, default is 2. */ public static int getMaxNumTimesToProcessImage() { if (ModuleSettings.settingExists(SETTINGS_PROPERTIES, MAX_NUM_TIMES_TO_PROCESS_IMAGE)) { return Integer.parseInt(ModuleSettings.getConfigSetting(SETTINGS_PROPERTIES, MAX_NUM_TIMES_TO_PROCESS_IMAGE)); } return 2; } /** * Set the maximum number of times to attempt to reprocess an image. This is * used to avoid endless attempts to process an image folder with corrupt * data that causes a crash. * * @param retries the number of retries to allow */ public static void setMaxNumTimesToProcessImage(int retries) { ModuleSettings.setConfigSetting(SETTINGS_PROPERTIES, MAX_NUM_TIMES_TO_PROCESS_IMAGE, Integer.toString(retries)); } /** * Get maximum number of concurrent ingest nodes allowable for one case at a * time. * * @return maximum number of concurrent nodes for one case. Default is 3. */ public static int getMaxConcurrentJobsForOneCase() { if (ModuleSettings.settingExists(SETTINGS_PROPERTIES, MAX_CONCURRENT_NODES_FOR_ONE_CASE)) { return Integer.parseInt(ModuleSettings.getConfigSetting(SETTINGS_PROPERTIES, MAX_CONCURRENT_NODES_FOR_ONE_CASE)); } return 3; } /** * Get maximum number of concurrent ingest nodes allowable for one case at a * time. * * @param numberOfNodes the number of concurrent nodes to allow for one case */ public static void setMaxConcurrentIngestNodesForOneCase(int numberOfNodes) { ModuleSettings.setConfigSetting(SETTINGS_PROPERTIES, MAX_CONCURRENT_NODES_FOR_ONE_CASE, Integer.toString(numberOfNodes)); } /** * Get status database logging checkbox state for automated ingest mode from * persistent storage. * * @return Boolean true if database logging is enabled. */ public static Boolean getStatusDatabaseLoggingEnabled() { if (ModuleSettings.settingExists(SETTINGS_PROPERTIES, STATUS_DATABASE_LOGGING_ENABLED)) { return Boolean.parseBoolean(ModuleSettings.getConfigSetting(SETTINGS_PROPERTIES, STATUS_DATABASE_LOGGING_ENABLED)); } return false; } /** * Save status database logging checkbox state for automated ingest mode to * persistent storage. * * @param databaseLoggingEnabled true = use database logging in auto-ingest * mode */ public static void setStatusDatabaseLoggingEnabled(boolean databaseLoggingEnabled) { ModuleSettings.setConfigSetting(SETTINGS_PROPERTIES, STATUS_DATABASE_LOGGING_ENABLED, Boolean.toString(databaseLoggingEnabled)); } /** * Get the logging database hostname from persistent storage. * * @return Logging database hostname or IP */ public static String getLoggingDatabaseHostnameOrIP() { if (ModuleSettings.settingExists(SETTINGS_PROPERTIES, LOGGING_DB_HOSTNAME_OR_IP)) { return ModuleSettings.getConfigSetting(SETTINGS_PROPERTIES, LOGGING_DB_HOSTNAME_OR_IP); } return ""; } /** * Save the logging database hostname to persistent storage. * * @param hostname Logging database hostname or IP */ public static void setLoggingDatabaseHostnameOrIP(String hostname) { ModuleSettings.setConfigSetting(SETTINGS_PROPERTIES, LOGGING_DB_HOSTNAME_OR_IP, hostname); } /** * Get the logging database port from persistent storage. * * @return logging database port */ public static String getLoggingPort() { if (ModuleSettings.settingExists(SETTINGS_PROPERTIES, LOGGING_PORT)) { return ModuleSettings.getConfigSetting(SETTINGS_PROPERTIES, LOGGING_PORT); } return ""; } /** * Save the logging database port to persistent storage. * * @param port Logging database port */ public static void setLoggingPort(String port) { ModuleSettings.setConfigSetting(SETTINGS_PROPERTIES, LOGGING_PORT, port); } /** * Get the logging database username from persistent storage. * * @return logging database username */ public static String getLoggingUsername() { if (ModuleSettings.settingExists(SETTINGS_PROPERTIES, LOGGING_USERNAME)) { return ModuleSettings.getConfigSetting(SETTINGS_PROPERTIES, LOGGING_USERNAME); } return ""; } /** * Save the logging database username to persistent storage. * * @param username Logging database username */ public static void setLoggingUsername(String username) { ModuleSettings.setConfigSetting(SETTINGS_PROPERTIES, LOGGING_USERNAME, username); } /** * Get the logging database password from persistent storage. * * @return logging database password */ public static String getLoggingPassword() throws UserPreferencesException { if (ModuleSettings.settingExists(SETTINGS_PROPERTIES, LOGGING_PASSWORD)) { return TextConverter.convertHexTextToText(ModuleSettings.getConfigSetting(SETTINGS_PROPERTIES, LOGGING_PASSWORD)); } return ""; } /** * Save the logging database password to persistent storage. * * @param password Logging database password */ public static void setLoggingPassword(String password) throws UserPreferencesException { ModuleSettings.setConfigSetting(SETTINGS_PROPERTIES, LOGGING_PASSWORD, TextConverter.convertTextToHexText(password)); } /** * Get the logging database name from persistent storage. * * @return logging database name */ public static String getLoggingDatabaseName() { if (ModuleSettings.settingExists(SETTINGS_PROPERTIES, LOGGING_DATABASE_NAME)) { return ModuleSettings.getConfigSetting(SETTINGS_PROPERTIES, LOGGING_DATABASE_NAME); } return ""; } /** * Save the logging database name to persistent storage. * * @param name Logging database name */ public static void setLoggingDatabaseName(String name) { ModuleSettings.setConfigSetting(SETTINGS_PROPERTIES, LOGGING_DATABASE_NAME, name); } /** * Get the configured time for input scan interval * * @return int the value in minutes, default is 60 minutes. */ public static int getMinutesOfInputScanInterval() { if (ModuleSettings.settingExists(SETTINGS_PROPERTIES, INPUT_SCAN_INTERVAL_TIME)) { return Integer.parseInt(ModuleSettings.getConfigSetting(SETTINGS_PROPERTIES, INPUT_SCAN_INTERVAL_TIME)); } return 60; } /** * Set the configured time for input scan interval * * @param value the number of minutes for input interval */ public static void setMinutesOfInputScanInterval(int value) { ModuleSettings.setConfigSetting(SETTINGS_PROPERTIES, INPUT_SCAN_INTERVAL_TIME, Integer.toString(value)); } /** * Copied from Autopsy UserPreferences - can be removed once everything is merged together. * Provides ability to convert text to hex text. */ static final class TextConverter { private static final char[] TMP = "hgleri21auty84fwe".toCharArray(); //NON-NLS private static final byte[] SALT = { (byte) 0xde, (byte) 0x33, (byte) 0x10, (byte) 0x12, (byte) 0xde, (byte) 0x33, (byte) 0x10, (byte) 0x12,}; /** * Convert text to hex text. * * @param property Input text string. * * @return Converted hex string. * * @throws org.sleuthkit.autopsy.core.UserPreferencesException */ static String convertTextToHexText(String property) throws UserPreferencesException { try { SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES"); //NON-NLS SecretKey key = keyFactory.generateSecret(new PBEKeySpec(TMP)); Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES"); //NON-NLS pbeCipher.init(Cipher.ENCRYPT_MODE, key, new PBEParameterSpec(SALT, 20)); return base64Encode(pbeCipher.doFinal(property.getBytes("UTF-8"))); } catch (Exception ex) { throw new UserPreferencesException("Error encrypting text"); } } private static String base64Encode(byte[] bytes) { return Base64.getEncoder().encodeToString(bytes); } /** * Convert hex text back to text. * * @param property Input hex text string. * * @return Converted text string. * * @throws org.sleuthkit.autopsy.core.UserPreferencesException */ static String convertHexTextToText(String property) throws UserPreferencesException { try { SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES"); //NON-NLS SecretKey key = keyFactory.generateSecret(new PBEKeySpec(TMP)); Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES"); //NON-NLS pbeCipher.init(Cipher.DECRYPT_MODE, key, new PBEParameterSpec(SALT, 20)); return new String(pbeCipher.doFinal(base64Decode(property)), "UTF-8"); } catch (Exception ex) { throw new UserPreferencesException("Error decrypting text"); } } private static byte[] base64Decode(String property) { return Base64.getDecoder().decode(property); } } }