Merge branch 'develop' of https://github.com/sleuthkit/autopsy into 3845-ObjectDetectionModule

This commit is contained in:
William Schaefer 2018-06-08 10:49:10 -04:00
commit 9d2639a177
19 changed files with 1242 additions and 239 deletions

View File

@ -91,6 +91,10 @@
<get src="https://drive.google.com/uc?id=1bghoSm7z7nhmGIxlllyY1MMlbLntxm7n" dest="${test-input}/local_files_test.zip" skipexisting="true"/> <get src="https://drive.google.com/uc?id=1bghoSm7z7nhmGIxlllyY1MMlbLntxm7n" dest="${test-input}/local_files_test.zip" skipexisting="true"/>
<get src="https://drive.google.com/uc?id=1BrSiUQ1fzxFS9vIaK4mYKX6qIVp9kRWT" dest="${test-input}/password_detection_test.img" skipexisting="true"/> <get src="https://drive.google.com/uc?id=1BrSiUQ1fzxFS9vIaK4mYKX6qIVp9kRWT" dest="${test-input}/password_detection_test.img" skipexisting="true"/>
<get src="https://drive.google.com/uc?id=1HD8s4rculgHV1qZT5g80Kg7j4m1qccrN" dest="${test-input}/veracrypt_detection_test.vhd" skipexisting="true"/> <get src="https://drive.google.com/uc?id=1HD8s4rculgHV1qZT5g80Kg7j4m1qccrN" dest="${test-input}/veracrypt_detection_test.vhd" skipexisting="true"/>
<get src="https://drive.google.com/uc?id=1O5D09fFCFpXZqw0uLEs8kVLtfYTxqXAd" dest="${test-input}/commonfiles_image1_v1.vhd" skipexisting="true"/>
<get src="https://drive.google.com/uc?id=1rMP1QTI0LdppzdypbG-4BDwkKcR3tHXc" dest="${test-input}/commonfiles_image2_v1.vhd" skipexisting="true"/>
<get src="https://drive.google.com/uc?id=1OdwyJ2lru55ZPdvwzj3pq6sXIys27i4x" dest="${test-input}/commonfiles_image3_v1.vhd" skipexisting="true"/>
<get src="https://drive.google.com/uc?id=1GoF2x0km5AyFvE926ttN20lrMX1oLN7E" dest="${test-input}/commonfiles_image4_v1.vhd" skipexisting="true"/>
</target> </target>
<target name="get-deps" depends="init-ivy,getTSKJars,get-thirdparty-dependencies,get-InternalPythonModules, download-binlist,getTestDataFiles"> <target name="get-deps" depends="init-ivy,getTSKJars,get-thirdparty-dependencies,get-InternalPythonModules, download-binlist,getTestDataFiles">

View File

@ -1,70 +0,0 @@
/*
* Central Repository
*
* Copyright 2015-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.centralrepository.contentviewer;
import java.util.Objects;
/**
* Used as a key to ensure we eliminate duplicates from the result set by not overwriting CR correlation instances.
*/
final class ArtifactKey {
private final String dataSourceID;
private final String filePath;
ArtifactKey(String theDataSource, String theFilePath) {
dataSourceID = theDataSource;
filePath = theFilePath.toLowerCase();
}
/**
*
* @return the dataSourceID device ID
*/
String getDataSourceID() {
return dataSourceID;
}
/**
*
* @return the filPath including the filename and extension.
*/
String getFilePath() {
return filePath;
}
@Override
public boolean equals(Object other) {
if (other instanceof ArtifactKey) {
return ((ArtifactKey) other).getDataSourceID().equals(dataSourceID) && ((ArtifactKey) other).getFilePath().equals(filePath);
}
return false;
}
@Override
public int hashCode() {
//int hash = 7;
//hash = 67 * hash + this.dataSourceID.hashCode();
//hash = 67 * hash + this.filePath.hashCode();
return Objects.hash(dataSourceID, filePath);
}
}

View File

@ -18,7 +18,9 @@
*/ */
package org.sleuthkit.autopsy.centralrepository.contentviewer; package org.sleuthkit.autopsy.centralrepository.contentviewer;
import java.awt.Color;
import java.awt.Component; import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import java.io.BufferedWriter; import java.io.BufferedWriter;
@ -31,19 +33,30 @@ import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import java.util.logging.Level; import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.swing.GroupLayout;
import javax.swing.JFileChooser; import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JMenuItem; import javax.swing.JMenuItem;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
import static javax.swing.JOptionPane.DEFAULT_OPTION; import static javax.swing.JOptionPane.DEFAULT_OPTION;
import static javax.swing.JOptionPane.PLAIN_MESSAGE; import static javax.swing.JOptionPane.PLAIN_MESSAGE;
import static javax.swing.JOptionPane.ERROR_MESSAGE; import static javax.swing.JOptionPane.ERROR_MESSAGE;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.LayoutStyle;
import javax.swing.ListSelectionModel;
import javax.swing.filechooser.FileNameExtensionFilter; import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.table.TableCellRenderer; import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn; import javax.swing.table.TableColumn;
import org.openide.awt.Mnemonics;
import org.openide.nodes.Node; import org.openide.nodes.Node;
import org.openide.util.NbBundle;
import org.openide.util.NbBundle.Messages; import org.openide.util.NbBundle.Messages;
import org.openide.util.lookup.ServiceProvider; import org.openide.util.lookup.ServiceProvider;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
@ -65,14 +78,16 @@ import org.sleuthkit.datamodel.TskException;
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb; import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb;
import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskData; import org.sleuthkit.datamodel.TskData;
import org.sleuthkit.datamodel.TskDataException;
/** /**
* View correlation results from other cases * View correlation results from other cases
*/ */
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
@ServiceProvider(service = DataContentViewer.class, position = 8) @ServiceProvider(service = DataContentViewer.class, position = 8)
@Messages({"DataContentViewerOtherCases.title=Other Occurrences", @Messages({"DataContentViewerOtherCases.title=Other Occurrences",
"DataContentViewerOtherCases.toolTip=Displays instances of the selected file/artifact from other occurrences.",}) "DataContentViewerOtherCases.toolTip=Displays instances of the selected file/artifact from other occurrences.",})
public class DataContentViewerOtherCases extends javax.swing.JPanel implements DataContentViewer { public class DataContentViewerOtherCases extends JPanel implements DataContentViewer {
private final static Logger LOGGER = Logger.getLogger(DataContentViewerOtherCases.class.getName()); private final static Logger LOGGER = Logger.getLogger(DataContentViewerOtherCases.class.getName());
@ -451,12 +466,12 @@ public class DataContentViewerOtherCases extends javax.swing.JPanel implements D
* *
* @return A collection of correlated artifact instances from other cases * @return A collection of correlated artifact instances from other cases
*/ */
private Map<ArtifactKey, CorrelationAttributeInstance> getCorrelatedInstances(CorrelationAttribute corAttr, String dataSourceName, String deviceId) { private Map<UniquePathKey,CorrelationAttributeInstance> getCorrelatedInstances(CorrelationAttribute corAttr, String dataSourceName, String deviceId) {
// @@@ Check exception // @@@ Check exception
try { try {
final Case openCase = Case.getCurrentCase(); final Case openCase = Case.getCurrentCase();
String caseUUID = openCase.getName(); String caseUUID = openCase.getName();
HashMap<ArtifactKey, CorrelationAttributeInstance> artifactInstances = new HashMap<>(); HashMap<UniquePathKey,CorrelationAttributeInstance> artifactInstances = new HashMap<>();
if (EamDb.isEnabled()) { if (EamDb.isEnabled()) {
EamDb dbManager = EamDb.getInstance(); EamDb dbManager = EamDb.getInstance();
@ -464,8 +479,7 @@ public class DataContentViewerOtherCases extends javax.swing.JPanel implements D
.filter(artifactInstance -> !artifactInstance.getCorrelationCase().getCaseUUID().equals(caseUUID) .filter(artifactInstance -> !artifactInstance.getCorrelationCase().getCaseUUID().equals(caseUUID)
|| !artifactInstance.getCorrelationDataSource().getName().equals(dataSourceName) || !artifactInstance.getCorrelationDataSource().getName().equals(dataSourceName)
|| !artifactInstance.getCorrelationDataSource().getDeviceID().equals(deviceId)) || !artifactInstance.getCorrelationDataSource().getDeviceID().equals(deviceId))
.collect(Collectors.toMap( .collect(Collectors.toMap(correlationAttr -> new UniquePathKey(correlationAttr.getCorrelationDataSource().getDeviceID(), correlationAttr.getFilePath()),
correlationAttr -> new ArtifactKey(correlationAttr.getCorrelationDataSource().getDeviceID(), correlationAttr.getFilePath()),
correlationAttr -> correlationAttr))); correlationAttr -> correlationAttr)));
} }
@ -507,29 +521,59 @@ public class DataContentViewerOtherCases extends javax.swing.JPanel implements D
} }
private void addOrUpdateAttributeInstance(final Case openCase, Map<ArtifactKey, CorrelationAttributeInstance> artifactInstances, AbstractFile caseDbFile) throws TskCoreException, EamDbException { /**
CorrelationCase caze = new CorrelationCase(openCase.getNumber(), openCase.getDisplayName()); * Adds the file to the artifactInstances map if it does not already exist
CorrelationDataSource dataSource = CorrelationDataSource.fromTSKDataSource(caze, caseDbFile.getDataSource()); *
String filePath = caseDbFile.getParentPath() + caseDbFile.getName(); * @param autopsyCase
ArtifactKey instKey = new ArtifactKey(dataSource.getDeviceID(), filePath); * @param artifactInstances
CorrelationAttributeInstance caseDbInstance = new CorrelationAttributeInstance(caze, dataSource, filePath, "", caseDbFile.getKnown()); * @param newFile
TskData.FileKnown knownStatus = caseDbInstance.getKnownStatus(); * @throws TskCoreException
// If not known, check Tags for known and set * @throws EamDbException
TskData.FileKnown knownBad = TskData.FileKnown.BAD; */
if (!knownStatus.equals(knownBad)) { private void addOrUpdateAttributeInstance(final Case autopsyCase, Map<UniquePathKey,CorrelationAttributeInstance> artifactInstances, AbstractFile newFile) throws TskCoreException, EamDbException {
List<ContentTag> fileMatchTags = openCase.getServices().getTagsManager().getContentTagsByContent(caseDbFile);
// figure out if the casedb file is known via either hash or tags
TskData.FileKnown localKnown = newFile.getKnown();
if (localKnown != TskData.FileKnown.BAD) {
List<ContentTag> fileMatchTags = autopsyCase.getServices().getTagsManager().getContentTagsByContent(newFile);
for (ContentTag tag : fileMatchTags) { for (ContentTag tag : fileMatchTags) {
TskData.FileKnown tagKnownStatus = tag.getName().getKnownStatus(); TskData.FileKnown tagKnownStatus = tag.getName().getKnownStatus();
if (tagKnownStatus.equals(knownBad)) { if (tagKnownStatus.equals(TskData.FileKnown.BAD)) {
caseDbInstance.setKnownStatus(knownBad); localKnown = TskData.FileKnown.BAD;
break; break;
} }
} }
} }
// If known, or not in CR, add // make a key to see if the file is already in the map
if (caseDbInstance.getKnownStatus().equals(knownBad) || !artifactInstances.containsKey(instKey)) { String filePath = newFile.getParentPath() + newFile.getName();
artifactInstances.put(instKey, caseDbInstance); String deviceId;
try {
deviceId = autopsyCase.getSleuthkitCase().getDataSource(newFile.getDataSource().getId()).getDeviceId();
} catch (TskDataException | TskCoreException ex) {
LOGGER.log(Level.WARNING, "Error getting data source info: " + ex);
return;
}
UniquePathKey uniquePathKey = new UniquePathKey(deviceId, filePath);
// double check that the CR version is BAD if the caseDB version is BAD.
if (artifactInstances.containsKey(uniquePathKey)) {
if (localKnown == TskData.FileKnown.BAD) {
CorrelationAttributeInstance prevInstance = artifactInstances.get(uniquePathKey);
prevInstance.setKnownStatus(localKnown);
}
}
// add the data from the case DB by pushing data into CorrelationAttributeInstance class
else {
// NOTE: If we are in here, it is likely because CR is not enabled. So, we cannot rely
// on any of the methods that query the DB.
CorrelationCase correlationCase = new CorrelationCase(autopsyCase.getName(), autopsyCase.getDisplayName());
CorrelationDataSource correlationDataSource = CorrelationDataSource.fromTSKDataSource(correlationCase, newFile.getDataSource());
CorrelationAttributeInstance caseDbInstance = new CorrelationAttributeInstance(correlationCase, correlationDataSource, filePath, "", localKnown);
artifactInstances.put(uniquePathKey, caseDbInstance);
} }
} }
@ -588,7 +632,7 @@ public class DataContentViewerOtherCases extends javax.swing.JPanel implements D
// get the attributes we can correlate on // get the attributes we can correlate on
correlationAttributes.addAll(getCorrelationAttributesFromNode(node)); correlationAttributes.addAll(getCorrelationAttributesFromNode(node));
for (CorrelationAttribute corAttr : correlationAttributes) { for (CorrelationAttribute corAttr : correlationAttributes) {
Map<ArtifactKey, CorrelationAttributeInstance> corAttrInstances = new HashMap<>(0); Map<UniquePathKey, CorrelationAttributeInstance> corAttrInstances = new HashMap<>(0);
// get correlation and reference set instances from DB // get correlation and reference set instances from DB
corAttrInstances.putAll(getCorrelatedInstances(corAttr, dataSourceName, deviceId)); corAttrInstances.putAll(getCorrelatedInstances(corAttr, dataSourceName, deviceId));
@ -608,6 +652,7 @@ public class DataContentViewerOtherCases extends javax.swing.JPanel implements D
} }
if (correlationAttributes.isEmpty()) { if (correlationAttributes.isEmpty()) {
// @@@ BC: We should have a more descriptive message than this. Mention that the file didn't have a MD5, etc.
displayMessageOnTableStatusPanel(Bundle.DataContentViewerOtherCases_table_noArtifacts()); displayMessageOnTableStatusPanel(Bundle.DataContentViewerOtherCases_table_noArtifacts());
} else if (0 == tableModel.getRowCount()) { } else if (0 == tableModel.getRowCount()) {
displayMessageOnTableStatusPanel(Bundle.DataContentViewerOtherCases_table_isempty()); displayMessageOnTableStatusPanel(Bundle.DataContentViewerOtherCases_table_isempty());
@ -645,131 +690,170 @@ public class DataContentViewerOtherCases extends javax.swing.JPanel implements D
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() { private void initComponents() {
rightClickPopupMenu = new javax.swing.JPopupMenu(); rightClickPopupMenu = new JPopupMenu();
selectAllMenuItem = new javax.swing.JMenuItem(); selectAllMenuItem = new JMenuItem();
exportToCSVMenuItem = new javax.swing.JMenuItem(); exportToCSVMenuItem = new JMenuItem();
showCaseDetailsMenuItem = new javax.swing.JMenuItem(); showCaseDetailsMenuItem = new JMenuItem();
showCommonalityMenuItem = new javax.swing.JMenuItem(); showCommonalityMenuItem = new JMenuItem();
CSVFileChooser = new javax.swing.JFileChooser(); CSVFileChooser = new JFileChooser();
otherCasesPanel = new javax.swing.JPanel(); otherCasesPanel = new JPanel();
tableContainerPanel = new javax.swing.JPanel(); tableContainerPanel = new JPanel();
tableScrollPane = new javax.swing.JScrollPane(); tableScrollPane = new JScrollPane();
otherCasesTable = new javax.swing.JTable(); otherCasesTable = new JTable();
tableStatusPanel = new javax.swing.JPanel(); tableStatusPanel = new JPanel();
tableStatusPanelLabel = new javax.swing.JLabel(); tableStatusPanelLabel = new JLabel();
org.openide.awt.Mnemonics.setLocalizedText(selectAllMenuItem, org.openide.util.NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.selectAllMenuItem.text")); // NOI18N Mnemonics.setLocalizedText(selectAllMenuItem, NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.selectAllMenuItem.text")); // NOI18N
rightClickPopupMenu.add(selectAllMenuItem); rightClickPopupMenu.add(selectAllMenuItem);
org.openide.awt.Mnemonics.setLocalizedText(exportToCSVMenuItem, org.openide.util.NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.exportToCSVMenuItem.text")); // NOI18N Mnemonics.setLocalizedText(exportToCSVMenuItem, NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.exportToCSVMenuItem.text")); // NOI18N
rightClickPopupMenu.add(exportToCSVMenuItem); rightClickPopupMenu.add(exportToCSVMenuItem);
org.openide.awt.Mnemonics.setLocalizedText(showCaseDetailsMenuItem, org.openide.util.NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.showCaseDetailsMenuItem.text")); // NOI18N Mnemonics.setLocalizedText(showCaseDetailsMenuItem, NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.showCaseDetailsMenuItem.text")); // NOI18N
rightClickPopupMenu.add(showCaseDetailsMenuItem); rightClickPopupMenu.add(showCaseDetailsMenuItem);
org.openide.awt.Mnemonics.setLocalizedText(showCommonalityMenuItem, org.openide.util.NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.showCommonalityMenuItem.text")); // NOI18N Mnemonics.setLocalizedText(showCommonalityMenuItem, NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.showCommonalityMenuItem.text")); // NOI18N
rightClickPopupMenu.add(showCommonalityMenuItem); rightClickPopupMenu.add(showCommonalityMenuItem);
setMinimumSize(new java.awt.Dimension(1500, 10)); setMinimumSize(new Dimension(1500, 10));
setOpaque(false); setOpaque(false);
setPreferredSize(new java.awt.Dimension(1500, 44)); setPreferredSize(new Dimension(1500, 44));
otherCasesPanel.setPreferredSize(new java.awt.Dimension(1500, 144)); otherCasesPanel.setPreferredSize(new Dimension(1500, 144));
tableContainerPanel.setPreferredSize(new java.awt.Dimension(1500, 63)); tableContainerPanel.setPreferredSize(new Dimension(1500, 63));
tableScrollPane.setPreferredSize(new java.awt.Dimension(1500, 30)); tableScrollPane.setPreferredSize(new Dimension(1500, 30));
otherCasesTable.setAutoCreateRowSorter(true); otherCasesTable.setAutoCreateRowSorter(true);
otherCasesTable.setModel(tableModel); otherCasesTable.setModel(tableModel);
otherCasesTable.setToolTipText(org.openide.util.NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.table.toolTip.text")); // NOI18N otherCasesTable.setToolTipText(NbBundle.getMessage(DataContentViewerOtherCases.class, "DataContentViewerOtherCases.table.toolTip.text")); // NOI18N
otherCasesTable.setComponentPopupMenu(rightClickPopupMenu); otherCasesTable.setComponentPopupMenu(rightClickPopupMenu);
otherCasesTable.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_INTERVAL_SELECTION); otherCasesTable.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
tableScrollPane.setViewportView(otherCasesTable); tableScrollPane.setViewportView(otherCasesTable);
tableStatusPanel.setPreferredSize(new java.awt.Dimension(1500, 16)); tableStatusPanel.setPreferredSize(new Dimension(1500, 16));
tableStatusPanelLabel.setForeground(new java.awt.Color(255, 0, 51)); tableStatusPanelLabel.setForeground(new Color(255, 0, 51));
javax.swing.GroupLayout tableStatusPanelLayout = new javax.swing.GroupLayout(tableStatusPanel); GroupLayout tableStatusPanelLayout = new GroupLayout(tableStatusPanel);
tableStatusPanel.setLayout(tableStatusPanelLayout); tableStatusPanel.setLayout(tableStatusPanelLayout);
tableStatusPanelLayout.setHorizontalGroup( tableStatusPanelLayout.setHorizontalGroup(tableStatusPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
tableStatusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 0, Short.MAX_VALUE) .addGap(0, 0, Short.MAX_VALUE)
.addGroup(tableStatusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(tableStatusPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addGroup(tableStatusPanelLayout.createSequentialGroup() .addGroup(tableStatusPanelLayout.createSequentialGroup()
.addContainerGap() .addContainerGap()
.addComponent(tableStatusPanelLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 780, Short.MAX_VALUE) .addComponent(tableStatusPanelLabel, GroupLayout.DEFAULT_SIZE, 780, Short.MAX_VALUE)
.addContainerGap())) .addContainerGap()))
); );
tableStatusPanelLayout.setVerticalGroup( tableStatusPanelLayout.setVerticalGroup(tableStatusPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
tableStatusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 16, Short.MAX_VALUE) .addGap(0, 16, Short.MAX_VALUE)
.addGroup(tableStatusPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(tableStatusPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addGroup(tableStatusPanelLayout.createSequentialGroup() .addGroup(tableStatusPanelLayout.createSequentialGroup()
.addComponent(tableStatusPanelLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 16, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(tableStatusPanelLabel, GroupLayout.PREFERRED_SIZE, 16, GroupLayout.PREFERRED_SIZE)
.addGap(0, 0, Short.MAX_VALUE))) .addGap(0, 0, Short.MAX_VALUE)))
); );
javax.swing.GroupLayout tableContainerPanelLayout = new javax.swing.GroupLayout(tableContainerPanel); GroupLayout tableContainerPanelLayout = new GroupLayout(tableContainerPanel);
tableContainerPanel.setLayout(tableContainerPanelLayout); tableContainerPanel.setLayout(tableContainerPanelLayout);
tableContainerPanelLayout.setHorizontalGroup( tableContainerPanelLayout.setHorizontalGroup(tableContainerPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
tableContainerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(tableScrollPane, GroupLayout.Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(tableScrollPane, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(tableStatusPanel, GroupLayout.Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(tableStatusPanel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
); );
tableContainerPanelLayout.setVerticalGroup( tableContainerPanelLayout.setVerticalGroup(tableContainerPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
tableContainerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(tableContainerPanelLayout.createSequentialGroup() .addGroup(tableContainerPanelLayout.createSequentialGroup()
.addComponent(tableScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(tableScrollPane, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
.addComponent(tableStatusPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(tableStatusPanel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
.addContainerGap()) .addContainerGap())
); );
javax.swing.GroupLayout otherCasesPanelLayout = new javax.swing.GroupLayout(otherCasesPanel); GroupLayout otherCasesPanelLayout = new GroupLayout(otherCasesPanel);
otherCasesPanel.setLayout(otherCasesPanelLayout); otherCasesPanel.setLayout(otherCasesPanelLayout);
otherCasesPanelLayout.setHorizontalGroup( otherCasesPanelLayout.setHorizontalGroup(otherCasesPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
otherCasesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 1500, Short.MAX_VALUE) .addGap(0, 1500, Short.MAX_VALUE)
.addGroup(otherCasesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(otherCasesPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addComponent(tableContainerPanel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addComponent(tableContainerPanel, GroupLayout.Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
); );
otherCasesPanelLayout.setVerticalGroup( otherCasesPanelLayout.setVerticalGroup(otherCasesPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
otherCasesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 60, Short.MAX_VALUE) .addGap(0, 60, Short.MAX_VALUE)
.addGroup(otherCasesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(otherCasesPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
.addGroup(otherCasesPanelLayout.createSequentialGroup() .addGroup(otherCasesPanelLayout.createSequentialGroup()
.addComponent(tableContainerPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 60, Short.MAX_VALUE) .addComponent(tableContainerPanel, GroupLayout.DEFAULT_SIZE, 60, Short.MAX_VALUE)
.addGap(0, 0, 0))) .addGap(0, 0, 0)))
); );
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); GroupLayout layout = new GroupLayout(this);
this.setLayout(layout); this.setLayout(layout);
layout.setHorizontalGroup( layout.setHorizontalGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(otherCasesPanel, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(otherCasesPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
); );
layout.setVerticalGroup( layout.setVerticalGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(otherCasesPanel, GroupLayout.DEFAULT_SIZE, 60, Short.MAX_VALUE)
.addComponent(otherCasesPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 60, Short.MAX_VALUE)
); );
}// </editor-fold>//GEN-END:initComponents }// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables // Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JFileChooser CSVFileChooser; private JFileChooser CSVFileChooser;
private javax.swing.JMenuItem exportToCSVMenuItem; private JMenuItem exportToCSVMenuItem;
private javax.swing.JPanel otherCasesPanel; private JPanel otherCasesPanel;
private javax.swing.JTable otherCasesTable; private JTable otherCasesTable;
private javax.swing.JPopupMenu rightClickPopupMenu; private JPopupMenu rightClickPopupMenu;
private javax.swing.JMenuItem selectAllMenuItem; private JMenuItem selectAllMenuItem;
private javax.swing.JMenuItem showCaseDetailsMenuItem; private JMenuItem showCaseDetailsMenuItem;
private javax.swing.JMenuItem showCommonalityMenuItem; private JMenuItem showCommonalityMenuItem;
private javax.swing.JPanel tableContainerPanel; private JPanel tableContainerPanel;
private javax.swing.JScrollPane tableScrollPane; private JScrollPane tableScrollPane;
private javax.swing.JPanel tableStatusPanel; private JPanel tableStatusPanel;
private javax.swing.JLabel tableStatusPanelLabel; private JLabel tableStatusPanelLabel;
// End of variables declaration//GEN-END:variables // End of variables declaration//GEN-END:variables
/**
* Used as a key to ensure we eliminate duplicates from the result set by not overwriting CR correlation instances.
*/
static final class UniquePathKey {
private final String dataSourceID;
private final String filePath;
UniquePathKey(String theDataSource, String theFilePath) {
super();
dataSourceID = theDataSource;
filePath = theFilePath.toLowerCase();
}
/**
*
* @return the dataSourceID device ID
*/
String getDataSourceID() {
return dataSourceID;
}
/**
*
* @return the filPath including the filename and extension.
*/
String getFilePath() {
return filePath;
}
@Override
public boolean equals(Object other) {
if (other instanceof UniquePathKey) {
return ((UniquePathKey) other).getDataSourceID().equals(dataSourceID) && ((UniquePathKey) other).getFilePath().equals(filePath);
}
return false;
}
@Override
public int hashCode() {
//int hash = 7;
//hash = 67 * hash + this.dataSourceID.hashCode();
//hash = 67 * hash + this.filePath.hashCode();
return Objects.hash(dataSourceID, filePath);
}
}
} }

View File

@ -24,7 +24,7 @@ import java.util.Map;
/** /**
* Provides logic for selecting common files from all data sources. * Provides logic for selecting common files from all data sources.
*/ */
final class AllDataSourcesCommonFilesAlgorithm extends CommonFilesMetadataBuilder { final public class AllDataSourcesCommonFilesAlgorithm extends CommonFilesMetadataBuilder {
private static final String WHERE_CLAUSE = "%s md5 in (select md5 from tsk_files where (known != 1 OR known IS NULL)%s GROUP BY md5 HAVING COUNT(*) > 1) order by md5"; //NON-NLS private static final String WHERE_CLAUSE = "%s md5 in (select md5 from tsk_files where (known != 1 OR known IS NULL)%s GROUP BY md5 HAVING COUNT(*) > 1) order by md5"; //NON-NLS
@ -36,7 +36,7 @@ final class AllDataSourcesCommonFilesAlgorithm extends CommonFilesMetadataBuilde
* @param filterByMediaMimeType match only on files whose mime types can be broadly categorized as media types * @param filterByMediaMimeType match only on files whose mime types can be broadly categorized as media types
* @param filterByDocMimeType match only on files whose mime types can be broadly categorized as document types * @param filterByDocMimeType match only on files whose mime types can be broadly categorized as document types
*/ */
AllDataSourcesCommonFilesAlgorithm(Map<Long, String> dataSourceIdMap, boolean filterByMediaMimeType, boolean filterByDocMimeType) { public AllDataSourcesCommonFilesAlgorithm(Map<Long, String> dataSourceIdMap, boolean filterByMediaMimeType, boolean filterByDocMimeType) {
super(dataSourceIdMap, filterByMediaMimeType, filterByDocMimeType); super(dataSourceIdMap, filterByMediaMimeType, filterByDocMimeType);
} }

View File

@ -26,7 +26,7 @@ import java.util.Map;
* Utility and wrapper model around data required for Common Files Search results. * Utility and wrapper model around data required for Common Files Search results.
* Subclass this to implement different selections of files from the case. * Subclass this to implement different selections of files from the case.
*/ */
final class CommonFilesMetadata { final public class CommonFilesMetadata {
private final Map<String, Md5Metadata> metadata; private final Map<String, Md5Metadata> metadata;
@ -52,7 +52,7 @@ final class CommonFilesMetadata {
return this.metadata.get(md5); return this.metadata.get(md5);
} }
Map<String, Md5Metadata> getMetadata() { public Map<String, Md5Metadata> getMetadata() {
return Collections.unmodifiableMap(this.metadata); return Collections.unmodifiableMap(this.metadata);
} }
@ -60,7 +60,7 @@ final class CommonFilesMetadata {
* How many distinct file instances exist for this metadata? * How many distinct file instances exist for this metadata?
* @return number of file instances * @return number of file instances
*/ */
int size() { public int size() {
int count = 0; int count = 0;
for (Md5Metadata data : this.metadata.values()) { for (Md5Metadata data : this.metadata.values()) {
count += data.size(); count += data.size();

View File

@ -46,7 +46,7 @@ import org.sleuthkit.datamodel.TskCoreException;
* This entire thing runs on a background thread where exceptions are handled. * This entire thing runs on a background thread where exceptions are handled.
*/ */
@SuppressWarnings("PMD.AbstractNaming") @SuppressWarnings("PMD.AbstractNaming")
abstract class CommonFilesMetadataBuilder { public abstract class CommonFilesMetadataBuilder {
private final Map<Long, String> dataSourceIdToNameMap; private final Map<Long, String> dataSourceIdToNameMap;
private final boolean filterByMedia; private final boolean filterByMedia;

View File

@ -18,12 +18,9 @@
*/ */
package org.sleuthkit.autopsy.commonfilesearch; package org.sleuthkit.autopsy.commonfilesearch;
import java.io.File;
import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
@ -33,7 +30,6 @@ import javax.swing.SwingUtilities;
import javax.swing.SwingWorker; import javax.swing.SwingWorker;
import org.openide.explorer.ExplorerManager; import org.openide.explorer.ExplorerManager;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataResultViewer; import org.sleuthkit.autopsy.corecomponentinterfaces.DataResultViewer;
import org.sleuthkit.autopsy.corecomponents.DataResultTopComponent; import org.sleuthkit.autopsy.corecomponents.DataResultTopComponent;
@ -42,8 +38,6 @@ import org.sleuthkit.autopsy.corecomponents.TableFilterNode;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.directorytree.DataResultFilterNode; import org.sleuthkit.autopsy.directorytree.DataResultFilterNode;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.SleuthkitCase.CaseDbQuery;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
/** /**
@ -97,10 +91,6 @@ public final class CommonFilesPanel extends javax.swing.JPanel {
new SwingWorker<Map<Long, String>, Void>() { new SwingWorker<Map<Long, String>, Void>() {
private static final String SELECT_DATA_SOURCES_LOGICAL = "select obj_id, name from tsk_files where obj_id in (SELECT obj_id FROM tsk_objects WHERE obj_id in (select obj_id from data_source_info))";
private static final String SELECT_DATA_SOURCES_IMAGE = "select obj_id, name from tsk_image_names where obj_id in (SELECT obj_id FROM tsk_objects WHERE obj_id in (select obj_id from data_source_info))";
private void updateUi() { private void updateUi() {
String[] dataSourcesNames = new String[CommonFilesPanel.this.dataSourceMap.size()]; String[] dataSourcesNames = new String[CommonFilesPanel.this.dataSourceMap.size()];
@ -131,48 +121,10 @@ public final class CommonFilesPanel extends javax.swing.JPanel {
return CommonFilesPanel.this.dataSourceMap.size() >= 2; return CommonFilesPanel.this.dataSourceMap.size() >= 2;
} }
private void loadLogicalSources(SleuthkitCase tskDb, Map<Long, String> dataSouceMap) throws TskCoreException, SQLException {
//try block releases resources - exceptions are handled in done()
try (
CaseDbQuery query = tskDb.executeQuery(SELECT_DATA_SOURCES_LOGICAL);
ResultSet resultSet = query.getResultSet()) {
while (resultSet.next()) {
Long objectId = resultSet.getLong(1);
String dataSourceName = resultSet.getString(2);
dataSouceMap.put(objectId, dataSourceName);
}
}
}
private void loadImageSources(SleuthkitCase tskDb, Map<Long, String> dataSouceMap) throws SQLException, TskCoreException {
//try block releases resources - exceptions are handled in done()
try (
CaseDbQuery query = tskDb.executeQuery(SELECT_DATA_SOURCES_IMAGE);
ResultSet resultSet = query.getResultSet()) {
while (resultSet.next()) {
Long objectId = resultSet.getLong(1);
String dataSourceName = resultSet.getString(2);
File image = new File(dataSourceName);
String dataSourceNameTrimmed = image.getName();
dataSouceMap.put(objectId, dataSourceNameTrimmed);
}
}
}
@Override @Override
protected Map<Long, String> doInBackground() throws NoCurrentCaseException, TskCoreException, SQLException { protected Map<Long, String> doInBackground() throws NoCurrentCaseException, TskCoreException, SQLException {
DataSourceLoader loader = new DataSourceLoader();
Map<Long, String> dataSouceMap = new HashMap<>(); return loader.getDataSourceMap();
Case currentCase = Case.getCurrentCaseThrows();
SleuthkitCase tskDb = currentCase.getSleuthkitCase();
loadLogicalSources(tskDb, dataSouceMap);
loadImageSources(tskDb, dataSouceMap);
return dataSouceMap;
} }
@Override @Override

View File

@ -0,0 +1,95 @@
/*
*
* Autopsy Forensic Browser
*
* Copyright 2018 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.commonfilesearch;
import java.io.File;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException;
/**
* Encapsulates logic required to create a mapping of data sources in the
* current case to their data source IDs.
*
* Intended to be used within the context of a SwingWorker or other background
* thread.
*/
public class DataSourceLoader {
private static final String SELECT_DATA_SOURCES_LOGICAL = "select obj_id, name from tsk_files where obj_id in (SELECT obj_id FROM tsk_objects WHERE obj_id in (select obj_id from data_source_info))";
private static final String SELECT_DATA_SOURCES_IMAGE = "select obj_id, name from tsk_image_names where obj_id in (SELECT obj_id FROM tsk_objects WHERE obj_id in (select obj_id from data_source_info))";
private void loadLogicalSources(SleuthkitCase tskDb, Map<Long, String> dataSouceMap) throws TskCoreException, SQLException {
//try block releases resources - exceptions are handled in done()
try (
SleuthkitCase.CaseDbQuery query = tskDb.executeQuery(SELECT_DATA_SOURCES_LOGICAL);
ResultSet resultSet = query.getResultSet()
) {
while (resultSet.next()) {
Long objectId = resultSet.getLong(1);
String dataSourceName = resultSet.getString(2);
dataSouceMap.put(objectId, dataSourceName);
}
}
}
private void loadImageSources(SleuthkitCase tskDb, Map<Long, String> dataSouceMap) throws SQLException, TskCoreException {
//try block releases resources - exceptions are handled in done()
try (
SleuthkitCase.CaseDbQuery query = tskDb.executeQuery(SELECT_DATA_SOURCES_IMAGE);
ResultSet resultSet = query.getResultSet()) {
while (resultSet.next()) {
Long objectId = resultSet.getLong(1);
String dataSourceName = resultSet.getString(2);
File image = new File(dataSourceName);
String dataSourceNameTrimmed = image.getName();
dataSouceMap.put(objectId, dataSourceNameTrimmed);
}
}
}
/**
* Get a map of data source Ids to their string names for the current case.
*
* @return Map of Long (id) to String (name)
* @throws NoCurrentCaseException
* @throws TskCoreException
* @throws SQLException
*/
public Map<Long, String> getDataSourceMap() throws NoCurrentCaseException, TskCoreException, SQLException {
Map<Long, String> dataSouceMap = new HashMap<>();
Case currentCase = Case.getCurrentCaseThrows();
SleuthkitCase tskDb = currentCase.getSleuthkitCase();
loadLogicalSources(tskDb, dataSouceMap);
loadImageSources(tskDb, dataSouceMap);
return dataSouceMap;
}
}

View File

@ -24,7 +24,7 @@ import java.util.Map;
/** /**
* Provides logic for selecting common files from a single data source. * Provides logic for selecting common files from a single data source.
*/ */
final class SingleDataSource extends CommonFilesMetadataBuilder { final public class SingleDataSource extends CommonFilesMetadataBuilder {
private static final String WHERE_CLAUSE = "%s md5 in (select md5 from tsk_files where md5 in (select md5 from tsk_files where (known != 1 OR known IS NULL) and data_source_obj_id=%s%s) GROUP BY md5 HAVING COUNT(*) > 1) order by md5"; //NON-NLS private static final String WHERE_CLAUSE = "%s md5 in (select md5 from tsk_files where md5 in (select md5 from tsk_files where (known != 1 OR known IS NULL) and data_source_obj_id=%s%s) GROUP BY md5 HAVING COUNT(*) > 1) order by md5"; //NON-NLS
private final Long selectedDataSourceId; private final Long selectedDataSourceId;
@ -35,10 +35,12 @@ final class SingleDataSource extends CommonFilesMetadataBuilder {
* once in the given data source * once in the given data source
* @param dataSourceId data source id for which common files must appear at least once * @param dataSourceId data source id for which common files must appear at least once
* @param dataSourceIdMap a map of obj_id to datasource name * @param dataSourceIdMap a map of obj_id to datasource name
* @param filterByMediaMimeType match only on files whose mime types can be broadly categorized as media types * @param filterByMediaMimeType match only on files whose mime types can be
* @param filterByDocMimeType match only on files whose mime types can be broadly categorized as document types * broadly categorized as media types
* @param filterByDocMimeType match only on files whose mime types can be
* broadly categorized as document types
*/ */
SingleDataSource(Long dataSourceId, Map<Long, String> dataSourceIdMap, boolean filterByMediaMimeType, boolean filterByDocMimeType) { public SingleDataSource(Long dataSourceId, Map<Long, String> dataSourceIdMap, boolean filterByMediaMimeType, boolean filterByDocMimeType) {
super(dataSourceIdMap, filterByMediaMimeType, filterByDocMimeType); super(dataSourceIdMap, filterByMediaMimeType, filterByDocMimeType);
this.selectedDataSourceId = dataSourceId; this.selectedDataSourceId = dataSourceId;
this.dataSourceName = dataSourceIdMap.get(this.selectedDataSourceId); this.dataSourceName = dataSourceIdMap.get(this.selectedDataSourceId);

View File

@ -373,7 +373,7 @@ class TimingMetricGraphPanel extends JPanel {
} }
} else if (y0value > maxValueOnYAxis) { } else if (y0value > maxValueOnYAxis) {
try { try {
y0value = minValueOnYAxis; y0value = maxValueOnYAxis;
x0value = trendLine.getXGivenY(y0value); x0value = trendLine.getXGivenY(y0value);
} catch (HealthMonitorException ex) { } catch (HealthMonitorException ex) {
// The exception is caused by a slope of zero on the trend line, which // The exception is caused by a slope of zero on the trend line, which

View File

@ -9,8 +9,8 @@ OpenIDE-Module-Name=Embedded File Extraction
OpenIDE-Module-Short-Description=Embedded File Extraction Ingest Module OpenIDE-Module-Short-Description=Embedded File Extraction Ingest Module
EmbeddedFileExtractorIngestModule.SevenZipContentReadStream.seek.exception.invalidOrigin=Invalid seek origin\: {0} EmbeddedFileExtractorIngestModule.SevenZipContentReadStream.seek.exception.invalidOrigin=Invalid seek origin\: {0}
EmbeddedFileExtractorIngestModule.SevenZipContentReadStream.read.exception.errReadStream=Error reading content stream. EmbeddedFileExtractorIngestModule.SevenZipContentReadStream.read.exception.errReadStream=Error reading content stream.
EmbeddedFileExtractorIngestModule.ArchiveExtractor.encryptionFileLevel=File-level Encryption EmbeddedFileExtractorIngestModule.ArchiveExtractor.encryptionFileLevel=Content-only Encryption (Archive File)
EmbeddedFileExtractorIngestModule.ArchiveExtractor.encryptionFull=Full Encryption EmbeddedFileExtractorIngestModule.ArchiveExtractor.encryptionFull=Full Encryption (Archive File)
EmbeddedFileExtractorIngestModule.ArchiveExtractor.init.errInitModule.details=Error initializing output dir\: {0}\: {1} EmbeddedFileExtractorIngestModule.ArchiveExtractor.init.errInitModule.details=Error initializing output dir\: {0}\: {1}
EmbeddedFileExtractorIngestModule.ArchiveExtractor.isZipBombCheck.warnMsg=Possible ZIP bomb detected in archive\: {0}, item\: {1} EmbeddedFileExtractorIngestModule.ArchiveExtractor.isZipBombCheck.warnMsg=Possible ZIP bomb detected in archive\: {0}, item\: {1}
EmbeddedFileExtractorIngestModule.ArchiveExtractor.isZipBombCheck.warnDetails=Compression ratio is {0}, skipping item in {1}. EmbeddedFileExtractorIngestModule.ArchiveExtractor.isZipBombCheck.warnDetails=Compression ratio is {0}, skipping item in {1}.

View File

@ -18,8 +18,6 @@
*/ */
package org.sleuthkit.autopsy.modules.hashdatabase; package org.sleuthkit.autopsy.modules.hashdatabase;
import java.util.ArrayList;
import java.util.List;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.openide.util.lookup.ServiceProvider; import org.openide.util.lookup.ServiceProvider;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;

View File

@ -0,0 +1,465 @@
/*
*
* Autopsy Forensic Browser
*
* Copyright 2018 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.commonfilessearch;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import junit.framework.Test;
import org.netbeans.junit.NbModuleSuite;
import org.netbeans.junit.NbTestCase;
import org.openide.util.Exceptions;
import org.python.icu.impl.Assert;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.commonfilesearch.AllDataSourcesCommonFilesAlgorithm;
import org.sleuthkit.autopsy.commonfilesearch.CommonFilesMetadata;
import org.sleuthkit.autopsy.commonfilesearch.CommonFilesMetadataBuilder;
import org.sleuthkit.autopsy.commonfilesearch.SingleDataSource;
import static org.sleuthkit.autopsy.commonfilessearch.IntraCaseUtils.*;
import org.sleuthkit.autopsy.ingest.IngestJobSettings;
import org.sleuthkit.autopsy.ingest.IngestJobSettings.IngestType;
import org.sleuthkit.autopsy.ingest.IngestModuleTemplate;
import org.sleuthkit.autopsy.modules.filetypeid.FileTypeIdModuleFactory;
import org.sleuthkit.autopsy.modules.hashdatabase.HashLookupModuleFactory;
import org.sleuthkit.autopsy.testutils.IngestUtils;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.TskCoreException;
/**
* Add set 1, set 2, set 3, and set 4 to case and ingest with hash algorithm.
*/
public class IngestedWithHashAndFileType extends NbTestCase {
public static Test suite() {
NbModuleSuite.Configuration conf = NbModuleSuite.createConfiguration(IngestedWithHashAndFileType.class).
clusters(".*").
enableModules(".*");
return conf.suite();
}
private final IntraCaseUtils utils;
public IngestedWithHashAndFileType(String name) {
super(name);
this.utils = new IntraCaseUtils(this, "IngestedWithHashAndFileTypeTests");
}
@Override
public void setUp() {
this.utils.setUp();
IngestModuleTemplate hashLookupTemplate = IngestUtils.getIngestModuleTemplate(new HashLookupModuleFactory());
IngestModuleTemplate mimeTypeLookupTemplate = IngestUtils.getIngestModuleTemplate(new FileTypeIdModuleFactory());
ArrayList<IngestModuleTemplate> templates = new ArrayList<>();
templates.add(hashLookupTemplate);
templates.add(mimeTypeLookupTemplate);
IngestJobSettings ingestJobSettings = new IngestJobSettings(IngestedWithHashAndFileType.class.getCanonicalName(), IngestType.FILES_ONLY, templates);
try {
IngestUtils.runIngestJob(Case.getCurrentCaseThrows().getDataSources(), ingestJobSettings);
} catch (NoCurrentCaseException | TskCoreException ex) {
Exceptions.printStackTrace(ex);
Assert.fail(ex);
}
}
@Override
public void tearDown() {
this.utils.tearDown();
}
/**
* Find all matches & all file types. Confirm file.jpg is found on all three
* and file.docx is found on two.
*/
public void testOneA() {
try {
Map<Long, String> dataSources = this.utils.getDataSourceMap();
CommonFilesMetadataBuilder allSourcesBuilder = new AllDataSourcesCommonFilesAlgorithm(dataSources, false, false);
CommonFilesMetadata metadata = allSourcesBuilder.findCommonFiles();
Map<Long, String> objectIdToDataSource = IntraCaseUtils.mapFileInstancesToDataSources(metadata);
List<AbstractFile> files = IntraCaseUtils.getFiles(objectIdToDataSource.keySet());
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET1, 2));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET2, 1));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET3, 1));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET4, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET1, 1));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET2, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET3, 1));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET4, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET1, 0));
assertTrue(IntraCaseUtils.verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET2, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET3, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET4, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET1, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET2, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET3, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET4, 0));
} catch (NoCurrentCaseException | TskCoreException | SQLException ex) {
Exceptions.printStackTrace(ex);
Assert.fail(ex);
}
}
/**
* Find all matches & only image types. Confirm file.jpg is found on all
* three.
*/
public void testOneB() {
try {
Map<Long, String> dataSources = this.utils.getDataSourceMap();
CommonFilesMetadataBuilder allSourcesBuilder = new AllDataSourcesCommonFilesAlgorithm(dataSources, true, false);
CommonFilesMetadata metadata = allSourcesBuilder.findCommonFiles();
Map<Long, String> objectIdToDataSource = mapFileInstancesToDataSources(metadata);
List<AbstractFile> files = getFiles(objectIdToDataSource.keySet());
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET1, 2));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET2, 1));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET3, 1));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET4, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET1, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET2, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET3, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET4, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET1, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET2, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET3, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET4, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET1, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET2, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET3, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET4, 0));
} catch (NoCurrentCaseException | TskCoreException | SQLException ex) {
Exceptions.printStackTrace(ex);
Assert.fail(ex);
}
}
/**
* Find all matches & only image types. Confirm file.jpg is found on all
* three.
*/
public void testOneC() {
try {
Map<Long, String> dataSources = this.utils.getDataSourceMap();
CommonFilesMetadataBuilder allSourcesBuilder = new AllDataSourcesCommonFilesAlgorithm(dataSources, false, true);
CommonFilesMetadata metadata = allSourcesBuilder.findCommonFiles();
Map<Long, String> objectIdToDataSource = mapFileInstancesToDataSources(metadata);
List<AbstractFile> files = getFiles(objectIdToDataSource.keySet());
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET1, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET2, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET3, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET4, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET1, 1));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET2, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET3, 1));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET4, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET1, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET2, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET3, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET4, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET1, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET2, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET3, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET4, 0));
} catch (NoCurrentCaseException | TskCoreException | SQLException ex) {
Exceptions.printStackTrace(ex);
Assert.fail(ex);
}
}
/**
* Find matches on set 1 & all file types. Confirm same results.
*
*/
public void testTwoA() {
try {
Map<Long, String> dataSources = this.utils.getDataSourceMap();
Long first = getDataSourceIdByName(SET1, dataSources);
CommonFilesMetadataBuilder singleSourceBuilder = new SingleDataSource(first, dataSources, false, false);
CommonFilesMetadata metadata = singleSourceBuilder.findCommonFiles();
Map<Long, String> objectIdToDataSource = mapFileInstancesToDataSources(metadata);
List<AbstractFile> files = getFiles(objectIdToDataSource.keySet());
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET1, 2));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET2, 1));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET3, 1));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET4, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET1, 1));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET2, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET3, 1));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET4, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET1, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET2, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET3, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET4, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET1, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET2, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET3, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET4, 0));
} catch (NoCurrentCaseException | TskCoreException | SQLException ex) {
Exceptions.printStackTrace(ex);
Assert.fail(ex);
}
}
/**
* Find matches on set 1 & only media types. Confirm same results.
*
*/
public void testTwoB() {
try {
Map<Long, String> dataSources = this.utils.getDataSourceMap();
Long first = getDataSourceIdByName(SET1, dataSources);
CommonFilesMetadataBuilder singleSourceBuilder = new SingleDataSource(first, dataSources, true, false);
CommonFilesMetadata metadata = singleSourceBuilder.findCommonFiles();
Map<Long, String> objectIdToDataSource = mapFileInstancesToDataSources(metadata);
List<AbstractFile> files = getFiles(objectIdToDataSource.keySet());
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET1, 2));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET2, 1));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET3, 1));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET4, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET1, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET2, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET3, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET4, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET1, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET2, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET3, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET4, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET1, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET2, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET3, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET4, 0));
} catch (NoCurrentCaseException | TskCoreException | SQLException ex) {
Exceptions.printStackTrace(ex);
Assert.fail(ex);
}
}
/**
* Find matches on set 1 & all file types. Confirm same results.
*
*/
public void testTwoC() {
try {
Map<Long, String> dataSources = this.utils.getDataSourceMap();
Long first = getDataSourceIdByName(SET1, dataSources);
CommonFilesMetadataBuilder singleSourceBuilder = new SingleDataSource(first, dataSources, false, true);
CommonFilesMetadata metadata = singleSourceBuilder.findCommonFiles();
Map<Long, String> objectIdToDataSource = mapFileInstancesToDataSources(metadata);
List<AbstractFile> files = getFiles(objectIdToDataSource.keySet());
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET1, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET2, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET3, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET4, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET1, 1));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET2, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET3, 1));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET4, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET1, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET2, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET3, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET4, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET1, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET2, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET3, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET4, 0));
} catch (NoCurrentCaseException | TskCoreException | SQLException ex) {
Exceptions.printStackTrace(ex);
Assert.fail(ex);
}
}
/**
* Find matches on set 2 & all file types: Confirm file.jpg.
*
*/
public void testThree() {
try {
Map<Long, String> dataSources = this.utils.getDataSourceMap();
Long second = getDataSourceIdByName(SET2, dataSources);
CommonFilesMetadataBuilder singleSourceBuilder = new SingleDataSource(second, dataSources, false, false);
CommonFilesMetadata metadata = singleSourceBuilder.findCommonFiles();
Map<Long, String> objectIdToDataSource = mapFileInstancesToDataSources(metadata);
List<AbstractFile> files = getFiles(objectIdToDataSource.keySet());
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET1, 2));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET2, 1));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET3, 1));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET4, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET1, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET2, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET3, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET4, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET1, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET2, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET3, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET4, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET1, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET2, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET3, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET4, 0));
} catch (NoCurrentCaseException | TskCoreException | SQLException ex) {
Exceptions.printStackTrace(ex);
Assert.fail(ex);
}
}
/**
* Find matches on set 4 & all file types: Confirm nothing is found.
*/
public void testFour() {
try {
Map<Long, String> dataSources = this.utils.getDataSourceMap();
Long last = getDataSourceIdByName(SET4, dataSources);
CommonFilesMetadataBuilder singleSourceBuilder = new SingleDataSource(last, dataSources, false, false);
CommonFilesMetadata metadata = singleSourceBuilder.findCommonFiles();
Map<Long, String> objectIdToDataSource = mapFileInstancesToDataSources(metadata);
List<AbstractFile> files = getFiles(objectIdToDataSource.keySet());
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET1, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET2, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET3, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET4, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET1, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET1, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET3, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET4, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET1, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET2, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET3, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET4, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET1, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET2, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET3, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET4, 0));
} catch (NoCurrentCaseException | TskCoreException | SQLException ex) {
Exceptions.printStackTrace(ex);
Assert.fail(ex);
}
}
/**
* Find matches on set 3 & all file types: Confirm file.jpg and file.docx.
*/
public void testFive() {
try {
Map<Long, String> dataSources = this.utils.getDataSourceMap();
Long third = getDataSourceIdByName(SET3, dataSources);
CommonFilesMetadataBuilder singleSourceBuilder = new SingleDataSource(third, dataSources, false, false);
CommonFilesMetadata metadata = singleSourceBuilder.findCommonFiles();
Map<Long, String> objectIdToDataSource = mapFileInstancesToDataSources(metadata);
List<AbstractFile> files = getFiles(objectIdToDataSource.keySet());
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET1, 2));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET2, 1));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET3, 1));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, IMG, SET4, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET1, 1));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET2, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET3, 1));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, DOC, SET4, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET1, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET2, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET3, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, PDF, SET4, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET1, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET2, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET3, 0));
assertTrue(verifyFileExistanceAndCount(files, objectIdToDataSource, EMPTY, SET4, 0));
} catch (NoCurrentCaseException | TskCoreException | SQLException ex) {
Exceptions.printStackTrace(ex);
Assert.fail(ex);
}
}
}

View File

@ -0,0 +1,140 @@
/*
*
* Autopsy Forensic Browser
*
* Copyright 2018 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.commonfilessearch;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import static junit.framework.Assert.assertTrue;
import junit.framework.Test;
import org.netbeans.junit.NbModuleSuite;
import org.netbeans.junit.NbTestCase;
import org.openide.util.Exceptions;
import org.python.icu.impl.Assert;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.commonfilesearch.AllDataSourcesCommonFilesAlgorithm;
import org.sleuthkit.autopsy.commonfilesearch.CommonFilesMetadata;
import org.sleuthkit.autopsy.commonfilesearch.CommonFilesMetadataBuilder;
import org.sleuthkit.autopsy.commonfilesearch.SingleDataSource;
import org.sleuthkit.autopsy.ingest.IngestJobSettings;
import org.sleuthkit.autopsy.ingest.IngestModuleTemplate;
import org.sleuthkit.autopsy.modules.hashdatabase.HashLookupModuleFactory;
import org.sleuthkit.autopsy.testutils.IngestUtils;
import static org.sleuthkit.autopsy.testutils.IngestUtils.getIngestModuleTemplate;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.TskCoreException;
/**
* Ingested w/o mime type info added to DB.
*
* Setup:
*
* Add images set 1, set 2, set 3, and set 4 to case. Do not run mime type
* module.
*/
public class IngestedWithNoFileTypes extends NbTestCase {
public static Test suite() {
NbModuleSuite.Configuration conf = NbModuleSuite.createConfiguration(IngestedWithNoFileTypes.class).
clusters(".*").
enableModules(".*");
return conf.suite();
}
private final IntraCaseUtils utils;
public IngestedWithNoFileTypes(String name) {
super(name);
this.utils = new IntraCaseUtils(this, "IngestedWithNoFileTypes");
}
@Override
public void setUp() {
this.utils.setUp();
IngestModuleTemplate hashLookupTemplate = getIngestModuleTemplate(new HashLookupModuleFactory());
ArrayList<IngestModuleTemplate> templates = new ArrayList<>();
templates.add(hashLookupTemplate);
IngestJobSettings ingestJobSettings = new IngestJobSettings(IngestedWithHashAndFileType.class.getCanonicalName(), IngestJobSettings.IngestType.FILES_ONLY, templates);
try {
IngestUtils.runIngestJob(Case.getCurrentCaseThrows().getDataSources(), ingestJobSettings);
} catch (NoCurrentCaseException | TskCoreException ex) {
Exceptions.printStackTrace(ex);
Assert.fail(ex);
}
}
@Override
public void tearDown(){
this.utils.tearDown();
}
/**
* Search using all data sources and filtering for media types. We should
* find nothing and no errors should arise.
*/
public void testOne() {
try {
Map<Long, String> dataSources = this.utils.getDataSourceMap();
CommonFilesMetadataBuilder allSourcesBuilder = new AllDataSourcesCommonFilesAlgorithm(dataSources, true, false);
CommonFilesMetadata metadata = allSourcesBuilder.findCommonFiles();
Map<Long, String> objectIdToDataSource = IntraCaseUtils.mapFileInstancesToDataSources(metadata);
List<AbstractFile> files = IntraCaseUtils.getFiles(objectIdToDataSource.keySet());
assertTrue(files.isEmpty());
} catch (NoCurrentCaseException | TskCoreException | SQLException ex) {
Exceptions.printStackTrace(ex);
}
}
/**
* Search using single data source and filtering for doc types. Observe that
* nothing is found and that nothing blows up.
*/
public void testTwo() {
try {
Map<Long, String> dataSources = this.utils.getDataSourceMap();
Long third = IntraCaseUtils.getDataSourceIdByName(IntraCaseUtils.SET3, dataSources);
CommonFilesMetadataBuilder singleSourceBuilder = new SingleDataSource(third, dataSources, true, false);
CommonFilesMetadata metadata = singleSourceBuilder.findCommonFiles();
Map<Long, String> objectIdToDataSource = IntraCaseUtils.mapFileInstancesToDataSources(metadata);
List<AbstractFile> files = IntraCaseUtils.getFiles(objectIdToDataSource.keySet());
assertTrue(files.isEmpty());
} catch (NoCurrentCaseException | TskCoreException | SQLException ex) {
Exceptions.printStackTrace(ex);
Assert.fail(ex);
}
}
}

View File

@ -0,0 +1,220 @@
/*
*
* Autopsy Forensic Browser
*
* Copyright 2018 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.commonfilessearch;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.netbeans.junit.NbTestCase;
import org.openide.util.Exceptions;
import org.python.icu.impl.Assert;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.ImageDSProcessor;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.commonfilesearch.CommonFilesMetadata;
import org.sleuthkit.autopsy.commonfilesearch.DataSourceLoader;
import org.sleuthkit.autopsy.commonfilesearch.FileInstanceMetadata;
import org.sleuthkit.autopsy.commonfilesearch.Md5Metadata;
import org.sleuthkit.autopsy.testutils.CaseUtils;
import org.sleuthkit.autopsy.testutils.IngestUtils;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.TskCoreException;
/**
*
* Provides setup and utility for testing presence of files in different data
* sets discoverable by Common Files Features.
*
* Data set definitions:
*
* set 1
* + file1
* - IMG_6175.jpg
* + file2
* - IMG_6175.jpg
* + file3
* - BasicStyleGuide.doc
*
* set 2
* - adsf.pdf
* - IMG_6175.jpg
*
* set 3
* - BasicStyleGuide.doc
* - IMG_6175.jpg
*
* set 4
* - file.dat (empty file)
*/
class IntraCaseUtils {
private static final String CASE_NAME = "IntraCaseCommonFilesSearchTest";
static final Path CASE_DIRECTORY_PATH = Paths.get(System.getProperty("java.io.tmpdir"), CASE_NAME);
private final Path imagePath1;
private final Path imagePath2;
private final Path imagePath3;
private final Path imagePath4;
static final String IMG = "IMG_6175.jpg";
static final String DOC = "BasicStyleGuide.doc";
static final String PDF = "adsf.pdf"; //not a typo - it appears this way in the test image
static final String EMPTY = "file.dat";
static final String SET1 = "commonfiles_image1_v1.vhd";
static final String SET2 = "commonfiles_image2_v1.vhd";
static final String SET3 = "commonfiles_image3_v1.vhd";
static final String SET4 = "commonfiles_image4_v1.vhd";
private final DataSourceLoader dataSourceLoader;
private final String caseName;
IntraCaseUtils(NbTestCase nbTestCase, String caseName){
imagePath1 = Paths.get(nbTestCase.getDataDir().toString(), "commonfiles_image1_v1.vhd");
imagePath2 = Paths.get(nbTestCase.getDataDir().toString(), "commonfiles_image2_v1.vhd");
imagePath3 = Paths.get(nbTestCase.getDataDir().toString(), "commonfiles_image3_v1.vhd");
imagePath4 = Paths.get(nbTestCase.getDataDir().toString(), "commonfiles_image4_v1.vhd");
this.dataSourceLoader = new DataSourceLoader();
this.caseName = caseName;
}
void setUp(){
CaseUtils.createAsCurrentCase(this.caseName);
final ImageDSProcessor imageDSProcessor = new ImageDSProcessor();
IngestUtils.addDataSource(imageDSProcessor, imagePath1);
IngestUtils.addDataSource(imageDSProcessor, imagePath2);
IngestUtils.addDataSource(imageDSProcessor, imagePath3);
IngestUtils.addDataSource(imageDSProcessor, imagePath4);
}
Map<Long, String> getDataSourceMap() throws NoCurrentCaseException, TskCoreException, SQLException{
return this.dataSourceLoader.getDataSourceMap();
}
void tearDown(){
CaseUtils.closeCurrentCase(false);
try {
CaseUtils.deleteCaseDir(CASE_DIRECTORY_PATH.toFile());
} catch (IOException ex) {
Exceptions.printStackTrace(ex);
//does not represent a failure in the common files search feature
}
}
/**
* Verify that the given file appears a precise number times in the given
* data source.
*
* @param files search domain
* @param objectIdToDataSource mapping of file ids to data source names
* @param name name of file to search for
* @param dataSource name of data source where file should appear
* @param count number of appearances of the given file
* @return true if a file with the given name exists the specified number
* of times in the given data source
*/
static boolean verifyFileExistanceAndCount(List<AbstractFile> files, Map<Long, String> objectIdToDataSource, String name, String dataSource, int count) {
int tally = 0;
for (AbstractFile file : files) {
Long objectId = file.getId();
String fileName = file.getName();
String dataSourceName = objectIdToDataSource.get(objectId);
if (fileName.equals(name) && dataSourceName.equals(dataSource)) {
tally++;
}
}
return tally == count;
}
/**
* Convenience method which verifies that a file exists within a given data
* source exactly once.
*
* @param files search domain
* @param objectIdToDataSource mapping of file ids to data source names
* @param name name of file to search for
* @param dataSource name of data source where file should appear
* @return true if a file with the given name exists once in the given data
* source
*/
static boolean verifySingularFileExistance(List<AbstractFile> files, Map<Long, String> objectIdToDataSource, String name, String dataSource) {
return verifyFileExistanceAndCount(files, objectIdToDataSource, name, dataSource, 1);
}
static Map<Long, String> mapFileInstancesToDataSources(CommonFilesMetadata metadata) {
Map<Long, String> instanceIdToDataSource = new HashMap<>();
for (Map.Entry<String, Md5Metadata> entry : metadata.getMetadata().entrySet()) {
for (FileInstanceMetadata md : entry.getValue().getMetadata()) {
instanceIdToDataSource.put(md.getObjectId(), md.getDataSourceName());
}
}
return instanceIdToDataSource;
}
static List<AbstractFile> getFiles(Set<Long> objectIds) {
List<AbstractFile> files = new ArrayList<>(objectIds.size());
for (Long id : objectIds) {
try {
AbstractFile file = Case.getCurrentCaseThrows().getSleuthkitCase().getAbstractFileById(id);
files.add(file);
} catch (NoCurrentCaseException | TskCoreException ex) {
Exceptions.printStackTrace(ex);
Assert.fail(ex);
}
}
return files;
}
static Long getDataSourceIdByName(String name, Map<Long, String> dataSources){
if(dataSources.containsValue(name)){
for(Map.Entry<Long, String> dataSource : dataSources.entrySet()){
if(dataSource.getValue().equals(name)){
return dataSource.getKey();
}
}
} else {
throw new IndexOutOfBoundsException(String.format("Name should be one of: {0}", String.join(",", dataSources.values())));
}
return null;
}
}

View File

@ -0,0 +1,114 @@
/*
*
* Autopsy Forensic Browser
*
* Copyright 2018 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.commonfilessearch;
import java.sql.SQLException;
import java.util.Map;
import static junit.framework.Assert.assertEquals;
import junit.framework.Test;
import org.netbeans.junit.NbModuleSuite;
import org.netbeans.junit.NbTestCase;
import org.openide.util.Exceptions;
import org.python.icu.impl.Assert;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.commonfilesearch.AllDataSourcesCommonFilesAlgorithm;
import org.sleuthkit.autopsy.commonfilesearch.CommonFilesMetadata;
import org.sleuthkit.autopsy.commonfilesearch.CommonFilesMetadataBuilder;
import org.sleuthkit.autopsy.commonfilesearch.SingleDataSource;
import static org.sleuthkit.autopsy.commonfilessearch.IntraCaseUtils.SET1;
import static org.sleuthkit.autopsy.commonfilessearch.IntraCaseUtils.getDataSourceIdByName;
import org.sleuthkit.datamodel.TskCoreException;
/**
* Test that cases which are created but have not run any ingest modules turn up
* no results.
*
* Setup:
*
* Add images set 1, set 2, set 3, and set 4 to case. Do not ingest.
*
*/
public class UningestedCases extends NbTestCase {
public static Test suite() {
NbModuleSuite.Configuration conf = NbModuleSuite.createConfiguration(UningestedCases.class).
clusters(".*").
enableModules(".*");
return conf.suite();
}
private final IntraCaseUtils utils;
public UningestedCases(String name) {
super(name);
this.utils = new IntraCaseUtils(this, "UningestedCasesTests");
}
@Override
public void setUp(){
this.utils.setUp();
}
@Override
public void tearDown(){
this.utils.tearDown();
}
/**
* Find all matches & all file types. Confirm no matches are found (since
* there are no hashes to match).
*/
public void testOne() {
try {
Map<Long, String> dataSources = this.utils.getDataSourceMap();
CommonFilesMetadataBuilder allSourcesBuilder = new AllDataSourcesCommonFilesAlgorithm(dataSources, false, false);
CommonFilesMetadata metadata = allSourcesBuilder.findCommonFiles();
int resultCount = metadata.size();
assertEquals(resultCount, 0);
} catch (NoCurrentCaseException | TskCoreException | SQLException ex) {
Exceptions.printStackTrace(ex);
Assert.fail(ex);
}
}
/**
* Find all matches on image #1 & all file types. Confirm no matches.
*/
public void testTwo() {
try {
Map<Long, String> dataSources = this.utils.getDataSourceMap();
Long first = getDataSourceIdByName(SET1, dataSources);
CommonFilesMetadataBuilder singleSourceBuilder = new SingleDataSource(first, dataSources, false, false);
CommonFilesMetadata metadata = singleSourceBuilder.findCommonFiles();
int resultCount = metadata.size();
assertEquals(resultCount, 0);
} catch (NoCurrentCaseException | TskCoreException | SQLException ex) {
Exceptions.printStackTrace(ex);
Assert.fail(ex);
}
}
}

View File

@ -125,5 +125,4 @@ public final class CaseUtils {
*/ */
private CaseUtils() { private CaseUtils() {
} }
} }

View File

@ -1,5 +1,5 @@
#Updated by build script #Updated by build script
#Mon, 19 Mar 2018 11:17:11 -0700 #Tue, 08 May 2018 10:29:55 -0600
LBL_splash_window_title=Starting Autopsy LBL_splash_window_title=Starting Autopsy
SPLASH_HEIGHT=314 SPLASH_HEIGHT=314
SPLASH_WIDTH=538 SPLASH_WIDTH=538
@ -8,4 +8,4 @@ SplashRunningTextBounds=0,289,538,18
SplashRunningTextColor=0x0 SplashRunningTextColor=0x0
SplashRunningTextFontSize=19 SplashRunningTextFontSize=19
currentVersion=Autopsy 4.6.0 currentVersion=Autopsy 4.7.0

View File

@ -1,4 +1,4 @@
#Updated by build script #Updated by build script
#Fri, 09 Mar 2018 13:03:41 -0700 #Tue, 08 May 2018 10:29:55 -0600
CTL_MainWindow_Title=Autopsy 4.6.0 CTL_MainWindow_Title=Autopsy 4.7.0
CTL_MainWindow_Title_No_Project=Autopsy 4.6.0 CTL_MainWindow_Title_No_Project=Autopsy 4.7.0