Reworked validation to run in module.

This commit is contained in:
U-BASIS\dgrove 2018-02-13 13:16:16 -05:00
parent e69934fb86
commit 5d9f999399
3 changed files with 104 additions and 60 deletions

View File

@ -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("<br/>\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;
}
}

View File

@ -136,8 +136,8 @@
</Component>
<Component class="javax.swing.JFormattedTextField" name="minimumFileSizeTextbox">
<Properties>
<Property name="formatterFactory" type="javax.swing.JFormattedTextField$AbstractFormatterFactory" editor="org.netbeans.modules.form.editors.AbstractFormatterFactoryEditor">
<Format format="#0" subtype="-1" type="0"/>
<Property name="formatterFactory" type="javax.swing.JFormattedTextField$AbstractFormatterFactory" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="minimumFileSizeTextFormatterFactory" type="code"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/modules/encryptiondetection/Bundle.properties" key="EncryptionDetectionIngestJobSettingsPanel.minimumFileSizeTextbox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
@ -150,7 +150,7 @@
<Component class="javax.swing.JFormattedTextField" name="minimumEntropyTextbox">
<Properties>
<Property name="formatterFactory" type="javax.swing.JFormattedTextField$AbstractFormatterFactory" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="entropyFormatterFactory" type="code"/>
<Connection code="minimumEntropyTextFormatterFactory" type="code"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/modules/encryptiondetection/Bundle.properties" key="EncryptionDetectionIngestJobSettingsPanel.minimumEntropyTextbox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2017 Basis Technology Corp.
* Copyright 2017-2018 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> 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) {
throw new IllegalArgumentException(NbBundle.getMessage(this.getClass(), "EncryptionDetectionIngestJobSettingsPanel.minimumEntropyInput.validationError.text"));
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);
}
}
}
/**
* 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) {
throw new IllegalArgumentException(NbBundle.getMessage(this.getClass(), "EncryptionDetectionIngestJobSettingsPanel.minimumFileSizeInput.validationError.text"));
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;
}
}
}
@ -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);