From 5d9f99939948f66a22d28d5862a40be543dd115b Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dgrove" Date: Tue, 13 Feb 2018 13:16:16 -0500 Subject: [PATCH] Reworked validation to run in module. --- .../EncryptionDetectionFileIngestModule.java | 42 +++++-- ...yptionDetectionIngestJobSettingsPanel.form | 6 +- ...yptionDetectionIngestJobSettingsPanel.java | 116 ++++++++++-------- 3 files changed, 104 insertions(+), 60 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionFileIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionFileIngestModule.java index 7dd8258263..5e1c962db0 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionFileIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionFileIngestModule.java @@ -23,6 +23,7 @@ import java.io.IOException; import java.io.InputStream; import java.util.Collections; import java.util.logging.Level; +import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.services.Blackboard; import org.sleuthkit.autopsy.coreutils.Logger; @@ -49,12 +50,16 @@ final class EncryptionDetectionFileIngestModule extends FileIngestModuleAdapter static final boolean DEFAULT_CONFIG_FILE_SIZE_MULTIPLE_ENFORCED = true; static final boolean DEFAULT_CONFIG_SLACK_FILES_ALLOWED = true; + private static final double MINIMUM_ENTROPY_INPUT_RANGE_MIN = 6.0; + private static final double MINIMUM_ENTROPY_INPUT_RANGE_MAX = 8.0; + private static final int MINIMUM_FILE_SIZE_INPUT_RANGE_MIN = 1; + private static final int FILE_SIZE_MODULUS = 512; private static final double ONE_OVER_LOG2 = 1.4426950408889634073599246810019; // (1 / log(2)) private static final int BYTE_OCCURENCES_BUFFER_SIZE = 256; - private final IngestServices SERVICES = IngestServices.getInstance(); - private final Logger LOGGER = SERVICES.getLogger(EncryptionDetectionModuleFactory.getModuleName()); + private final IngestServices services = IngestServices.getInstance(); + private final Logger logger = services.getLogger(EncryptionDetectionModuleFactory.getModuleName()); private FileTypeDetector fileTypeDetector; private Blackboard blackboard; private double calculatedEntropy; @@ -79,8 +84,9 @@ final class EncryptionDetectionFileIngestModule extends FileIngestModuleAdapter @Override public void startUp(IngestJobContext context) throws IngestModule.IngestModuleException { - blackboard = Case.getCurrentCase().getServices().getBlackboard(); try { + validateSettings(); + blackboard = Case.getCurrentCase().getServices().getBlackboard(); fileTypeDetector = new FileTypeDetector(); } catch (FileTypeDetector.FileTypeDetectorInitException ex) { throw new IngestModule.IngestModuleException("Failed to create file type detector", ex); @@ -95,13 +101,33 @@ final class EncryptionDetectionFileIngestModule extends FileIngestModuleAdapter return flagFile(file); } } catch (IOException | TskCoreException ex) { - LOGGER.log(Level.SEVERE, String.format("Unable to process file '%s'", file.getParentPath() + file.getName()), ex); + logger.log(Level.SEVERE, String.format("Unable to process file '%s'", file.getParentPath() + file.getName()), ex); return IngestModule.ProcessResult.ERROR; } return IngestModule.ProcessResult.OK; } + /** + * Validate ingest module settings. + * + * @throws IngestModule.IngestModuleException If the input is empty, + * invalid, or out of range. + */ + @NbBundle.Messages({ + "EncryptionDetectionFileIngestModule.errorMessage.minimumEntropyInput=Minimum entropy input must be a number between 6.0 and 8.0.", + "EncryptionDetectionFileIngestModule.errorMessage.minimumFileSizeInput=Minimum file size input must be an integer (in megabytes) of 1 or greater." + }) + private void validateSettings() throws IngestModule.IngestModuleException { + if (minimumEntropy < MINIMUM_ENTROPY_INPUT_RANGE_MIN || minimumEntropy > MINIMUM_ENTROPY_INPUT_RANGE_MAX) { + throw new IngestModule.IngestModuleException(Bundle.EncryptionDetectionFileIngestModule_errorMessage_minimumEntropyInput()); + } + + if (minimumFileSize < MINIMUM_FILE_SIZE_INPUT_RANGE_MIN) { + throw new IngestModule.IngestModuleException(Bundle.EncryptionDetectionFileIngestModule_errorMessage_minimumFileSizeInput()); + } + } + /** * Create a blackboard artifact. * @@ -120,13 +146,13 @@ final class EncryptionDetectionFileIngestModule extends FileIngestModuleAdapter */ blackboard.indexArtifact(artifact); } catch (Blackboard.BlackboardException ex) { - LOGGER.log(Level.SEVERE, "Unable to index blackboard artifact " + artifact.getArtifactID(), ex); //NON-NLS + logger.log(Level.SEVERE, "Unable to index blackboard artifact " + artifact.getArtifactID(), ex); //NON-NLS } /* * Send an event to update the view with the new result. */ - SERVICES.fireModuleDataEvent(new ModuleDataEvent(EncryptionDetectionModuleFactory.getModuleName(), BlackboardArtifact.ARTIFACT_TYPE.TSK_ENCRYPTION_SUSPECTED, Collections.singletonList(artifact))); + services.fireModuleDataEvent(new ModuleDataEvent(EncryptionDetectionModuleFactory.getModuleName(), BlackboardArtifact.ARTIFACT_TYPE.TSK_ENCRYPTION_SUSPECTED, Collections.singletonList(artifact))); /* * Make an ingest inbox message. @@ -135,7 +161,7 @@ final class EncryptionDetectionFileIngestModule extends FileIngestModuleAdapter detailsSb.append("File: ").append(file.getParentPath()).append(file.getName()).append("
\n"); detailsSb.append("Entropy: ").append(calculatedEntropy); - SERVICES.postMessage(IngestMessage.createDataMessage(EncryptionDetectionModuleFactory.getModuleName(), + services.postMessage(IngestMessage.createDataMessage(EncryptionDetectionModuleFactory.getModuleName(), "Encryption Detected Match: " + file.getName(), detailsSb.toString(), file.getName(), @@ -143,7 +169,7 @@ final class EncryptionDetectionFileIngestModule extends FileIngestModuleAdapter return IngestModule.ProcessResult.OK; } catch (TskCoreException ex) { - LOGGER.log(Level.SEVERE, String.format("Failed to create blackboard artifact for '%s'.", file.getParentPath() + file.getName()), ex); //NON-NLS + logger.log(Level.SEVERE, String.format("Failed to create blackboard artifact for '%s'.", file.getParentPath() + file.getName()), ex); //NON-NLS return IngestModule.ProcessResult.ERROR; } } diff --git a/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionIngestJobSettingsPanel.form b/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionIngestJobSettingsPanel.form index 3799a21ea7..6ad4fcff2b 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionIngestJobSettingsPanel.form +++ b/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionIngestJobSettingsPanel.form @@ -136,8 +136,8 @@ - - + + @@ -150,7 +150,7 @@ - + diff --git a/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionIngestJobSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionIngestJobSettingsPanel.java index 2eb38f1161..33a80992c1 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionIngestJobSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/modules/encryptiondetection/EncryptionDetectionIngestJobSettingsPanel.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2017 Basis Technology Corp. + * Copyright 2017-2018 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,12 +18,11 @@ */ package org.sleuthkit.autopsy.modules.encryptiondetection; -import java.text.NumberFormat; -import javax.swing.JFormattedTextField.AbstractFormatterFactory; +import java.text.ParseException; +import java.util.logging.Level; +import javax.swing.text.DefaultFormatter; import javax.swing.text.DefaultFormatterFactory; -import javax.swing.text.NumberFormatter; -import org.openide.util.NbBundle; -import org.openide.util.NbBundle.Messages; +import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings; import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettingsPanel; @@ -33,10 +32,12 @@ import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettingsPanel; final class EncryptionDetectionIngestJobSettingsPanel extends IngestModuleIngestJobSettingsPanel { private static final int MEGABYTE_SIZE = 1048576; - private static final double MINIMUM_ENTROPY_INPUT_RANGE_MIN = 6.0; - private static final double MINIMUM_ENTROPY_INPUT_RANGE_MAX = 8.0; - private static final int MINIMUM_FILE_SIZE_INPUT_RANGE_MIN = 1; - private AbstractFormatterFactory entropyFormatterFactory = null; + private static final int INVALID_TEXT_FIELD_INPUT_RETURN = -1; + + private final Logger logger = Logger.getLogger(EncryptionDetectionIngestJobSettingsPanel.class.getName()); + + private final DefaultFormatterFactory minimumFileSizeTextFormatterFactory = new DefaultFormatterFactory(new MinimumFileSizeTextFormatter());; + private final DefaultFormatterFactory minimumEntropyTextFormatterFactory = new DefaultFormatterFactory(new MinimumEntropyTextFormatter());; /** * Instantiate the ingest job settings panel. @@ -44,12 +45,6 @@ final class EncryptionDetectionIngestJobSettingsPanel extends IngestModuleIngest * @param settings The ingest job settings. */ public EncryptionDetectionIngestJobSettingsPanel(EncryptionDetectionIngestJobSettings settings) { - NumberFormatter entropyFormatter = new NumberFormatter(NumberFormat.getNumberInstance()); - entropyFormatter.setValueClass(Float.TYPE); - entropyFormatter.setMinimum(0); - entropyFormatter.setMaximum(Float.MAX_VALUE); - entropyFormatterFactory = new DefaultFormatterFactory(entropyFormatter); - initComponents(); customizeComponents(settings); } @@ -68,9 +63,6 @@ final class EncryptionDetectionIngestJobSettingsPanel extends IngestModuleIngest @Override public IngestModuleIngestJobSettings getSettings() { - //DLG: validateMinimumEntropy(); - //DLG: validateMinimumFileSize(); - return new EncryptionDetectionIngestJobSettings( Double.valueOf(minimumEntropyTextbox.getText()), Integer.valueOf(minimumFileSizeTextbox.getText()) * MEGABYTE_SIZE, @@ -79,42 +71,68 @@ final class EncryptionDetectionIngestJobSettingsPanel extends IngestModuleIngest } /** - * Validate the minimum entropy input. - * - * @throws IllegalArgumentException If the input is empty, invalid, or out - * of range. + * Formatter to handle minimum entropy text input. */ - @Messages({ - "EncryptionDetectionIngestJobSettingsPanel.minimumEntropyInput.validationError.text=Minimum entropy input must be a number between 6.0 and 8.0." - }) - private void validateMinimumEntropy() throws IllegalArgumentException { - try { - double minimumEntropy = Double.valueOf(minimumEntropyTextbox.getText()); - if (minimumEntropy < MINIMUM_ENTROPY_INPUT_RANGE_MIN || minimumEntropy > MINIMUM_ENTROPY_INPUT_RANGE_MAX) { - throw new IllegalArgumentException(NbBundle.getMessage(this.getClass(), "EncryptionDetectionIngestJobSettingsPanel.minimumEntropyInput.validationError.text")); + private final class MinimumEntropyTextFormatter extends DefaultFormatter { + + /** + * Create an instance of the formatter. + */ + MinimumEntropyTextFormatter() { + super(); + } + + @Override + public String valueToString(Object object) throws ParseException { + return super.valueToString(object); + } + + @Override + public Object stringToValue(String string) throws ParseException { + try { + return Double.parseDouble(string); + } catch (NumberFormatException ex) { + logger.log(Level.WARNING, String.format("The text input '%s' for minimum entropy is not valid.", string), ex); + /* + * Return a valid number outside the acceptable value range so + * it can be run through the validator in the file ingest + * module. + */ + return new Double(INVALID_TEXT_FIELD_INPUT_RETURN); } - } catch (NumberFormatException ex) { - throw new IllegalArgumentException(NbBundle.getMessage(this.getClass(), "EncryptionDetectionIngestJobSettingsPanel.minimumEntropyInput.validationError.text")); } } /** - * Validate the minimum file size input. - * - * @throws IllegalArgumentException If the input is empty, invalid, or out - * of range. + * Formatter to handle minimum file size text input. */ - @Messages({ - "EncryptionDetectionIngestJobSettingsPanel.minimumFileSizeInput.validationError.text=Minimum file size input must be an integer (in megabytes) of 1 or greater." - }) - private void validateMinimumFileSize() throws IllegalArgumentException { - try { - int minimumFileSize = Integer.valueOf(minimumFileSizeTextbox.getText()); - if (minimumFileSize < MINIMUM_FILE_SIZE_INPUT_RANGE_MIN) { - throw new IllegalArgumentException(NbBundle.getMessage(this.getClass(), "EncryptionDetectionIngestJobSettingsPanel.minimumFileSizeInput.validationError.text")); + private final class MinimumFileSizeTextFormatter extends DefaultFormatter { + + /** + * Create an instance of the formatter. + */ + MinimumFileSizeTextFormatter() { + super(); + } + + @Override + public String valueToString(Object object) throws ParseException { + return super.valueToString(object); + } + + @Override + public Object stringToValue(String string) throws ParseException { + try { + return Integer.parseInt(string); + } catch (NumberFormatException ex) { + logger.log(Level.WARNING, String.format("The text input '%s' for minimum file size is not valid.", string), ex); + /* + * Return a valid number outside the acceptable value range so + * it can still be run through the validator in the file ingest + * module. + */ + return INVALID_TEXT_FIELD_INPUT_RETURN; } - } catch (NumberFormatException ex) { - throw new IllegalArgumentException(NbBundle.getMessage(this.getClass(), "EncryptionDetectionIngestJobSettingsPanel.minimumFileSizeInput.validationError.text")); } } @@ -155,7 +173,7 @@ final class EncryptionDetectionIngestJobSettingsPanel extends IngestModuleIngest detectionSettingsLabel.setFont(new java.awt.Font("Tahoma", 1, 11)); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(detectionSettingsLabel, org.openide.util.NbBundle.getMessage(EncryptionDetectionIngestJobSettingsPanel.class, "EncryptionDetectionIngestJobSettingsPanel.detectionSettingsLabel.text")); // NOI18N - minimumFileSizeTextbox.setFormatterFactory(new javax.swing.text.DefaultFormatterFactory(new javax.swing.text.NumberFormatter(new java.text.DecimalFormat("#0")))); + minimumFileSizeTextbox.setFormatterFactory(minimumFileSizeTextFormatterFactory); minimumFileSizeTextbox.setText(org.openide.util.NbBundle.getMessage(EncryptionDetectionIngestJobSettingsPanel.class, "EncryptionDetectionIngestJobSettingsPanel.minimumFileSizeTextbox.text")); // NOI18N minimumFileSizeTextbox.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { @@ -163,7 +181,7 @@ final class EncryptionDetectionIngestJobSettingsPanel extends IngestModuleIngest } }); - minimumEntropyTextbox.setFormatterFactory(entropyFormatterFactory); + minimumEntropyTextbox.setFormatterFactory(minimumEntropyTextFormatterFactory); minimumEntropyTextbox.setText(org.openide.util.NbBundle.getMessage(EncryptionDetectionIngestJobSettingsPanel.class, "EncryptionDetectionIngestJobSettingsPanel.minimumEntropyTextbox.text")); // NOI18N javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);