Implementation of hash database name and path filters

This commit is contained in:
Richard Cordovano
2013-12-02 10:34:09 -05:00
parent 2603934173
commit f74c65c417
12 changed files with 603 additions and 454 deletions
@@ -130,7 +130,7 @@ final class AddContentToHashDbAction extends AbstractAction implements Presenter
newHashSetItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
HashDb hashDb = new HashDbCreateDatabaseDialog().doDialog();
HashDb hashDb = new HashDbCreateDatabaseDialog().getHashDatabase();
if (null != hashDb) {
HashDbManager.getInstance().save();
addFilesToHashSet(selectedFiles, hashDb);
@@ -145,7 +145,7 @@ final class AddContentToHashDbAction extends AbstractAction implements Presenter
String md5Hash = file.getMd5Hash();
if (null != md5Hash) {
try {
hashSet.add(file);
hashSet.addHashes(file);
}
catch (TskCoreException ex) {
Logger.getLogger(AddContentToHashDbAction.class.getName()).log(Level.SEVERE, "Error adding to hash database", ex);
@@ -47,10 +47,7 @@ HashDbConfigPanel.hashDbIndexStatusLabel.text=No database selected
HashDbConfigPanel.hashDbTypeLabel.text=No database selected
HashDbConfigPanel.indexButton.text=Index
HashDbConfigPanel.indexLabel.text=Index Status:
HashDbConfigPanel.showInboxMessagesCheckBox.text=Send ingest messages
HashDbConfigPanel.useForIngestCheckbox.text=Search during ingest
HashDbConfigPanel.informationLabel.text=Information
HashDbSimpleConfigPanel.calcHashesButton.text=Calculate hashes even if no hash database is selected
HashDbConfigPanel.importDatabaseButton.text=Import Database
HashDbConfigPanel.deleteDatabaseButton.text=Delete Database
HashDbConfigPanel.indexPathLabelLabel.text=Index Path:
@@ -64,7 +61,7 @@ HashDbSimpleConfigPanel.knownBadHashDbsLabel.text=Enable known bad databases for
HashDbSimpleConfigPanel.knownHashDbsLabel.text=Enable known hash databases for ingest:
HashDbImportDatabaseDialog.knownRadioButton.text=Known (NSRL or other)
HashDbCreateDatabaseDialog.knownRadioButton.text=Known
HashDbCreateDatabaseDialog.jLabel1.text=Hash Set Name:
HashDbCreateDatabaseDialog.jLabel1.text=Database Path:
HashDbCreateDatabaseDialog.saveAsButton.text=Save As...
HashDbCreateDatabaseDialog.hashSetNameTextField.text=
HashDbImportDatabaseDialog.jLabel3.text=Database Path:
@@ -76,3 +73,9 @@ HashDbImportDatabaseDialog.sendIngestMessagesCheckbox.text=Send ingest messages
HashDbImportDatabaseDialog.hashSetNameTextField.text=
HashDbConfigPanel.createDatabaseButton.text=Create Database
HashDbImportDatabaseDialog.openButton.text=Open...
HashDbSimpleConfigPanel.alwaysCalcHashesCheckbox.text=Calculate hashes even if no hash database is selected
HashDbCreateDatabaseDialog.jLabel3.text=Hash Set Name:
HashDbCreateDatabaseDialog.okButton.text=OK
HashDbCreateDatabaseDialog.databasePathTextField.text=
HashDbConfigPanel.searchDuringIngestCheckbox.text=Search during ingest
HashDbConfigPanel.sendIngestMessagesCheckBox.text=Send ingest messages
@@ -96,10 +96,10 @@
<EmptySpace min="-2" pref="53" max="-2" attributes="0"/>
<Component id="hashDbNameLabel" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="useForIngestCheckbox" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="searchDuringIngestCheckbox" alignment="0" min="-2" max="-2" attributes="0"/>
<Group type="102" attributes="0">
<EmptySpace min="21" pref="21" max="-2" attributes="0"/>
<Component id="showInboxMessagesCheckBox" min="-2" max="-2" attributes="0"/>
<Component id="sendIngestMessagesCheckBox" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
@@ -180,9 +180,9 @@
<Component id="optionsSeparator" min="-2" pref="6" max="-2" attributes="0"/>
</Group>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="useForIngestCheckbox" min="-2" max="-2" attributes="0"/>
<Component id="searchDuringIngestCheckbox" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="showInboxMessagesCheckBox" min="-2" max="-2" attributes="0"/>
<Component id="sendIngestMessagesCheckBox" min="-2" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="ingestWarningLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
@@ -360,24 +360,24 @@
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="indexButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JCheckBox" name="useForIngestCheckbox">
<Component class="javax.swing.JCheckBox" name="searchDuringIngestCheckbox">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/hashdatabase/Bundle.properties" key="HashDbConfigPanel.useForIngestCheckbox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<ResourceString bundle="org/sleuthkit/autopsy/hashdatabase/Bundle.properties" key="HashDbConfigPanel.searchDuringIngestCheckbox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="useForIngestCheckboxActionPerformed"/>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="searchDuringIngestCheckboxActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JCheckBox" name="showInboxMessagesCheckBox">
<Component class="javax.swing.JCheckBox" name="sendIngestMessagesCheckBox">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/hashdatabase/Bundle.properties" key="HashDbConfigPanel.showInboxMessagesCheckBox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<ResourceString bundle="org/sleuthkit/autopsy/hashdatabase/Bundle.properties" key="HashDbConfigPanel.sendIngestMessagesCheckBox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="showInboxMessagesCheckBoxActionPerformed"/>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="sendIngestMessagesCheckBoxActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="informationLabel">
@@ -40,13 +40,16 @@ import org.sleuthkit.autopsy.corecomponents.OptionsPanel;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.ingest.IngestManager;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.autopsy.hashdatabase.HashDbManager.HashDb;
import org.sleuthkit.autopsy.hashdatabase.HashDbManager.HashDb.KnownFilesType;
/**
* Instances of this class provide a comprehensive UI for managing the hash sets configuration.
*/
public final class HashDbConfigPanel extends javax.swing.JPanel implements OptionsPanel {
private static final String NO_SELECTION_TEXT = "No database selected";
private static final String ERROR_GETTING_INDEX_STATUS = "Error occurred getting status";
private static final String ERROR_GETTING_PATH_TEXT = "Error occurred getting path";
private static final String ERROR_GETTING_INDEX_STATUS_TEXT = "Error occurred getting status";
private static final String LEGACY_INDEX_FILE_EXTENSION = "-md5.idx";
private HashDbManager hashSetManager = HashDbManager.getInstance();
private HashSetTableModel hashSetTableModel = new HashSetTableModel();
@@ -111,10 +114,10 @@ public final class HashDbConfigPanel extends javax.swing.JPanel implements Optio
indexButton.setEnabled(false);
// Update ingest options.
useForIngestCheckbox.setSelected(false);
useForIngestCheckbox.setEnabled(false);
showInboxMessagesCheckBox.setSelected(false);
showInboxMessagesCheckBox.setEnabled(false);
searchDuringIngestCheckbox.setSelected(false);
searchDuringIngestCheckbox.setEnabled(false);
sendIngestMessagesCheckBox.setSelected(false);
sendIngestMessagesCheckBox.setEnabled(false);
optionsLabel.setEnabled(false);
optionsSeparator.setEnabled(false);
@@ -133,8 +136,22 @@ public final class HashDbConfigPanel extends javax.swing.JPanel implements Optio
// Update descriptive labels.
hashDbNameLabel.setText(db.getHashSetName());
hashDbTypeLabel.setText(db.getKnownFilesType().getDisplayName());
hashDbLocationLabel.setText(shortenPath(db.getDatabasePath()));
indexPathLabel.setText(shortenPath(db.getIndexPath()));
try {
hashDbLocationLabel.setText(shortenPath(db.getDatabasePath()));
}
catch (TskCoreException ex) {
Logger.getLogger(HashDbConfigPanel.class.getName()).log(Level.SEVERE, "Error getting database path of " + db.getHashSetName() + " hash database", ex);
hashDbLocationLabel.setText(ERROR_GETTING_PATH_TEXT);
}
try {
indexPathLabel.setText(shortenPath(db.getIndexPath()));
}
catch (TskCoreException ex) {
Logger.getLogger(HashDbConfigPanel.class.getName()).log(Level.SEVERE, "Error getting index path of " + db.getHashSetName() + " hash database", ex);
indexPathLabel.setText(ERROR_GETTING_PATH_TEXT);
}
// Update indexing components.
try {
@@ -155,7 +172,7 @@ public final class HashDbConfigPanel extends javax.swing.JPanel implements Optio
hashDbIndexStatusLabel.setText("Indexed");
}
hashDbIndexStatusLabel.setForeground(Color.black);
if (db.canBeReindexed()) {
if (db.canBeReIndexed()) {
indexButton.setText("Re-Index");
indexButton.setEnabled(true);
}
@@ -173,7 +190,7 @@ public final class HashDbConfigPanel extends javax.swing.JPanel implements Optio
}
catch (TskCoreException ex) {
Logger.getLogger(HashDbConfigPanel.class.getName()).log(Level.SEVERE, "Error getting index state of hash database", ex);
hashDbIndexStatusLabel.setText(ERROR_GETTING_INDEX_STATUS);
hashDbIndexStatusLabel.setText(ERROR_GETTING_INDEX_STATUS_TEXT);
hashDbIndexStatusLabel.setForeground(Color.red);
indexButton.setText("Index");
indexButton.setEnabled(false);
@@ -185,12 +202,12 @@ public final class HashDbConfigPanel extends javax.swing.JPanel implements Optio
}
// Update ingest option components.
useForIngestCheckbox.setSelected(db.getUseForIngest());
useForIngestCheckbox.setEnabled(!ingestIsRunning);
showInboxMessagesCheckBox.setSelected(db.getShowInboxMessages());
showInboxMessagesCheckBox.setEnabled(!ingestIsRunning && db.getUseForIngest() && db.getKnownFilesType().equals(HashDb.KnownFilesType.KNOWN_BAD));
optionsLabel.setEnabled(!ingestIsRunning && db.getUseForIngest() && db.getKnownFilesType().equals(HashDb.KnownFilesType.KNOWN_BAD));
optionsSeparator.setEnabled(!ingestIsRunning && db.getUseForIngest() && db.getKnownFilesType().equals(HashDb.KnownFilesType.KNOWN_BAD));
searchDuringIngestCheckbox.setSelected(db.getSearchDuringIngest());
searchDuringIngestCheckbox.setEnabled(!ingestIsRunning);
sendIngestMessagesCheckBox.setSelected(db.getSendIngestMessages());
sendIngestMessagesCheckBox.setEnabled(!ingestIsRunning && db.getSearchDuringIngest() && db.getKnownFilesType().equals(KnownFilesType.KNOWN_BAD));
optionsLabel.setEnabled(!ingestIsRunning);
optionsSeparator.setEnabled(!ingestIsRunning);
// Update database action buttons.
createDatabaseButton.setEnabled(true);
@@ -245,14 +262,9 @@ public final class HashDbConfigPanel extends javax.swing.JPanel implements Optio
hashSetManager.save();
}
/**
* Removes a list of HashDbs from the dialog panel that do not have a companion -md5.idx file.
* Occurs when user clicks "No" to the dialog pop up box.
* @param toRemove a list of HashDbs that are unindexed
*/
void removeThese(List<HashDb> toRemove) {
for (HashDb hashDb : toRemove) {
hashSetManager.removeHashSet(hashDb);
hashSetManager.removeHashDatabase(hashDb);
}
hashSetTableModel.refreshModel();
}
@@ -290,7 +302,6 @@ public final class HashDbConfigPanel extends javax.swing.JPanel implements Optio
}
boolean valid() {
// TODO check whether form is consistent and complete
return true;
}
@@ -439,8 +450,8 @@ public final class HashDbConfigPanel extends javax.swing.JPanel implements Optio
hashDbIndexStatusLabel = new javax.swing.JLabel();
indexLabel = new javax.swing.JLabel();
indexButton = new javax.swing.JButton();
useForIngestCheckbox = new javax.swing.JCheckBox();
showInboxMessagesCheckBox = new javax.swing.JCheckBox();
searchDuringIngestCheckbox = new javax.swing.JCheckBox();
sendIngestMessagesCheckBox = new javax.swing.JCheckBox();
informationLabel = new javax.swing.JLabel();
optionsLabel = new javax.swing.JLabel();
informationSeparator = new javax.swing.JSeparator();
@@ -529,17 +540,17 @@ public final class HashDbConfigPanel extends javax.swing.JPanel implements Optio
}
});
org.openide.awt.Mnemonics.setLocalizedText(useForIngestCheckbox, org.openide.util.NbBundle.getMessage(HashDbConfigPanel.class, "HashDbConfigPanel.useForIngestCheckbox.text")); // NOI18N
useForIngestCheckbox.addActionListener(new java.awt.event.ActionListener() {
org.openide.awt.Mnemonics.setLocalizedText(searchDuringIngestCheckbox, org.openide.util.NbBundle.getMessage(HashDbConfigPanel.class, "HashDbConfigPanel.searchDuringIngestCheckbox.text")); // NOI18N
searchDuringIngestCheckbox.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
useForIngestCheckboxActionPerformed(evt);
searchDuringIngestCheckboxActionPerformed(evt);
}
});
org.openide.awt.Mnemonics.setLocalizedText(showInboxMessagesCheckBox, org.openide.util.NbBundle.getMessage(HashDbConfigPanel.class, "HashDbConfigPanel.showInboxMessagesCheckBox.text")); // NOI18N
showInboxMessagesCheckBox.addActionListener(new java.awt.event.ActionListener() {
org.openide.awt.Mnemonics.setLocalizedText(sendIngestMessagesCheckBox, org.openide.util.NbBundle.getMessage(HashDbConfigPanel.class, "HashDbConfigPanel.sendIngestMessagesCheckBox.text")); // NOI18N
sendIngestMessagesCheckBox.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
showInboxMessagesCheckBoxActionPerformed(evt);
sendIngestMessagesCheckBoxActionPerformed(evt);
}
});
@@ -600,10 +611,10 @@ public final class HashDbConfigPanel extends javax.swing.JPanel implements Optio
.addComponent(nameLabel)
.addGap(53, 53, 53)
.addComponent(hashDbNameLabel))
.addComponent(useForIngestCheckbox)
.addComponent(searchDuringIngestCheckbox)
.addGroup(layout.createSequentialGroup()
.addGap(21, 21, 21)
.addComponent(showInboxMessagesCheckBox)))
.addComponent(sendIngestMessagesCheckBox)))
.addGap(0, 0, Short.MAX_VALUE))))
.addGroup(layout.createSequentialGroup()
.addComponent(optionsLabel)
@@ -661,9 +672,9 @@ public final class HashDbConfigPanel extends javax.swing.JPanel implements Optio
.addComponent(optionsLabel)
.addComponent(optionsSeparator, javax.swing.GroupLayout.PREFERRED_SIZE, 6, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(18, 18, 18)
.addComponent(useForIngestCheckbox)
.addComponent(searchDuringIngestCheckbox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(showInboxMessagesCheckBox)
.addComponent(sendIngestMessagesCheckBox)
.addGap(18, 18, 18)
.addComponent(ingestWarningLabel)
.addGap(0, 0, Short.MAX_VALUE))
@@ -712,7 +723,7 @@ public final class HashDbConfigPanel extends javax.swing.JPanel implements Optio
if (JOptionPane.showConfirmDialog(null, "This will remove the hash database for all cases. Do you want to proceed? ", "Delete Hash Database from Configuration", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE) == JOptionPane.YES_OPTION) {
HashDb hashDb = ((HashSetTable)hashSetTable).getSelection();
if (hashDb != null) {
hashSetManager.removeHashSet(hashDb);
hashSetManager.removeHashDatabase(hashDb);
hashSetTableModel.refreshModel();
}
}
@@ -722,40 +733,41 @@ public final class HashDbConfigPanel extends javax.swing.JPanel implements Optio
if (evt.getKeyCode() == KeyEvent.VK_DELETE) {
HashDb hashDb = ((HashSetTable)hashSetTable).getSelection();
if (hashDb != null) {
hashSetManager.removeHashSet(hashDb);
hashSetManager.removeHashDatabase(hashDb);
hashSetTableModel.refreshModel();
}
}
}//GEN-LAST:event_hashSetTableKeyPressed
private void useForIngestCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_useForIngestCheckboxActionPerformed
private void searchDuringIngestCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_searchDuringIngestCheckboxActionPerformed
HashDb hashDb = ((HashSetTable)hashSetTable).getSelection();
if (hashDb != null) {
hashDb.setUseForIngest(useForIngestCheckbox.isSelected());
showInboxMessagesCheckBox.setEnabled(useForIngestCheckbox.isSelected());
hashDb.setSearchDuringIngest(searchDuringIngestCheckbox.isSelected());
if (!searchDuringIngestCheckbox.isSelected()) {
sendIngestMessagesCheckBox.setSelected(false);
}
hashDb.setSendIngestMessages(sendIngestMessagesCheckBox.isSelected());
}
}//GEN-LAST:event_useForIngestCheckboxActionPerformed
}//GEN-LAST:event_searchDuringIngestCheckboxActionPerformed
private void showInboxMessagesCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_showInboxMessagesCheckBoxActionPerformed
private void sendIngestMessagesCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_sendIngestMessagesCheckBoxActionPerformed
HashDb hashDb = ((HashSetTable)hashSetTable).getSelection();
if (hashDb != null) {
hashDb.setShowInboxMessages(showInboxMessagesCheckBox.isSelected());
hashDb.setSendIngestMessages(sendIngestMessagesCheckBox.isSelected());
}
}//GEN-LAST:event_showInboxMessagesCheckBoxActionPerformed
}//GEN-LAST:event_sendIngestMessagesCheckBoxActionPerformed
private void importDatabaseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_importDatabaseButtonActionPerformed
HashDb hashDb = new HashDbImportDatabaseDialog().doDialog();
if (hashDb != null) {
hashSetManager.addHashSet(hashDb);
HashDb hashDb = new HashDbImportDatabaseDialog().getHashDatabase();
if (null != hashDb) {
hashSetTableModel.refreshModel();
((HashSetTable)hashSetTable).selectRowByName(hashDb.getHashSetName());
}
}//GEN-LAST:event_importDatabaseButtonActionPerformed
private void createDatabaseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_createDatabaseButtonActionPerformed
HashDb hashDb = new HashDbCreateDatabaseDialog().doDialog();
HashDb hashDb = new HashDbCreateDatabaseDialog().getHashDatabase();
if (null != hashDb) {
hashSetManager.addHashSet(hashDb);
hashSetTableModel.refreshModel();
((HashSetTable)hashSetTable).selectRowByName(hashDb.getHashSetName());
}
@@ -787,8 +799,8 @@ public final class HashDbConfigPanel extends javax.swing.JPanel implements Optio
private javax.swing.JLabel nameLabel;
private javax.swing.JLabel optionsLabel;
private javax.swing.JSeparator optionsSeparator;
private javax.swing.JCheckBox showInboxMessagesCheckBox;
private javax.swing.JCheckBox searchDuringIngestCheckbox;
private javax.swing.JCheckBox sendIngestMessagesCheckBox;
private javax.swing.JLabel typeLabel;
private javax.swing.JCheckBox useForIngestCheckbox;
// End of variables declaration//GEN-END:variables
}
@@ -27,7 +27,7 @@
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
@@ -42,12 +42,13 @@
</Group>
<Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jLabel2" min="-2" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Component id="jLabel1" min="-2" max="-2" attributes="0"/>
<Group type="102" alignment="1" attributes="0">
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
<Component id="okButton" linkSize="2" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="hashSetNameTextField" min="-2" pref="176" max="-2" attributes="0"/>
<Component id="cancelButton" linkSize="2" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="jLabel2" min="-2" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" pref="20" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
@@ -55,29 +56,44 @@
<Component id="knownBadRadioButton" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="1" max="-2" attributes="0">
<Group type="102" attributes="0">
<Component id="jLabel1" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="databasePathTextField" max="32767" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Component id="jLabel3" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="hashSetNameTextField" min="-2" pref="272" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="saveAsButton" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</Group>
<Group type="102" alignment="1" attributes="0">
<EmptySpace max="32767" attributes="0"/>
<Component id="saveAsButton" linkSize="1" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="cancelButton" linkSize="1" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<EmptySpace min="-2" pref="2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="jLabel1" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="jLabel3" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="hashSetNameTextField" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="databasePathTextField" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="saveAsButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="jLabel1" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" pref="7" max="-2" attributes="0"/>
<Component id="jLabel2" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="knownRadioButton" min="-2" max="-2" attributes="0"/>
@@ -87,12 +103,12 @@
<Component id="searchDuringIngestCheckbox" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="sendIngestMessagesCheckbox" min="-2" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="3" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="saveAsButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="cancelButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="okButton" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace pref="12" max="32767" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@@ -188,5 +204,30 @@
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabel3">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/hashdatabase/Bundle.properties" key="HashDbCreateDatabaseDialog.jLabel3.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="databasePathTextField">
<Properties>
<Property name="editable" type="boolean" value="false"/>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/hashdatabase/Bundle.properties" key="HashDbCreateDatabaseDialog.databasePathTextField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JButton" name="okButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/hashdatabase/Bundle.properties" key="HashDbCreateDatabaseDialog.okButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="okButtonActionPerformed"/>
</Events>
</Component>
</SubComponents>
</Form>
@@ -27,21 +27,48 @@ import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.JFrame;
import org.apache.commons.io.FilenameUtils;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.autopsy.hashdatabase.HashDbManager.KnownFilesType;
import org.sleuthkit.autopsy.hashdatabase.HashDbManager.HashDb;
import org.sleuthkit.autopsy.hashdatabase.HashDbManager.HashDb.KnownFilesType;
import org.sleuthkit.autopsy.hashdatabase.HashDbManager.HashDatabaseFileAlreadyExistsException;
import org.sleuthkit.autopsy.hashdatabase.HashDbManager.DuplicateHashSetNameException;
import org.sleuthkit.autopsy.hashdatabase.HashDbManager.HashDatabaseAlreadyAddedException;
import org.sleuthkit.autopsy.hashdatabase.HashDbManager.IllegalHashDatabaseFileNameExtensionException;
/**
* Instances of this class allow a user to create a new hash database.
* Instances of this class allow a user to create a new hash database and
* add it to the set of hash databases used to classify files as unknown, known
* or known bad.
*/
final class HashDbCreateDatabaseDialog extends javax.swing.JDialog {
private static final String DEFAULT_FILE_NAME = "hashset";
private JFileChooser fileChooser = null;
private HashDb newHashDb = null;
/**
* Displays a dialog that allows a user to create a new hash database and
* add it to the set of hash databases used to classify files as unknown, known
* or known bad.
*/
HashDbCreateDatabaseDialog() {
super(new javax.swing.JFrame(), "Create Hash Database", true);
super(new JFrame(), "Create Hash Database", true);
initFileChooser();
initComponents();
display();
}
/**
* Get the hash database created by the user, if any.
* @return A HashDb object or null.
*/
HashDb getHashDatabase() {
return newHashDb;
}
private void initFileChooser() {
fileChooser = new JFileChooser() {
@Override
public void approveSelection() {
@@ -49,36 +76,29 @@ final class HashDbCreateDatabaseDialog extends javax.swing.JDialog {
if (!FilenameUtils.getExtension(selectedFile.getName()).equalsIgnoreCase(HashDbManager.getHashDatabaseFileExtension())) {
if (JOptionPane.showConfirmDialog(this, "The hash database file must have a ." + HashDbManager.getHashDatabaseFileExtension() + " extension.", "File Name Error", JOptionPane.OK_CANCEL_OPTION) == JOptionPane.CANCEL_OPTION) {
cancelSelection();
return;
}
return;
}
if (selectedFile.exists()) {
if (JOptionPane.showConfirmDialog(this, "A file with this name already exists. Please choose a new file name.", "File Already Exists Error", JOptionPane.OK_CANCEL_OPTION) == JOptionPane.CANCEL_OPTION) {
cancelSelection();
return;
}
return;
}
super.approveSelection();
}
};
fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
fileChooser.setDragEnabled(false);
fileChooser.setMultiSelectionEnabled(false);
initComponents();
fileChooser.setMultiSelectionEnabled(false);
}
HashDb doDialog() {
newHashDb = null;
// Center and display the dialog.
private void display() {
Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize();
setLocation((screenDimension.width - getSize().width) / 2, (screenDimension.height - getSize().height) / 2);
this.setVisible(true);
return newHashDb;
setVisible(true);
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
@@ -98,6 +118,9 @@ final class HashDbCreateDatabaseDialog extends javax.swing.JDialog {
jLabel2 = new javax.swing.JLabel();
searchDuringIngestCheckbox = new javax.swing.JCheckBox();
sendIngestMessagesCheckbox = new javax.swing.JCheckBox();
jLabel3 = new javax.swing.JLabel();
databasePathTextField = new javax.swing.JTextField();
okButton = new javax.swing.JButton();
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
@@ -150,6 +173,18 @@ final class HashDbCreateDatabaseDialog extends javax.swing.JDialog {
sendIngestMessagesCheckbox.setSelected(true);
org.openide.awt.Mnemonics.setLocalizedText(sendIngestMessagesCheckbox, org.openide.util.NbBundle.getMessage(HashDbCreateDatabaseDialog.class, "HashDbCreateDatabaseDialog.sendIngestMessagesCheckbox.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(jLabel3, org.openide.util.NbBundle.getMessage(HashDbCreateDatabaseDialog.class, "HashDbCreateDatabaseDialog.jLabel3.text")); // NOI18N
databasePathTextField.setEditable(false);
databasePathTextField.setText(org.openide.util.NbBundle.getMessage(HashDbCreateDatabaseDialog.class, "HashDbCreateDatabaseDialog.databasePathTextField.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(okButton, org.openide.util.NbBundle.getMessage(HashDbCreateDatabaseDialog.class, "HashDbCreateDatabaseDialog.okButton.text")); // NOI18N
okButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
okButtonActionPerformed(evt);
}
});
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
@@ -166,35 +201,47 @@ final class HashDbCreateDatabaseDialog extends javax.swing.JDialog {
.addGap(0, 0, Short.MAX_VALUE))
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jLabel2)
.addGroup(layout.createSequentialGroup()
.addComponent(jLabel1)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addGap(0, 0, Short.MAX_VALUE)
.addComponent(okButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(hashSetNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 176, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(cancelButton))
.addComponent(jLabel2)
.addGroup(layout.createSequentialGroup()
.addGap(20, 20, 20)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(knownRadioButton)
.addComponent(knownBadRadioButton))))
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(saveAsButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(cancelButton)
.addContainerGap())
.addComponent(knownBadRadioButton)))
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
.addGroup(layout.createSequentialGroup()
.addComponent(jLabel1)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(databasePathTextField))
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
.addComponent(jLabel3)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(hashSetNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 272, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(saveAsButton)))
.addContainerGap())))
);
layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {cancelButton, saveAsButton});
layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {cancelButton, okButton});
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap()
.addGap(2, 2, 2)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabel1)
.addComponent(jLabel3)
.addComponent(hashSetNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(databasePathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(saveAsButton)
.addComponent(jLabel1))
.addGap(7, 7, 7)
.addComponent(jLabel2)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(knownRadioButton)
@@ -204,22 +251,24 @@ final class HashDbCreateDatabaseDialog extends javax.swing.JDialog {
.addComponent(searchDuringIngestCheckbox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(sendIngestMessagesCheckbox)
.addGap(18, 18, 18)
.addGap(3, 3, 3)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(saveAsButton)
.addComponent(cancelButton))
.addContainerGap(12, Short.MAX_VALUE))
.addComponent(cancelButton)
.addComponent(okButton))
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
pack();
}// </editor-fold>//GEN-END:initComponents
private void knownRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_knownRadioButtonActionPerformed
searchDuringIngestCheckbox.setSelected(true);
sendIngestMessagesCheckbox.setSelected(false);
sendIngestMessagesCheckbox.setEnabled(false);
}//GEN-LAST:event_knownRadioButtonActionPerformed
private void knownBadRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_knownBadRadioButtonActionPerformed
searchDuringIngestCheckbox.setSelected(true);
sendIngestMessagesCheckbox.setSelected(true);
sendIngestMessagesCheckbox.setEnabled(true);
}//GEN-LAST:event_knownBadRadioButtonActionPerformed
@@ -229,16 +278,47 @@ final class HashDbCreateDatabaseDialog extends javax.swing.JDialog {
}//GEN-LAST:event_cancelButtonActionPerformed
private void saveAsButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveAsButtonActionPerformed
if (hashSetNameTextField.getText().isEmpty()) {
JOptionPane.showMessageDialog(this, "A hash set name must be entered.");
return;
}
fileChooser.setSelectedFile(new File(hashSetNameTextField.getText() + "." + HashDbManager.getHashDatabaseFileExtension()));
if (fileChooser.showSaveDialog(this) != JFileChooser.APPROVE_OPTION) {
return;
try {
StringBuilder path = new StringBuilder();
if (!hashSetNameTextField.getText().isEmpty()) {
path.append(hashSetNameTextField.getText());
}
else {
path.append(DEFAULT_FILE_NAME);
}
path.append(".").append(HashDbManager.getHashDatabaseFileExtension());
fileChooser.setSelectedFile(new File(path.toString()));
if (fileChooser.showSaveDialog(this) == JFileChooser.APPROVE_OPTION) {
File databaseFile = fileChooser.getSelectedFile();
databasePathTextField.setText(databaseFile.getCanonicalPath());
}
}
catch (IOException ex) {
Logger.getLogger(HashDbCreateDatabaseDialog.class.getName()).log(Level.WARNING, "Couldn't get selected file path.", ex);
}
}//GEN-LAST:event_saveAsButtonActionPerformed
private void searchDuringIngestCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_searchDuringIngestCheckboxActionPerformed
sendIngestMessagesCheckbox.setEnabled(searchDuringIngestCheckbox.isSelected());
if (!searchDuringIngestCheckbox.isSelected()) {
sendIngestMessagesCheckbox.setSelected(false);
}
}//GEN-LAST:event_searchDuringIngestCheckboxActionPerformed
private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed
// Note that the error handlers in this method call return without disposing of the
// dialog to allow the user to try again, if desired.
if (hashSetNameTextField.getText().isEmpty()) {
JOptionPane.showMessageDialog(this, "A hash set name must be entered.", "Create Hash Database Error", JOptionPane.ERROR_MESSAGE);
return;
}
if (databasePathTextField.getText().isEmpty()) {
JOptionPane.showMessageDialog(this, "A database path must be entered.", "Create Hash Database Error", JOptionPane.ERROR_MESSAGE);
return;
}
KnownFilesType type;
if (knownRadioButton.isSelected()) {
type = KnownFilesType.KNOWN;
@@ -254,53 +334,34 @@ final class HashDbCreateDatabaseDialog extends javax.swing.JDialog {
}
catch (IOException ex) {
Logger.getLogger(HashDbCreateDatabaseDialog.class.getName()).log(Level.WARNING, errorMessage, ex);
JOptionPane.showMessageDialog(this, "Cannot create a hash database file at the selected location.");
JOptionPane.showMessageDialog(this, "Cannot create a hash database file at the selected location.", "Create Hash Database Error", JOptionPane.ERROR_MESSAGE);
return;
}
catch (HashDbManager.FileAlreadyExistsException ex) {
catch (HashDatabaseFileAlreadyExistsException | DuplicateHashSetNameException | HashDatabaseAlreadyAddedException | IllegalHashDatabaseFileNameExtensionException ex) {
Logger.getLogger(HashDbCreateDatabaseDialog.class.getName()).log(Level.WARNING, errorMessage, ex);
JOptionPane.showMessageDialog(this, ex.getMessage());
JOptionPane.showMessageDialog(this, ex.getMessage(), "Create Hash Database Error", JOptionPane.ERROR_MESSAGE);
return;
}
catch (HashDbManager.DuplicateHashSetNameException ex) {
Logger.getLogger(HashDbCreateDatabaseDialog.class.getName()).log(Level.WARNING, errorMessage, ex);
JOptionPane.showMessageDialog(this, ex.getMessage());
return;
}
catch (HashDbManager.HashDatabaseAlreadyAddedException ex) {
Logger.getLogger(HashDbCreateDatabaseDialog.class.getName()).log(Level.WARNING, errorMessage, ex);
JOptionPane.showMessageDialog(this, ex.getMessage());
return;
}
catch (HashDbManager.IllegalHashDatabaseFileNameExtensionException ex) {
Logger.getLogger(HashDbCreateDatabaseDialog.class.getName()).log(Level.WARNING, errorMessage, ex);
JOptionPane.showMessageDialog(this, ex.getMessage());
return;
}
catch (TskCoreException ex) {
Logger.getLogger(HashDbCreateDatabaseDialog.class.getName()).log(Level.SEVERE, errorMessage, ex);
JOptionPane.showMessageDialog(this, "Failed to create the hash database.");
JOptionPane.showMessageDialog(this, "Failed to create the hash database.", "Create Hash Database Error", JOptionPane.ERROR_MESSAGE);
return;
}
dispose();
}//GEN-LAST:event_saveAsButtonActionPerformed
private void searchDuringIngestCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_searchDuringIngestCheckboxActionPerformed
sendIngestMessagesCheckbox.setEnabled(searchDuringIngestCheckbox.isSelected());
if (!searchDuringIngestCheckbox.isSelected()) {
sendIngestMessagesCheckbox.setSelected(false);
}
}//GEN-LAST:event_searchDuringIngestCheckboxActionPerformed
}//GEN-LAST:event_okButtonActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.ButtonGroup buttonGroup1;
private javax.swing.JButton cancelButton;
private javax.swing.JTextField databasePathTextField;
private javax.swing.JTextField hashSetNameTextField;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel2;
private javax.swing.JLabel jLabel3;
private javax.swing.JRadioButton knownBadRadioButton;
private javax.swing.JRadioButton knownRadioButton;
private javax.swing.JButton okButton;
private javax.swing.JButton saveAsButton;
private javax.swing.JCheckBox searchDuringIngestCheckbox;
private javax.swing.JCheckBox sendIngestMessagesCheckbox;
@@ -27,47 +27,61 @@ import org.sleuthkit.autopsy.coreutils.Logger;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.JFrame;
import org.sleuthkit.datamodel.TskCoreException;
import org.apache.commons.io.FilenameUtils;
import org.sleuthkit.autopsy.hashdatabase.HashDbManager.KnownFilesType;
import org.sleuthkit.autopsy.hashdatabase.HashDbManager.HashDb.KnownFilesType;
import org.sleuthkit.autopsy.hashdatabase.HashDbManager.HashDb;
import org.sleuthkit.autopsy.hashdatabase.HashDbManager.HashDatabaseDoesNotExistException;
import org.sleuthkit.autopsy.hashdatabase.HashDbManager.DuplicateHashSetNameException;
import org.sleuthkit.autopsy.hashdatabase.HashDbManager.HashDatabaseAlreadyAddedException;
/**
* Instances of this class allow a user to select a hash database for import.
* Instances of this class allow a user to select an existing hash database and
* add it to the set of hash databases used to classify files as unknown, known,
* or known bad.
*/
final class HashDbImportDatabaseDialog extends javax.swing.JDialog {
private JFileChooser fileChooser = new JFileChooser();
private String selectedFilePath = "";
private HashDb selectedHashDb;
HashDbImportDatabaseDialog() {
super(new javax.swing.JFrame(), "Import Hash Database", true);
setResizable(false);
initComponents();
customizeComponents();
}
private HashDb selectedHashDb = null;
void customizeComponents() {
/**
* Displays a dialog that allows a user to select an existing hash database
* and add it to the set of hash databases used to classify files as unknown,
* known, or known bad.
*/
HashDbImportDatabaseDialog() {
super(new JFrame(), "Import Hash Database", true);
initFileChooser();
initComponents();
display();
}
/**
* Get the hash database imported by the user, if any.
* @return A HashDb object or null.
*/
HashDb getHashDatabase() {
return selectedHashDb;
}
private void initFileChooser() {
fileChooser.setDragEnabled(false);
fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
String[] EXTENSION = new String[] { "txt", "kdb", "idx", "hash", "Hash", "hsh"};
FileNameExtensionFilter filter = new FileNameExtensionFilter("Hash Database File", EXTENSION);
fileChooser.setFileFilter(filter);
fileChooser.setMultiSelectionEnabled(false);
}
HashDb doDialog() {
selectedHashDb = null;
// Center and display the dialog.
Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize();
setLocation((screenDimension.width - getSize().width) / 2, (screenDimension.height - getSize().height) / 2);
this.setVisible(true);
return selectedHashDb;
fileChooser.setMultiSelectionEnabled(false);
}
private void display() {
Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize();
setLocation((screenDimension.width - getSize().width) / 2, (screenDimension.height - getSize().height) / 2);
setVisible(true);
}
private static String shortenPath(String path) {
String shortenedPath = path;
if (shortenedPath.length() > 50){
@@ -260,11 +274,13 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog {
}//GEN-LAST:event_openButtonActionPerformed
private void knownRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_knownRadioButtonActionPerformed
searchDuringIngestCheckbox.setSelected(true);
sendIngestMessagesCheckbox.setSelected(false);
sendIngestMessagesCheckbox.setEnabled(false);
}//GEN-LAST:event_knownRadioButtonActionPerformed
private void knownBadRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_knownBadRadioButtonActionPerformed
searchDuringIngestCheckbox.setSelected(true);
sendIngestMessagesCheckbox.setSelected(true);
sendIngestMessagesCheckbox.setEnabled(true);
}//GEN-LAST:event_knownBadRadioButtonActionPerformed
@@ -274,19 +290,21 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog {
}//GEN-LAST:event_cancelButtonActionPerformed
private void okButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed
if(selectedFilePath.isEmpty()) {
JOptionPane.showMessageDialog(this, "A hash database file path must be selected.");
return;
}
// Note that the error handlers in this method call return without disposing of the
// dialog to allow the user to try again, if desired.
if(hashSetNameTextField.getText().isEmpty()) {
JOptionPane.showMessageDialog(this, "A hash set name must be entered..");
JOptionPane.showMessageDialog(this, "A hash set name must be entered.", "Import Hash Database Error", JOptionPane.ERROR_MESSAGE);
return;
}
if(selectedFilePath.isEmpty()) {
JOptionPane.showMessageDialog(this, "A hash database file path must be selected.", "Import Hash Database Error", JOptionPane.ERROR_MESSAGE);
return;
}
File file = new File(selectedFilePath);
if (!file.exists()) {
JOptionPane.showMessageDialog(this, "The selected hash database does not exist.");
JOptionPane.showMessageDialog(this, "The selected hash database does not exist.", "Import Hash Database Error", JOptionPane.ERROR_MESSAGE);
return;
}
@@ -298,16 +316,22 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog {
type = KnownFilesType.KNOWN_BAD;
}
String errorMessage = "Failed to open hash database at " + selectedFilePath + ".";
try {
selectedHashDb = HashDb.openHashDatabase(hashSetNameTextField.getText(), selectedFilePath, searchDuringIngestCheckbox.isSelected(), sendIngestMessagesCheckbox.isSelected(), type);
selectedHashDb = HashDbManager.getInstance().addExistingHashDatabase(hashSetNameTextField.getText(), selectedFilePath, searchDuringIngestCheckbox.isSelected(), sendIngestMessagesCheckbox.isSelected(), type);
}
catch (TskCoreException ex) {
Logger.getLogger(HashDbImportDatabaseDialog.class.getName()).log(Level.WARNING, "Failed to open hash database at " + selectedFilePath, ex);
JOptionPane.showMessageDialog(this, "Failed to import the selected database.\nPlease verify that the selected file is a hash database.");
catch (HashDatabaseDoesNotExistException | DuplicateHashSetNameException | HashDatabaseAlreadyAddedException ex) {
Logger.getLogger(HashDbImportDatabaseDialog.class.getName()).log(Level.WARNING, errorMessage, ex);
JOptionPane.showMessageDialog(this, ex.getMessage(), "Import Hash Database Error", JOptionPane.ERROR_MESSAGE);
return;
}
}
catch (TskCoreException ex) {
Logger.getLogger(HashDbCreateDatabaseDialog.class.getName()).log(Level.SEVERE, errorMessage, ex);
JOptionPane.showMessageDialog(this, errorMessage, "Import Hash Database Error", JOptionPane.ERROR_MESSAGE);
return;
}
this.dispose();
dispose();
}//GEN-LAST:event_okButtonActionPerformed
private void searchDuringIngestCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_searchDuringIngestCheckboxActionPerformed
@@ -42,6 +42,7 @@ import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskData;
import org.sleuthkit.datamodel.TskException;
import org.sleuthkit.autopsy.hashdatabase.HashDbManager.HashDb;
public class HashDbIngestModule extends IngestModuleAbstractFile {
private static HashDbIngestModule instance = null;
@@ -138,9 +139,9 @@ public class HashDbIngestModule extends IngestModuleAbstractFile {
skCase = Case.getCurrentCase().getSleuthkitCase();
HashDbManager hashDbManager = HashDbManager.getInstance();
getHashSetsUsableForIngest(hashDbManager.getKnownBadHashSets(), knownBadHashSets);
getHashSetsUsableForIngest(hashDbManager.getKnownHashSets(), knownHashSets);
calcHashesIsSet = hashDbManager.shouldAlwaysCalculateHashes();
getHashSetsUsableForIngest(hashDbManager.getKnownBadFileHashSets(), knownBadHashSets);
getHashSetsUsableForIngest(hashDbManager.getKnownFileHashSets(), knownHashSets);
calcHashesIsSet = hashDbManager.getAlwaysCalculateHashes();
if (knownHashSets.isEmpty()) {
services.postMessage(IngestMessage.createWarningMessage(++messageId, this, "No known hash database set", "Known file search will not be executed."));
@@ -155,14 +156,14 @@ public class HashDbIngestModule extends IngestModuleAbstractFile {
assert hashDbsForIngest != null;
hashDbsForIngest.clear();
for (HashDb db : hashDbs) {
if (db.getUseForIngest()) {
if (db.getSearchDuringIngest()) {
try {
if (db.hasLookupIndex()) {
hashDbsForIngest.add(db);
}
}
catch (TskCoreException ex) {
logger.log(Level.WARNING, "Error get index status for hash database at " +db.getDatabasePath(), ex);
logger.log(Level.WARNING, "Error getting index status for " + db.getHashSetName() +" hash database", ex);
}
}
}
@@ -211,7 +212,7 @@ public class HashDbIngestModule extends IngestModuleAbstractFile {
for (HashDb db : knownBadHashSets) {
try {
long lookupstart = System.currentTimeMillis();
if (db.hasHashOfContent(file)) {
if (db.hasMd5HashOf(file)) {
foundBad = true;
knownBadCount += 1;
try {
@@ -223,7 +224,7 @@ public class HashDbIngestModule extends IngestModuleAbstractFile {
ret = ProcessResult.ERROR;
}
String hashSetName = db.getHashSetName();
postHashSetHitToBlackboard(file, md5Hash, hashSetName, db.getShowInboxMessages());
postHashSetHitToBlackboard(file, md5Hash, hashSetName, db.getSendIngestMessages());
}
lookuptime += (System.currentTimeMillis() - lookupstart);
} catch (TskException ex) {
@@ -241,7 +242,7 @@ public class HashDbIngestModule extends IngestModuleAbstractFile {
for (HashDb db : knownHashSets) {
try {
long lookupstart = System.currentTimeMillis();
if (db.hasHashOfContent(file)) {
if (db.hasMd5HashOf(file)) {
try {
skCase.setKnown(file, TskData.FileKnown.KNOWN);
break;
@@ -16,26 +16,22 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.hashdatabase;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
import org.sleuthkit.autopsy.coreutils.XMLUtil;
import org.sleuthkit.datamodel.TskCoreException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
@@ -54,48 +50,28 @@ import org.sleuthkit.datamodel.HashInfo;
import org.sleuthkit.datamodel.SleuthkitJNI;
import org.sleuthkit.datamodel.TskCoreException;
/**
* This class is a singleton that manages the set of hash databases
* used to identify files as known files or known bad files.
* This class implements a singleton that manages the set of hash databases
* used to classify files as unknown, known or known bad.
*/
public class HashDbManager {
/**
* Characterizes the files whose hashes are stored in a hash database.
*/
public enum KnownFilesType{
KNOWN("Known"),
KNOWN_BAD("Known Bad");
private String displayName;
private KnownFilesType(String displayName) {
this.displayName = displayName;
}
public String getDisplayName() {
return this.displayName;
}
}
// RJCTODO: Consider making these local
private static final String ROOT_EL = "hash_sets";
private static final String SET_EL = "hash_set";
private static final String SET_NAME_ATTR = "name";
private static final String SET_TYPE_ATTR = "type";
private static final String SET_USE_FOR_INGEST_ATTR = "use_for_ingest";
private static final String SET_SHOW_INBOX_MESSAGES = "show_inbox_messages";
private static final String PATH_EL = "hash_set_path";
private static final String CUR_HASHSETS_FILE_NAME = "hashsets.xml";
private static final String XSDFILE = "HashsetsSchema.xsd";
private static final String ROOT_ELEMENT = "hash_sets";
private static final String SET_ELEMENT = "hash_set";
private static final String SET_NAME_ATTRIBUTE = "name";
private static final String SET_TYPE_ATTRIBUTE = "type";
private static final String SEARCH_DURING_INGEST_ATTRIBUTE = "use_for_ingest";
private static final String SEND_INGEST_MESSAGES_ATTRIBUTE = "show_inbox_messages";
private static final String PATH_ELEMENT = "hash_set_path";
private static final String CONFIG_FILE_NAME = "hashsets.xml";
private static final String XSD_FILE_NAME = "HashsetsSchema.xsd";
private static final String ENCODING = "UTF-8";
private static final String SET_CALC = "hash_calculate";
private static final String SET_VALUE = "value";
private static final String ALWAYS_CALCULATE_HASHES_ELEMENT = "hash_calculate";
private static final String VALUE_ATTRIBUTE = "value";
private static final String HASH_DATABASE_FILE_EXTENSON = "kdb";
private static final String LEGACY_INDEX_FILE_EXTENSION = "-md5.idx";
private static final Logger logger = Logger.getLogger(HashDbManager.class.getName());
private static HashDbManager instance;
private final String configFilePath = PlatformUtil.getUserConfigDirectory() + File.separator + CUR_HASHSETS_FILE_NAME;
private final String configFilePath = PlatformUtil.getUserConfigDirectory() + File.separator + CONFIG_FILE_NAME;
private List<HashDb> knownHashSets = new ArrayList<>();
private List<HashDb> knownBadHashSets = new ArrayList<>();
private Set<String> hashSetNames = new HashSet<>();
@@ -118,171 +94,209 @@ public class HashDbManager {
}
}
private boolean hashSetsConfigurationFileExists() {
File f = new File(configFilePath);
return f.exists() && f.canRead() && f.canWrite();
}
/**
* Gets the extension, without the dot separator, that the SleuthKit requires
* for hash database files that combine the database and the index.
*/
public static String getHashDatabaseFileExtension() {
return HASH_DATABASE_FILE_EXTENSON;
}
public class DuplicateHashSetNameException extends Exception {
private DuplicateHashSetNameException() {
super("The hash set name has already been used for another hash database.");
private DuplicateHashSetNameException(String hashSetName) {
super("The hash set name '"+ hashSetName +"' has already been used for another hash database.");
}
}
public class HashDatabaseDoesNotExistException extends Exception {
private HashDatabaseDoesNotExistException() {
super("Attempt to add a hash database that does not exist to the configuration");
private HashDatabaseDoesNotExistException(String path) {
super("No hash database found at\n" + path);
}
}
public class FileAlreadyExistsException extends Exception {
private FileAlreadyExistsException() {
super("A hash database file already exists at the selected location.");
public class HashDatabaseFileAlreadyExistsException extends Exception {
private HashDatabaseFileAlreadyExistsException(String path) {
super("A file already exists at\n" + path);
}
}
public class HashDatabaseAlreadyAddedException extends Exception {
private HashDatabaseAlreadyAddedException() {
super("The hash database has already been created.");
private HashDatabaseAlreadyAddedException(String path) {
super("The hash database at\n" + path + "\nhas already been created or imported.");
}
}
public class IllegalHashDatabaseFileNameExtensionException extends Exception {
private IllegalHashDatabaseFileNameExtensionException() {
super("The hash database file must have a ." + getHashDatabaseFileExtension() + " extension.");
super("The hash database file name must have a ." + getHashDatabaseFileExtension() + " extension.");
}
}
/**
* Adds an existing hash database to the set of hash databases used to classify files as known or known bad.
* Does not save the configuration - the configuration is only saved on demand to support cancellation of
* configuration panels.
* @param hashSetName Name used to represent the hash database in user interface components.
* @param filePath Full path to either a hash database file or a hash database index file.
* @param path Full path to either a hash database file or a hash database index file.
* @param searchDuringIngest A flag indicating whether or not the hash database should be searched during ingest.
* @param sendIngestMessages A flag indicating whether hash set hit messages should be sent as ingest messages.
* @param knownFilesType The classification to apply to files whose hashes are found in the hash database.
* @return A HashDb object representation of the hash database.
* @return A HashDb representing the hash database.
* @throws HashDatabaseDoesNotExistException, DuplicateHashSetNameException, HashDatabaseAlreadyAddedException, TskCoreException
*/
public synchronized HashDb addExistingHashDatabase(String hashSetName, String filePath, boolean searchDuringIngest, boolean sendIngestMessages, KnownFilesType knownFilesType) throws HashDatabaseDoesNotExistException, DuplicateHashSetNameException, HashDatabaseAlreadyAddedException, TskCoreException {
if (new File(filePath).exists()) {
throw new HashDatabaseDoesNotExistException();
public synchronized HashDb addExistingHashDatabase(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType) throws HashDatabaseDoesNotExistException, DuplicateHashSetNameException, HashDatabaseAlreadyAddedException, TskCoreException {
if (!new File(path).exists()) {
throw new HashDatabaseDoesNotExistException(path);
}
if (hashSetPaths.contains(path)) {
throw new HashDatabaseAlreadyAddedException(path);
}
if (hashSetNames.contains(hashSetName)) {
throw new DuplicateHashSetNameException();
throw new DuplicateHashSetNameException(hashSetName);
}
if (hashSetPaths.contains(filePath)) {
throw new HashDatabaseAlreadyAddedException();
}
int handle = SleuthkitJNI.openHashDatabase(filePath);
HashDb hashDb = new HashDb(handle, SleuthkitJNI.getHashDatabasePath(handle), SleuthkitJNI.getHashDatabaseIndexPath(handle), hashSetName, searchDuringIngest, sendIngestMessages, knownFilesType);
addToConfiguration(hashDb);
return hashDb;
return addHashDatabase(SleuthkitJNI.openHashDatabase(path), hashSetName, searchDuringIngest, sendIngestMessages, knownFilesType);
}
/**
* Adds a new hash database to the set of hash databases used to classify files as known or known bad.
* Does not save the configuration - the configuration is only saved on demand to support cancellation of
* configuration panels.
* @param hashSetName Hash set name used to represent the hash database in user interface components.
* @param filePath Full path to the database file to be created. The file name component of the path must have a ".kdb" extension.
* @param useForIngest A flag indicating whether or not the data base should be used during the file ingest process.
* @param showInboxMessages A flag indicating whether messages indicating lookup hits should be sent to the application in box.
* @param hashSetType The type of hash set to associate with the database.
* @return A HashDb object representation of the opened hash database.
* @param path Full path to the database file to be created.
* @param searchDuringIngest A flag indicating whether or not the hash database should be searched during ingest.
* @param sendIngestMessages A flag indicating whether hash set hit messages should be sent as ingest messages.
* @param knownFilesType The classification to apply to files whose hashes are found in the hash database.
* @return A HashDb representing the hash database.
* @throws TskCoreException
*/
public synchronized HashDb addNewHashDatabase(String hashSetName, String filePath, boolean useForIngest, boolean showInboxMessages, KnownFilesType knownFilesType) throws FileAlreadyExistsException, DuplicateHashSetNameException, HashDatabaseAlreadyAddedException, IllegalHashDatabaseFileNameExtensionException, TskCoreException {
File file = new File(filePath);
public synchronized HashDb addNewHashDatabase(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType) throws HashDatabaseFileAlreadyExistsException, IllegalHashDatabaseFileNameExtensionException, DuplicateHashSetNameException, HashDatabaseAlreadyAddedException, TskCoreException {
File file = new File(path);
if (file.exists()) {
throw new FileAlreadyExistsException();
throw new HashDatabaseFileAlreadyExistsException(path);
}
if (!FilenameUtils.getExtension(file.getName()).equalsIgnoreCase(HASH_DATABASE_FILE_EXTENSON)) {
throw new IllegalHashDatabaseFileNameExtensionException();
}
if (hashSetPaths.contains(path)) {
throw new HashDatabaseAlreadyAddedException(path);
}
if (hashSetNames.contains(hashSetName)) {
throw new DuplicateHashSetNameException();
throw new DuplicateHashSetNameException(hashSetName);
}
if (hashSetPaths.contains(filePath)) {
throw new HashDatabaseAlreadyAddedException();
}
int handle = SleuthkitJNI.createHashDatabase(filePath);
HashDb hashDb = new HashDb(handle, SleuthkitJNI.getHashDatabasePath(handle), SleuthkitJNI.getHashDatabaseIndexPath(handle), hashSetName, useForIngest, showInboxMessages, knownFilesType);
addToConfiguration(hashDb);
return hashDb;
return addHashDatabase(SleuthkitJNI.createHashDatabase(path), hashSetName, searchDuringIngest, sendIngestMessages, knownFilesType);
}
private void addToConfiguration(HashDb hashDb) {
private HashDb addHashDatabase(int handle, String hashSetName, boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType) throws TskCoreException {
HashDb hashDb = new HashDb(handle, hashSetName, searchDuringIngest, sendIngestMessages, knownFilesType);
// Get the paths before updating the collections since the path
// getting methods may throw.
String databasePath = hashDb.getDatabasePath();
String indexPath = hashDb.getIndexPath();
// Update the collections used to ensure that hash set names are unique
// and the same database is not added to the configuration more than once.
hashSetNames.add(hashDb.getHashSetName());
hashSetPaths.add(hashDb.getDatabasePath());
hashSetPaths.add(hashDb.getIndexPath());
hashSetPaths.add(indexPath);
if (!hashDb.hasIndexOnly()) {
hashSetPaths.add(databasePath);
}
// Add the hash database to the appropriate collection for its type.
if (hashDb.getKnownFilesType() == HashDb.KnownFilesType.KNOWN) {
knownHashSets.add(hashDb);
}
else {
knownBadHashSets.add(hashDb);
}
}
return hashDb;
}
/**
* Removes a hash database from the configuration. Does not save the
* configuration - the configuration is only saved on demand to support
* cancellation of configuration panels.
* Removes a hash database from the set of hash databases used to classify
* files as known or known bad. Does not save the configuration - the
* configuration is only saved on demand to support cancellation of
* configuration panels.
* @throws TskCoreException
*/
public synchronized void removeHashDatabase(HashDb hashDb) {
try {
hashDb.close();
}
catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error closing hash database at " + hashDb.getDatabasePath(), ex);
}
// First remove the database from whichever hash set list it occupies,
// and remove its hash set name from the hash set used to ensure unique
// hash set names are used. These operations will succeed and constitute
// a mostly effective removal, even if the subsequent operations fail.
knownHashSets.remove(hashDb);
knownBadHashSets.remove(hashDb);
hashSetNames.remove(hashDb.getHashSetName());
// Now undertake the operations that could fail.
try {
hashSetPaths.remove(hashDb.getIndexPath());
}
catch (TskCoreException ex) {
Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error getting index path of " + hashDb.getHashSetName() + " hash database when removing the database", ex);
}
try {
if (!hashDb.hasIndexOnly()) {
hashSetPaths.remove(hashDb.getDatabasePath());
}
}
catch (TskCoreException ex) {
Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error getting database path of " + hashDb.getHashSetName() + " hash database when removing the database", ex);
}
try {
hashDb.close();
}
catch (TskCoreException ex) {
Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error closing " + hashDb.getHashSetName() + " hash database when removing the database", ex);
}
}
/**
* Gets all of the configured hash sets.
* @return A list, possibly empty, of HashDb objects representing the hash
* sets.
* Gets all of the hash databases used to classify files as known or known bad.
* @return A list, possibly empty, of hash databases.
*/
public synchronized List<HashDb> getAllHashSets() {
List<HashDb> hashDbs = new ArrayList<>();
hashDbs.addAll(knownHashSets);
hashDbs.addAll(knownBadHashSets);
return Collections.unmodifiableList(hashDbs);
return hashDbs;
}
/**
* Gets the configured known files hash sets.
* @return A list, possibly empty, of HashDb objects.
* Gets all of the hash databases used to classify files as known.
* @return A list, possibly empty, of hash databases.
*/
public synchronized List<HashDb> getKnownHashSets() {
return Collections.unmodifiableList(knownHashSets);
public synchronized List<HashDb> getKnownFileHashSets() {
List<HashDb> hashDbs = new ArrayList<>();
hashDbs.addAll(knownHashSets);
return hashDbs;
}
/**
* Gets the configured known bad files hash sets.
* @return A list, possibly empty, of HashDb objects.
* Gets all of the hash databases used to classify files as known bad.
* @return A list, possibly empty, of hash databases.
*/
public synchronized List<HashDb> getKnownBadHashSets() {
return Collections.unmodifiableList(knownBadHashSets);
public synchronized List<HashDb> getKnownBadFileHashSets() {
List<HashDb> hashDbs = new ArrayList<>();
hashDbs.addAll(knownBadHashSets);
return hashDbs;
}
/**
* Gets all of the configured hash sets that accept updates.
* @return A list, possibly empty, of HashDb objects.
/**
* Gets all of the hash databases that accept updates.
* @return A list, possibly empty, of hash databases.
*/
public synchronized List<HashDb> getUpdateableHashSets() {
List<HashDb> updateableDbs = getUpdateableHashSets(knownHashSets);
updateableDbs.addAll(getUpdateableHashSets(knownBadHashSets));
return Collections.unmodifiableList(updateableDbs);
return updateableDbs;
}
private List<HashDb> getUpdateableHashSets(List<HashDb> hashDbs) {
@@ -294,25 +308,25 @@ public class HashDbManager {
}
}
catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error checking updateable status of hash database at " + db.getDatabasePath(), ex);
Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error checking updateable status of " + db.getHashSetName() + " hash database", ex);
}
}
return updateableDbs;
}
}
/**
* Sets the value for the flag that indicates whether hashes should be calculated
* for content even if no hash databases are configured.
*/
public synchronized void alwaysCalculateHashes(boolean alwaysCalculateHashes) {
public synchronized void setAlwaysCalculateHashes(boolean alwaysCalculateHashes) {
this.alwaysCalculateHashes = alwaysCalculateHashes;
}
/**
* Accesses the flag that indicates whether hashes should be calculated
* Gets the flag that indicates whether hashes should be calculated
* for content even if no hash databases are configured.
*/
public synchronized boolean shouldAlwaysCalculateHashes() {
public synchronized boolean getAlwaysCalculateHashes() {
return alwaysCalculateHashes;
}
@@ -333,6 +347,7 @@ public class HashDbManager {
closeHashDatabases(knownHashSets);
closeHashDatabases(knownBadHashSets);
hashSetNames.clear();
hashSetPaths.clear();
if (hashSetsConfigurationFileExists()) {
readHashSetsConfigurationFromDisk();
@@ -348,7 +363,7 @@ public class HashDbManager {
}
}
catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error closing hash database at " + dbPath, ex);
Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error closing hash database at " + dbPath, ex);
}
hashDbs.clear();
}
@@ -359,33 +374,30 @@ public class HashDbManager {
try {
DocumentBuilder docBuilder = dbfac.newDocumentBuilder();
Document doc = docBuilder.newDocument();
Element rootEl = doc.createElement(ROOT_EL);
Element rootEl = doc.createElement(ROOT_ELEMENT);
doc.appendChild(rootEl);
writeHashDbsToDisk(doc, rootEl, knownHashSets);
writeHashDbsToDisk(doc, rootEl, knownBadHashSets);
String calcValue = Boolean.toString(alwaysCalculateHashes);
Element setCalc = doc.createElement(SET_CALC);
setCalc.setAttribute(SET_VALUE, calcValue);
Element setCalc = doc.createElement(ALWAYS_CALCULATE_HASHES_ELEMENT);
setCalc.setAttribute(VALUE_ATTRIBUTE, calcValue);
rootEl.appendChild(setCalc);
success = XMLUtil.saveDoc(HashDbManager.class, configFilePath, ENCODING, doc);
}
catch (ParserConfigurationException e) {
logger.log(Level.SEVERE, "Error saving hash databases", e);
Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error saving hash databases", e);
}
return success;
}
private static void writeHashDbsToDisk(Document doc, Element rootEl, List<HashDb> hashDbs) {
for (HashDb db : hashDbs) {
Element setEl = doc.createElement(SET_EL);
setEl.setAttribute(SET_NAME_ATTR, db.getHashSetName());
setEl.setAttribute(SET_TYPE_ATTR, db.getKnownFilesType().toString());
setEl.setAttribute(SET_USE_FOR_INGEST_ATTR, Boolean.toString(db.getUseForIngest()));
setEl.setAttribute(SET_SHOW_INBOX_MESSAGES, Boolean.toString(db.getShowInboxMessages()));
String path = null;
// Get the path for the hash database before writing anything, in
// case an exception is thrown.
String path;
try {
if (db.hasIndexOnly()) {
path = db.getIndexPath();
@@ -393,21 +405,32 @@ public class HashDbManager {
else {
path = db.getDatabasePath();
}
Element pathEl = doc.createElement(PATH_EL);
pathEl.setTextContent(path);
setEl.appendChild(pathEl);
rootEl.appendChild(setEl);
}
catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error getting path of hash database " + db.getHashSetName() + ", unable to save configuration", ex);
Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error getting path of hash database " + db.getHashSetName() + ", discarding from hash database configuration", ex);
continue;
}
Element setElement = doc.createElement(SET_ELEMENT);
setElement.setAttribute(SET_NAME_ATTRIBUTE, db.getHashSetName());
setElement.setAttribute(SET_TYPE_ATTRIBUTE, db.getKnownFilesType().toString());
setElement.setAttribute(SEARCH_DURING_INGEST_ATTRIBUTE, Boolean.toString(db.getSearchDuringIngest()));
setElement.setAttribute(SEND_INGEST_MESSAGES_ATTRIBUTE, Boolean.toString(db.getSendIngestMessages()));
Element pathElement = doc.createElement(PATH_ELEMENT);
pathElement.setTextContent(path);
setElement.appendChild(pathElement);
rootEl.appendChild(setElement);
}
}
// TODO: The return value from this function is never checked. Failure is not indicated to the user. Is this desired?
private boolean hashSetsConfigurationFileExists() {
File f = new File(configFilePath);
return f.exists() && f.canRead() && f.canWrite();
}
private boolean readHashSetsConfigurationFromDisk() {
// Open the XML document that implements the configuration file.
final Document doc = XMLUtil.loadDoc(HashDbManager.class, configFilePath, XSDFILE);
final Document doc = XMLUtil.loadDoc(HashDbManager.class, configFilePath, XSD_FILE_NAME);
if (doc == null) {
return false;
}
@@ -415,15 +438,15 @@ public class HashDbManager {
// Get the root element.
Element root = doc.getDocumentElement();
if (root == null) {
logger.log(Level.SEVERE, "Error loading hash sets: invalid file format.");
Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error loading hash sets: invalid file format.");
return false;
}
// Get the hash set elements.
NodeList setsNList = root.getElementsByTagName(SET_EL);
NodeList setsNList = root.getElementsByTagName(SET_ELEMENT);
int numSets = setsNList.getLength();
if(numSets == 0) {
logger.log(Level.WARNING, "No element hash_set exists.");
Logger.getLogger(HashDbManager.class.getName()).log(Level.WARNING, "No element hash_set exists.");
}
// Create HashDb objects for each hash set element.
@@ -433,9 +456,9 @@ public class HashDbManager {
for (int i = 0; i < numSets; ++i) {
Element setEl = (Element) setsNList.item(i);
String hashSetName = setEl.getAttribute(SET_NAME_ATTR);
String hashSetName = setEl.getAttribute(SET_NAME_ATTRIBUTE);
if (hashSetName.isEmpty()) {
logger.log(Level.SEVERE, SET_NAME_ATTR + attributeErrorMessage, i);
Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, SET_NAME_ATTRIBUTE + attributeErrorMessage, i);
continue;
}
@@ -452,71 +475,70 @@ public class HashDbManager {
hashSetName = newHashSetName;
}
String knownFilesType = setEl.getAttribute(SET_TYPE_ATTR);
String knownFilesType = setEl.getAttribute(SET_TYPE_ATTRIBUTE);
if(knownFilesType.isEmpty()) {
logger.log(Level.SEVERE, SET_TYPE_ATTR + attributeErrorMessage, i);
Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, SET_TYPE_ATTRIBUTE + attributeErrorMessage, i);
continue;
}
// Handle legacy known files types.
if (knownFilesType.equals("NSRL")) {
knownFilesType = KnownFilesType.KNOWN.toString();
knownFilesType = HashDb.KnownFilesType.KNOWN.toString();
}
final String useForIngest = setEl.getAttribute(SET_USE_FOR_INGEST_ATTR);
if (useForIngest.isEmpty()) {
logger.log(Level.SEVERE, SET_USE_FOR_INGEST_ATTR + attributeErrorMessage, i);
final String searchDuringIngest = setEl.getAttribute(SEARCH_DURING_INGEST_ATTRIBUTE);
if (searchDuringIngest.isEmpty()) {
Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, SEARCH_DURING_INGEST_ATTRIBUTE + attributeErrorMessage, i);
continue;
}
Boolean useForIngestFlag = Boolean.parseBoolean(useForIngest);
Boolean seearchDuringIngestFlag = Boolean.parseBoolean(searchDuringIngest);
final String showInboxMessages = setEl.getAttribute(SET_SHOW_INBOX_MESSAGES);
if (useForIngest.isEmpty()) {
logger.log(Level.SEVERE, SET_SHOW_INBOX_MESSAGES + attributeErrorMessage, i);
final String sendIngestMessages = setEl.getAttribute(SEND_INGEST_MESSAGES_ATTRIBUTE);
if (searchDuringIngest.isEmpty()) {
Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, SEND_INGEST_MESSAGES_ATTRIBUTE + attributeErrorMessage, i);
continue;
}
Boolean showInboxMessagesFlag = Boolean.parseBoolean(showInboxMessages);
Boolean sendIngestMessagesFlag = Boolean.parseBoolean(sendIngestMessages);
String dbPath;
NodeList pathsNList = setEl.getElementsByTagName(PATH_EL);
NodeList pathsNList = setEl.getElementsByTagName(PATH_ELEMENT);
if (pathsNList.getLength() > 0) {
Element pathEl = (Element) pathsNList.item(0); // Shouldn't be more than one.
dbPath = pathEl.getTextContent();
if (dbPath.isEmpty()) {
logger.log(Level.SEVERE, PATH_EL + elementErrorMessage, i);
Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, PATH_ELEMENT + elementErrorMessage, i);
continue;
}
}
else {
logger.log(Level.SEVERE, PATH_EL + elementErrorMessage, i);
Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, PATH_ELEMENT + elementErrorMessage, i);
continue;
}
dbPath = getValidFilePath(hashSetName, dbPath);
if (null != dbPath) {
try {
addHashSet(HashDb.openHashDatabase(hashSetName, dbPath, useForIngestFlag, showInboxMessagesFlag, KnownFilesType.valueOf(knownFilesType)));
hashSetNames.add(hashSetName);
addExistingHashDatabase(hashSetName, dbPath, seearchDuringIngestFlag, sendIngestMessagesFlag, HashDb.KnownFilesType.valueOf(knownFilesType));
}
catch (TskCoreException ex) {
catch (HashDatabaseDoesNotExistException | DuplicateHashSetNameException | HashDatabaseAlreadyAddedException | TskCoreException ex) {
Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error opening hash database", ex);
JOptionPane.showMessageDialog(null, "Unable to open " + dbPath + " hash database.", "Open Hash Database Error", JOptionPane.ERROR_MESSAGE);
}
}
else {
logger.log(Level.WARNING, "No valid path for hash_set at index {0}, cannot make instance of HashDb class", i);
Logger.getLogger(HashDbManager.class.getName()).log(Level.WARNING, "No valid path for hash_set at index {0}, cannot make instance of HashDb class", i);
}
}
// Get the element that stores the always calculate hashes flag.
NodeList calcList = root.getElementsByTagName(SET_CALC);
NodeList calcList = root.getElementsByTagName(ALWAYS_CALCULATE_HASHES_ELEMENT);
if (calcList.getLength() > 0) {
Element calcEl = (Element) calcList.item(0); // Shouldn't be more than one.
final String value = calcEl.getAttribute(SET_VALUE);
final String value = calcEl.getAttribute(VALUE_ATTRIBUTE);
alwaysCalculateHashes = Boolean.parseBoolean(value);
}
else {
logger.log(Level.WARNING, " element ");
Logger.getLogger(HashDbManager.class.getName()).log(Level.WARNING, " element ");
alwaysCalculateHashes = false;
}
@@ -566,7 +588,7 @@ public class HashDbManager {
filePath = f.getCanonicalPath();
}
catch (IOException ex) {
logger.log(Level.WARNING, "Couldn't get selected file path", ex);
Logger.getLogger(HashDbManager.class.getName()).log(Level.WARNING, "Couldn't get selected file path", ex);
}
}
return filePath;
@@ -576,6 +598,26 @@ public class HashDbManager {
* Instances of this class represent hash databases used to classify files as known or know bad.
*/
public static class HashDb {
/**
* Indicates how files with hashes stored in a particular hash database
* object should be classified.
*/
public enum KnownFilesType{
KNOWN("Known"),
KNOWN_BAD("Known Bad");
private String displayName;
private KnownFilesType(String displayName) {
this.displayName = displayName;
}
public String getDisplayName() {
return this.displayName;
}
}
/**
* Property change events published by hash database objects.
*/
@@ -584,53 +626,19 @@ public class HashDbManager {
}
private int handle;
private KnownFilesType knownFilesType;
private String databasePath;
private String indexPath;
private String hashSetName;
private boolean useForIngest;
private boolean sendHitMessages;
private boolean searchDuringIngest;
private boolean sendIngestMessages;
private KnownFilesType knownFilesType;
private boolean indexing;
private final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
/**
* Opens an existing hash database.
* @param hashSetName Name used to represent the hash database in user interface components.
* @param selectedFilePath Full path to either a hash database file or a hash database index file.
* @param useForIngest A flag indicating whether or not the hash database should be used during ingest.
* @param sendHitMessages A flag indicating whether hash set hit messages should be sent to the application in box.
* @param knownFilesType The classification to apply to files whose hashes are stored in the hash database.
* @return A HashDb object representation of the new hash database.
* @throws TskCoreException
*/
public static HashDb openHashDatabase(String hashSetName, String selectedFilePath, boolean useForIngest, boolean sendHitMessages, KnownFilesType knownFilesType) throws TskCoreException {
int handle = SleuthkitJNI.openHashDatabase(selectedFilePath);
return new HashDb(handle, SleuthkitJNI.getHashDatabasePath(handle), SleuthkitJNI.getHashDatabaseIndexPath(handle), hashSetName, useForIngest, sendHitMessages, knownFilesType);
}
/**
* Creates a new hash database.
* @param hashSetName Hash set name used to represent the hash database in user interface components.
* @param databasePath Full path to the database file to be created. The file name component of the path must have a ".kdb" extension.
* @param useForIngest A flag indicating whether or not the data base should be used during the file ingest process.
* @param showInboxMessages A flag indicating whether messages indicating lookup hits should be sent to the application in box.
* @param hashSetType The type of hash set to associate with the database.
* @return A HashDb object representation of the opened hash database.
* @throws TskCoreException
*/
public static HashDb createHashDatabase(String hashSetName, String databasePath, boolean useForIngest, boolean showInboxMessages, KnownFilesType knownFilesType) throws TskCoreException {
int handle = SleuthkitJNI.createHashDatabase(databasePath);
return new HashDb(handle, SleuthkitJNI.getHashDatabasePath(handle), SleuthkitJNI.getHashDatabaseIndexPath(handle), hashSetName, useForIngest, showInboxMessages, knownFilesType);
}
private HashDb(int handle, String databasePath, String indexPath, String name, boolean useForIngest, boolean sendHitMessages, KnownFilesType knownFilesType) {
this.databasePath = databasePath;
this.indexPath = indexPath;
this.hashSetName = name;
this.useForIngest = useForIngest;
this.sendHitMessages = sendHitMessages;
this.knownFilesType = knownFilesType;
private HashDb(int handle, String hashSetName, boolean useForIngest, boolean sendHitMessages, KnownFilesType knownFilesType) {
this.handle = handle;
this.hashSetName = hashSetName;
this.searchDuringIngest = useForIngest;
this.sendIngestMessages = sendHitMessages;
this.knownFilesType = knownFilesType;
this.indexing = false;
}
@@ -652,45 +660,45 @@ public class HashDbManager {
return hashSetName;
}
public String getDatabasePath() {
return databasePath;
public String getDatabasePath() throws TskCoreException {
return SleuthkitJNI.getHashDatabasePath(handle);
}
public String getIndexPath() {
return indexPath;
public String getIndexPath() throws TskCoreException {
return SleuthkitJNI.getHashDatabaseIndexPath(handle);
}
public KnownFilesType getKnownFilesType() {
return knownFilesType;
}
public boolean getUseForIngest() {
return useForIngest;
public boolean getSearchDuringIngest() {
return searchDuringIngest;
}
void setUseForIngest(boolean useForIngest) {
this.useForIngest = useForIngest;
void setSearchDuringIngest(boolean useForIngest) {
this.searchDuringIngest = useForIngest;
}
public boolean getShowInboxMessages() {
return sendHitMessages;
public boolean getSendIngestMessages() {
return sendIngestMessages;
}
void setShowInboxMessages(boolean showInboxMessages) {
this.sendHitMessages = showInboxMessages;
void setSendIngestMessages(boolean showInboxMessages) {
this.sendIngestMessages = showInboxMessages;
}
public boolean hasLookupIndex() throws TskCoreException {
return SleuthkitJNI.hashDatabaseHasLookupIndex(handle);
}
public boolean canBeReindexed() throws TskCoreException {
return SleuthkitJNI.hashDatabaseCanBeReindexed(handle);
}
public boolean hasIndexOnly() throws TskCoreException {
return SleuthkitJNI.hashDatabaseHasLegacyLookupIndexOnly(handle);
}
public boolean canBeReIndexed() throws TskCoreException {
return SleuthkitJNI.hashDatabaseCanBeReindexed(handle);
}
/**
* Indicates whether the hash database accepts updates.
@@ -705,8 +713,8 @@ public class HashDbManager {
* @param content The content for which the calculated hashes, if any, are to be added to the hash database.
* @throws TskCoreException
*/
public void add(Content content) throws TskCoreException {
add(content, null);
public void addHashes(Content content) throws TskCoreException {
addHashes(content, null);
}
/**
@@ -715,7 +723,7 @@ public class HashDbManager {
* @param comment A comment to associate with the hashes, e.g., the name of the case in which the content was encountered.
* @throws TskCoreException
*/
public void add(Content content, String comment) throws TskCoreException {
public void addHashes(Content content, String comment) throws TskCoreException {
// TODO: This only works for AbstractFiles at present. Change when Content
// can be queried for hashes.
assert content instanceof AbstractFile;
@@ -728,13 +736,11 @@ public class HashDbManager {
}
}
public boolean hasHashOfContent(Content content) throws TskCoreException {
public boolean hasMd5HashOf(Content content) throws TskCoreException {
boolean result = false;
// TODO: This only works for AbstractFiles at present. Change when Content can be queried for hashes.
assert content instanceof AbstractFile;
if (content instanceof AbstractFile) {
AbstractFile file = (AbstractFile)content;
// TODO: Add support for SHA-1 and SHA-256 hashes.
if (null != file.getMd5Hash()) {
result = SleuthkitJNI.lookupInHashDatabase(file.getMd5Hash(), handle);
}
@@ -783,7 +789,6 @@ public class HashDbManager {
progress.switchToIndeterminate();
try {
SleuthkitJNI.createLookupIndexForHashDatabase(handle, deleteIndexFile);
indexPath = SleuthkitJNI.getHashDatabaseIndexPath(handle);
}
catch (TskCoreException ex) {
Logger.getLogger(HashDb.class.getName()).log(Level.SEVERE, "Error indexing hash database", ex);
@@ -800,7 +805,7 @@ public class HashDbManager {
}
}
public void close() throws TskCoreException {
private void close() throws TskCoreException {
SleuthkitJNI.closeHashDatabase(handle);
}
}
@@ -28,7 +28,7 @@
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
<Component id="jScrollPane2" alignment="1" pref="0" max="32767" attributes="1"/>
<Component id="calcHashesButton" alignment="1" max="32767" attributes="0"/>
<Component id="alwaysCalcHashesCheckbox" alignment="1" max="32767" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
@@ -46,7 +46,7 @@
<EmptySpace max="-2" attributes="0"/>
<Component id="jScrollPane2" min="-2" pref="55" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="32767" attributes="0"/>
<Component id="calcHashesButton" min="-2" max="-2" attributes="0"/>
<Component id="alwaysCalcHashesCheckbox" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
@@ -92,10 +92,10 @@
</Property>
</Properties>
</Component>
<Component class="javax.swing.JCheckBox" name="calcHashesButton">
<Component class="javax.swing.JCheckBox" name="alwaysCalcHashesCheckbox">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/hashdatabase/Bundle.properties" key="HashDbSimpleConfigPanel.calcHashesButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<ResourceString bundle="org/sleuthkit/autopsy/hashdatabase/Bundle.properties" key="HashDbSimpleConfigPanel.alwaysCalcHashesCheckbox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
@@ -30,6 +30,7 @@ import javax.swing.table.TableColumn;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.ingest.IngestManager;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.autopsy.hashdatabase.HashDbManager.HashDb;
/**
* Instances of this class provide a simplified UI for managing the hash sets configuration.
@@ -39,8 +40,8 @@ public class HashDbSimpleConfigPanel extends javax.swing.JPanel {
private HashDbsTableModel knownBadTableModel;
public HashDbSimpleConfigPanel() {
knownTableModel = new HashDbsTableModel(HashDbManager.getInstance().getKnownHashSets());
knownBadTableModel = new HashDbsTableModel(HashDbManager.getInstance().getKnownBadHashSets());
knownTableModel = new HashDbsTableModel(HashDbManager.getInstance().getKnownFileHashSets());
knownBadTableModel = new HashDbsTableModel(HashDbManager.getInstance().getKnownBadFileHashSets());
initComponents();
customizeComponents();
}
@@ -51,10 +52,10 @@ public class HashDbSimpleConfigPanel extends javax.swing.JPanel {
// Add a listener to the always calculate hashes checkbox component.
// The listener passes the user's selection on to the hash database manager.
calcHashesButton.addActionListener( new ActionListener() {
alwaysCalcHashesCheckbox.addActionListener( new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
HashDbManager.getInstance().alwaysCalculateHashes(calcHashesButton.isSelected());
HashDbManager.getInstance().setAlwaysCalculateHashes(alwaysCalcHashesCheckbox.isSelected());
}
});
@@ -82,33 +83,33 @@ public class HashDbSimpleConfigPanel extends javax.swing.JPanel {
public void refreshComponents() {
knownTableModel.refresh();
knownBadTableModel.refresh();
refreshAlwaysCalcHashesComponents();
refreshAlwaysCalcHashesCheckbox();
}
private void refreshAlwaysCalcHashesComponents() {
private void refreshAlwaysCalcHashesCheckbox() {
boolean noHashDbsConfiguredForIngest = true;
for (HashDb hashDb : HashDbManager.getInstance().getAllHashSets()) {
try {
if (hashDb.getUseForIngest()== true && hashDb.hasLookupIndex()) {
if (hashDb.getSearchDuringIngest()== true && hashDb.hasLookupIndex()) {
noHashDbsConfiguredForIngest = false;
break;
}
}
catch (TskCoreException ex) {
Logger.getLogger(HashDbSimpleConfigPanel.class.getName()).log(Level.SEVERE, "Error getting info for hash database at " + hashDb.getDatabasePath(), ex);
Logger.getLogger(HashDbSimpleConfigPanel.class.getName()).log(Level.SEVERE, "Error getting info for " + hashDb.getHashSetName() + " hash database", ex);
}
}
// If there are no hash databases configured for use during file ingest,
// default to always calculating hashes of the files.
if (noHashDbsConfiguredForIngest) {
calcHashesButton.setEnabled(true);
calcHashesButton.setSelected(true);
HashDbManager.getInstance().alwaysCalculateHashes(true);
alwaysCalcHashesCheckbox.setEnabled(true);
alwaysCalcHashesCheckbox.setSelected(true);
HashDbManager.getInstance().setAlwaysCalculateHashes(true);
} else {
calcHashesButton.setEnabled(false);
calcHashesButton.setSelected(false);
HashDbManager.getInstance().alwaysCalculateHashes(false);
alwaysCalcHashesCheckbox.setEnabled(false);
alwaysCalcHashesCheckbox.setSelected(false);
HashDbManager.getInstance().setAlwaysCalculateHashes(false);
}
}
@@ -137,7 +138,7 @@ public class HashDbSimpleConfigPanel extends javax.swing.JPanel {
public Object getValueAt(int rowIndex, int columnIndex) {
HashDb db = hashDbs.get(rowIndex);
if (columnIndex == 0) {
return db.getUseForIngest();
return db.getSearchDuringIngest();
} else {
return db.getHashSetName();
}
@@ -157,10 +158,10 @@ public class HashDbSimpleConfigPanel extends javax.swing.JPanel {
dbHasIndex = db.hasLookupIndex();
}
catch (TskCoreException ex) {
Logger.getLogger(HashDbSimpleConfigPanel.class.getName()).log(Level.SEVERE, "Error getting info for hash database at " + db.getDatabasePath(), ex);
Logger.getLogger(HashDbSimpleConfigPanel.class.getName()).log(Level.SEVERE, "Error getting info for " + db.getHashSetName() + " hash database", ex);
}
if(((Boolean) getValueAt(rowIndex, columnIndex)) || dbHasIndex) {
db.setUseForIngest((Boolean) aValue);
db.setSearchDuringIngest((Boolean) aValue);
}
else {
JOptionPane.showMessageDialog(HashDbSimpleConfigPanel.this, "Hash databases must be indexed before they can be used for ingest");
@@ -187,7 +188,7 @@ public class HashDbSimpleConfigPanel extends javax.swing.JPanel {
knownHashTable = new javax.swing.JTable();
knownBadHashDbsLabel = new javax.swing.JLabel();
knownHashDbsLabel = new javax.swing.JLabel();
calcHashesButton = new javax.swing.JCheckBox();
alwaysCalcHashesCheckbox = new javax.swing.JCheckBox();
jScrollPane2 = new javax.swing.JScrollPane();
knownBadHashTable = new javax.swing.JTable();
@@ -202,7 +203,7 @@ public class HashDbSimpleConfigPanel extends javax.swing.JPanel {
knownHashDbsLabel.setText(org.openide.util.NbBundle.getMessage(HashDbSimpleConfigPanel.class, "HashDbSimpleConfigPanel.knownHashDbsLabel.text")); // NOI18N
calcHashesButton.setText(org.openide.util.NbBundle.getMessage(HashDbSimpleConfigPanel.class, "HashDbSimpleConfigPanel.calcHashesButton.text")); // NOI18N
alwaysCalcHashesCheckbox.setText(org.openide.util.NbBundle.getMessage(HashDbSimpleConfigPanel.class, "HashDbSimpleConfigPanel.alwaysCalcHashesCheckbox.text")); // NOI18N
jScrollPane2.setBorder(javax.swing.BorderFactory.createEtchedBorder());
@@ -233,7 +234,7 @@ public class HashDbSimpleConfigPanel extends javax.swing.JPanel {
.addComponent(knownBadHashDbsLabel))
.addGap(0, 0, Short.MAX_VALUE))
.addComponent(jScrollPane2, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
.addComponent(calcHashesButton, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addComponent(alwaysCalcHashesCheckbox, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addContainerGap())
);
layout.setVerticalGroup(
@@ -248,13 +249,13 @@ public class HashDbSimpleConfigPanel extends javax.swing.JPanel {
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 55, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(calcHashesButton)
.addComponent(alwaysCalcHashesCheckbox)
.addContainerGap())
);
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JCheckBox calcHashesButton;
private javax.swing.JCheckBox alwaysCalcHashesCheckbox;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JScrollPane jScrollPane2;
private javax.swing.JLabel knownBadHashDbsLabel;
@@ -28,6 +28,7 @@ import java.util.logging.Level;
import javax.swing.JOptionPane;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.autopsy.hashdatabase.HashDbManager.HashDb;
/**
* This class exists as a stop-gap measure to force users to have an indexed database.