Merge branch '4121_correlation_types' of https://github.com/wschaeferB/autopsy into 4167-UpdateCommonAttributeGUI

This commit is contained in:
William Schaefer 2018-09-13 14:25:36 -04:00
commit 450ef528d2
33 changed files with 1874 additions and 451 deletions

View File

@ -103,10 +103,10 @@
<get src="https://drive.google.com/uc?id=1xv3Lz9m2QLq35ofDfHQNe9aHVtVzHUsj" dest="${test-input}/c2ds2_v1.vhd" skipexisting="true"/>
<get src="https://drive.google.com/uc?id=1sg-znklB9yJAWq8i1cF2W-QLOM4FjZyv" dest="${test-input}/c3ds1_v1.vhd" skipexisting="true"/>
<get src="https://drive.google.com/uc?id=1qXyaSlm3hMhv0jl6JkZEficknKjYNOlt" dest="${test-input}/c3ds2_v1.vhd" skipexisting="true"/>
<!-- <get src="TODO" dest="${test-input}/CommonFilesAttrs_img1_v1.vhd" skipexisting="true"/>
<get src="TODO" dest="${test-input}/CommonFilesAttrs_img2_v1.vhd" skipexisting="true"/>
<get src="TODO" dest="${test-input}/CommonFilesAttrs_img2_v1.vhd" skipexisting="true"/>
<get src="TODO" dest="${test-input}/CommonFilesAttrs_img2_v1.vhd" skipexisting="true"/>-->
<get src="https://drive.google.com/uc?id=1gW-SvduRwwoHmOheQypaRZ3ig-bezRre" dest="${test-input}/CommonFilesAttrs_img4_v1.vhd" skipexisting="true"/>
<get src="https://drive.google.com/uc?id=14vx83MZcd5PJadOesQz7tja-4a-Hz7eD" dest="${test-input}/CommonFilesAttrs_img3_v1.vhd" skipexisting="true"/>
<get src="https://drive.google.com/uc?id=1ZIYca4CWxyDcfF5Vf2uWkXeI83mR8L9B" dest="${test-input}/CommonFilesAttrs_img2_v1.vhd" skipexisting="true"/>
<get src="https://drive.google.com/uc?id=1RvLNhuKzqHURqeVml_o4lpv6jPCJJ9sv" dest="${test-input}/CommonFilesAttrs_img1_v1.vhd" skipexisting="true"/>
</target>

View File

@ -7,12 +7,8 @@
</configurations>
<dependencies >
<dependency conf="core->default" org="com.github.jgraph" name="jgraphx" rev="v3.8.0"/>
<dependency conf="core->default" org="org.apache.activemq" name="activemq-all" rev="5.11.1"/>
<dependency conf="core->default" org="org.apache.curator" name="curator-client" rev="2.8.0"/>
<dependency conf="core->default" org="org.apache.curator" name="curator-framework" rev="2.8.0"/>
@ -27,6 +23,7 @@
<dependency conf="core->default" org="com.adobe.xmp" name="xmpcore" rev="5.1.2"/>
<dependency conf="core->default" org="org.apache.zookeeper" name="zookeeper" rev="3.4.6"/>
<dependency conf="core->default" org="org.apache.commons" name="commons-dbcp2" rev="2.1.1"/>
<dependency conf="core->default" org="org.apache.commons" name="commons-pool2" rev="2.4.2"/>
<dependency org="com.monitorjbl" name="xlsx-streamer" rev="1.2.1"/>
@ -34,5 +31,7 @@
<dependency conf="core->default" org="org.jsoup" name="jsoup" rev="1.10.3"/>
<dependency conf="core->default" org="com.googlecode.plist" name="dd-plist" rev="1.20"/>
<dependency conf="core->default" org="commons-validator" name="commons-validator" rev="1.6"/>
</dependencies>
</ivy-module>

View File

@ -40,6 +40,7 @@ file.reference.xmpcore-5.1.3.jar=release/modules/ext/xmpcore-5.1.3.jar
file.reference.xz-1.6.jar=release/modules/ext/xz-1.6.jar
file.reference.zookeeper-3.4.6.jar=release/modules/ext/zookeeper-3.4.6.jar
file.reference.SparseBitSet-1.1.jar=release/modules/ext/SparseBitSet-1.1.jar
file.reference.commons-validator-1.6.jar=release/modules/ext/commons-validator-1.6.jar
javac.source=1.8
javac.compilerargs=-Xlint -Xlint:-serial
license.file=../LICENSE-2.0.txt

View File

@ -356,6 +356,10 @@
<runtime-relative-path>ext/cxf-rt-transports-http-3.0.16.jar</runtime-relative-path>
<binary-origin>release/modules/ext/cxf-rt-transports-http-3.0.16.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/commons-validator-1.6.jar</runtime-relative-path>
<binary-origin>release/modules/ext/commons-validator-1.6.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/curator-framework-2.8.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/curator-framework-2.8.0.jar</binary-origin>

View File

@ -38,7 +38,8 @@ import org.sleuthkit.datamodel.AbstractFile;
@Messages({"AddEditCentralRepoCommentAction.menuItemText.addEditCentralRepoComment=Add/Edit Central Repository Comment"})
public final class AddEditCentralRepoCommentAction extends AbstractAction {
private static final Logger logger = Logger.getLogger(AddEditCentralRepoCommentAction.class.getName());
private static final Logger LOGGER = Logger.getLogger(AddEditCentralRepoCommentAction.class.getName());
private static final long serialVersionUID = 1L;
private boolean addToDatabase;
private CorrelationAttributeInstance correlationAttributeInstance;
@ -101,7 +102,7 @@ public final class AddEditCentralRepoCommentAction extends AbstractAction {
comment = centralRepoCommentDialog.getComment();
} catch (EamDbException ex) {
logger.log(Level.SEVERE, "Error adding comment", ex);
LOGGER.log(Level.SEVERE, "Error adding comment", ex);
NotifyDescriptor notifyDescriptor = new NotifyDescriptor.Message(
"An error occurred while trying to save the comment to the central repository.",
NotifyDescriptor.ERROR_MESSAGE);

View File

@ -80,7 +80,7 @@
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="otherCasesPanel" pref="59" max="32767" attributes="0"/>
<Component id="otherCasesPanel" pref="58" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
</Layout>
@ -106,7 +106,7 @@
<EmptySpace min="0" pref="483" max="32767" attributes="0"/>
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="tableContainerPanel" pref="59" max="32767" attributes="0"/>
<Component id="tableContainerPanel" pref="58" max="32767" attributes="0"/>
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
</Group>
</Group>

View File

@ -52,11 +52,13 @@ import javax.swing.table.TableColumn;
import org.joda.time.DateTimeZone;
import org.joda.time.LocalDateTime;
import org.openide.nodes.Node;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle.Messages;
import org.openide.util.lookup.ServiceProvider;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.centralrepository.AddEditCentralRepoCommentAction;
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeNormalizationException;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer;
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance;
import org.sleuthkit.autopsy.centralrepository.datamodel.EamArtifactUtil;
@ -79,14 +81,14 @@ import org.sleuthkit.datamodel.TskData;
* 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 = 9)
@Messages({"DataContentViewerOtherCases.title=Other Occurrences",
"DataContentViewerOtherCases.toolTip=Displays instances of the selected file/artifact from other occurrences.",})
public class DataContentViewerOtherCases extends JPanel implements DataContentViewer {
private static final long serialVersionUID = -1L;
private static final Logger logger = Logger.getLogger(DataContentViewerOtherCases.class.getName());
private static final Logger LOGGER = Logger.getLogger(DataContentViewerOtherCases.class.getName());
private static final int DEFAULT_MIN_CELL_WIDTH = 15;
private static final int CELL_TEXT_WIDTH_PADDING = 5;
@ -123,7 +125,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
try {
saveToCSV();
} catch (NoCurrentCaseException ex) {
logger.log(Level.SEVERE, "Exception while getting open case.", ex); // NON-NLS
LOGGER.log(Level.SEVERE, "Exception while getting open case.", ex); // NON-NLS
}
} else if (jmi.equals(showCommonalityMenuItem)) {
showCommonalityDetails();
@ -138,7 +140,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
otherCasesTable.repaint();
}
} catch (EamDbException ex) {
logger.log(Level.SEVERE, "Error performing Add/Edit Central Repository Comment action", ex);
LOGGER.log(Level.SEVERE, "Error performing Add/Edit Comment action", ex); //NON-NLS
}
}
}
@ -179,17 +181,21 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
try {
EamDb dbManager = EamDb.getInstance();
for (CorrelationAttributeInstance eamArtifact : correlationAttributes) {
percentage = dbManager.getFrequencyPercentage(eamArtifact);
msg.append(Bundle.DataContentViewerOtherCases_correlatedArtifacts_byType(percentage,
eamArtifact.getCorrelationType().getDisplayName(),
eamArtifact.getCorrelationValue()));
try {
percentage = dbManager.getFrequencyPercentage(eamArtifact);
msg.append(Bundle.DataContentViewerOtherCases_correlatedArtifacts_byType(percentage,
eamArtifact.getCorrelationType().getDisplayName(),
eamArtifact.getCorrelationValue()));
} catch (CorrelationAttributeNormalizationException ex) {
LOGGER.log(Level.WARNING, String.format("Error getting commonality details for artifact with ID: %s.", eamArtifact.getID()), ex);
}
}
JOptionPane.showConfirmDialog(showCommonalityMenuItem,
msg.toString(),
Bundle.DataContentViewerOtherCases_correlatedArtifacts_title(),
DEFAULT_OPTION, PLAIN_MESSAGE);
} catch (EamDbException ex) {
logger.log(Level.SEVERE, "Error getting commonality details.", ex);
LOGGER.log(Level.SEVERE, "Error getting commonality details.", ex);
JOptionPane.showConfirmDialog(showCommonalityMenuItem,
Bundle.DataContentViewerOtherCases_correlatedArtifacts_failed(),
Bundle.DataContentViewerOtherCases_correlatedArtifacts_title(),
@ -242,7 +248,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
DEFAULT_OPTION, PLAIN_MESSAGE);
}
} catch (EamDbException ex) {
logger.log(Level.SEVERE, "Error loading case details", ex);
LOGGER.log(Level.SEVERE, "Error loading case details", ex);
JOptionPane.showConfirmDialog(showCaseDetailsMenuItem,
Bundle.DataContentViewerOtherCases_caseDetailsDialog_noDetails(),
caseDisplayName,
@ -305,7 +311,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
}
} catch (IOException ex) {
logger.log(Level.SEVERE, "Error writing selected rows to CSV.", ex);
LOGGER.log(Level.SEVERE, "Error writing selected rows to CSV.", ex);
}
}
@ -397,7 +403,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
try {
content = nodeBbArtifact.getSleuthkitCase().getContentById(nodeBbArtifact.getObjectID());
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error retrieving blackboard artifact", ex); // NON-NLS
LOGGER.log(Level.SEVERE, "Error retrieving blackboard artifact", ex); // NON-NLS
return null;
}
@ -438,33 +444,47 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
for (CorrelationAttributeInstance.Type aType : artifactTypes) {
if (aType.getId() == CorrelationAttributeInstance.FILES_TYPE_ID) {
CorrelationCase corCase = EamDb.getInstance().getCase(Case.getCurrentCase());
ret.add(new CorrelationAttributeInstance(
md5,
aType,
corCase,
CorrelationDataSource.fromTSKDataSource(corCase, file.getDataSource()),
file.getParentPath() + file.getName(),
"",
file.getKnown()));
try {
ret.add(new CorrelationAttributeInstance(
md5,
aType,
corCase,
CorrelationDataSource.fromTSKDataSource(corCase, file.getDataSource()),
file.getParentPath() + file.getName(),
"",
file.getKnown()));
} catch (CorrelationAttributeNormalizationException ex) {
LOGGER.log(Level.INFO, String.format("Unable to check create CorrelationAttribtueInstance for value %s and type %s.", md5, aType.toString()), ex);
}
break;
}
}
}
} catch (EamDbException | TskCoreException ex) {
logger.log(Level.SEVERE, "Error connecting to DB", ex); // NON-NLS
LOGGER.log(Level.SEVERE, "Error connecting to DB", ex); // NON-NLS
}
} else {
try {
// If EamDb not enabled, get the Files default correlation type to allow Other Occurances to be enabled.
if (this.file != null) {
String md5 = this.file.getMd5Hash();
if (md5 != null && !md5.isEmpty()) {
ret.add(new CorrelationAttributeInstance(CorrelationAttributeInstance.getDefaultCorrelationTypes().get(0), md5));
// If EamDb not enabled, get the Files default correlation type to allow Other Occurances to be enabled.
if (this.file != null) {
String md5 = this.file.getMd5Hash();
if (md5 != null && !md5.isEmpty()) {
try {
final CorrelationAttributeInstance.Type fileAttributeType
= CorrelationAttributeInstance.getDefaultCorrelationTypes()
.stream()
.filter(attrType -> attrType.getId() == CorrelationAttributeInstance.FILES_TYPE_ID)
.findAny()
.get();
ret.add(new CorrelationAttributeInstance(fileAttributeType, md5));
} catch (EamDbException ex) {
LOGGER.log(Level.SEVERE, "Error connecting to DB", ex); // NON-NLS
} catch (CorrelationAttributeNormalizationException ex) {
LOGGER.log(Level.INFO, String.format("Unable to create CorrelationAttributeInstance for value %s", md5), ex); // NON-NLS
}
}
} catch (EamDbException ex) {
logger.log(Level.SEVERE, "Error connecting to DB", ex); // NON-NLS
}
}
@ -496,9 +516,9 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
}
} catch (EamDbException ex) {
logger.log(Level.SEVERE, "Error getting list of cases from database.", ex); // NON-NLS
LOGGER.log(Level.SEVERE, "Error getting list of cases from database.", ex); // NON-NLS
} catch (ParseException ex) {
logger.log(Level.SEVERE, "Error parsing date of cases from database.", ex); // NON-NLS
LOGGER.log(Level.SEVERE, "Error parsing date of cases from database.", ex); // NON-NLS
}
}
@ -511,9 +531,9 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
* artifact. If the central repo is not enabled, this will only return files
* from the current case with matching MD5 hashes.
*
* @param corAttr CorrelationAttribute to query for
* @param corAttr CorrelationAttribute to query for
* @param dataSourceName Data source to filter results
* @param deviceId Device Id to filter results
* @param deviceId Device Id to filter results
*
* @return A collection of correlated artifact instances
*/
@ -558,13 +578,15 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
return nodeDataMap;
} catch (EamDbException ex) {
logger.log(Level.SEVERE, "Error getting artifact instances from database.", ex); // NON-NLS
LOGGER.log(Level.SEVERE, "Error getting artifact instances from database.", ex); // NON-NLS
} catch (CorrelationAttributeNormalizationException ex) {
LOGGER.log(Level.INFO, "Error getting artifact instances from database.", ex); // NON-NLS
} catch (NoCurrentCaseException ex) {
logger.log(Level.SEVERE, "Exception while getting open case.", ex); // NON-NLS
LOGGER.log(Level.SEVERE, "Exception while getting open case.", ex); // NON-NLS
} catch (TskCoreException ex) {
// do nothing.
// @@@ Review this behavior
logger.log(Level.SEVERE, "Exception while querying open case.", ex); // NON-NLS
LOGGER.log(Level.SEVERE, "Exception while querying open case.", ex); // NON-NLS
}
return new HashMap<>(0);
@ -574,7 +596,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
* Get all other abstract files in the current case with the same MD5 as the
* selected node.
*
* @param corAttr The CorrelationAttribute containing the MD5 to search for
* @param corAttr The CorrelationAttribute containing the MD5 to search for
* @param openCase The current case
*
* @return List of matching AbstractFile objects
@ -708,7 +730,6 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
correlatedNodeDataMap.values().forEach((nodeData) -> {
tableModel.addNodeData(nodeData);
});
}
@ -728,8 +749,8 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
* Adjust a given column for the text provided.
*
* @param columnIndex The index of the column to adjust.
* @param text The text whose length will be used to adjust the
* column width.
* @param text The text whose length will be used to adjust the column
* width.
*/
private void setColumnWidthToText(int columnIndex, String text) {
TableColumn column = otherCasesTable.getColumnModel().getColumn(columnIndex);
@ -993,5 +1014,4 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
return dataSourceID;
}
}
}

View File

@ -652,7 +652,7 @@ abstract class AbstractSqlEamDb implements EamDb {
preparedStatement.setString(1, eamArtifact.getCorrelationCase().getCaseUUID());
preparedStatement.setString(2, eamArtifact.getCorrelationDataSource().getDeviceID());
preparedStatement.setInt(3, eamArtifact.getCorrelationDataSource().getCaseID());
preparedStatement.setString(4, eamArtifact.getCorrelationValue().toLowerCase());
preparedStatement.setString(4, eamArtifact.getCorrelationValue());
preparedStatement.setString(5, eamArtifact.getFilePath().toLowerCase());
preparedStatement.setByte(6, eamArtifact.getKnownStatus().getFileKnownValue());
if ("".equals(eamArtifact.getComment())) {
@ -712,10 +712,10 @@ abstract class AbstractSqlEamDb implements EamDb {
* @throws EamDbException
*/
@Override
public List<CorrelationAttributeInstance> getArtifactInstancesByTypeValue(CorrelationAttributeInstance.Type aType, String value) throws EamDbException {
if (aType == null) {
throw new EamDbException("Correlation type is null");
}
public List<CorrelationAttributeInstance> getArtifactInstancesByTypeValue(CorrelationAttributeInstance.Type aType, String value) throws EamDbException, CorrelationAttributeNormalizationException {
String normalizedValue = CorrelationAttributeNormalizer.normalize(aType, value);
Connection conn = connect();
List<CorrelationAttributeInstance> artifactInstances = new ArrayList<>();
@ -743,7 +743,7 @@ abstract class AbstractSqlEamDb implements EamDb {
try {
preparedStatement = conn.prepareStatement(sql);
preparedStatement.setString(1, value);
preparedStatement.setString(1, normalizedValue);
resultSet = preparedStatement.executeQuery();
while (resultSet.next()) {
artifactInstance = getEamArtifactInstanceFromResultSet(resultSet, aType);
@ -809,8 +809,12 @@ abstract class AbstractSqlEamDb implements EamDb {
preparedStatement.setString(1, filePath.toLowerCase());
resultSet = preparedStatement.executeQuery();
while (resultSet.next()) {
artifactInstance = getEamArtifactInstanceFromResultSet(resultSet, aType);
artifactInstances.add(artifactInstance);
try {
artifactInstance = getEamArtifactInstanceFromResultSet(resultSet, aType);
artifactInstances.add(artifactInstance);
} catch (CorrelationAttributeNormalizationException ex) {
logger.log(Level.INFO, "Unable to get artifact instance from resultset.", ex);
}
}
} catch (SQLException ex) {
throw new EamDbException("Error getting artifact instances by artifactType and artifactValue.", ex); // NON-NLS
@ -834,13 +838,8 @@ abstract class AbstractSqlEamDb implements EamDb {
* ArtifactValue.
*/
@Override
public Long getCountArtifactInstancesByTypeValue(CorrelationAttributeInstance.Type aType, String value) throws EamDbException {
if (aType == null) {
throw new EamDbException("Correlation type is null");
}
if (value == null) {
throw new EamDbException("Correlation value is null");
}
public Long getCountArtifactInstancesByTypeValue(CorrelationAttributeInstance.Type aType, String value) throws EamDbException, CorrelationAttributeNormalizationException {
String normalizedValue = CorrelationAttributeNormalizer.normalize(aType, value);
Connection conn = connect();
@ -856,7 +855,7 @@ abstract class AbstractSqlEamDb implements EamDb {
try {
preparedStatement = conn.prepareStatement(sql);
preparedStatement.setString(1, value.toLowerCase());
preparedStatement.setString(1, normalizedValue);
resultSet = preparedStatement.executeQuery();
resultSet.next();
instanceCount = resultSet.getLong(1);
@ -872,7 +871,7 @@ abstract class AbstractSqlEamDb implements EamDb {
}
@Override
public int getFrequencyPercentage(CorrelationAttributeInstance corAttr) throws EamDbException {
public int getFrequencyPercentage(CorrelationAttributeInstance corAttr) throws EamDbException, CorrelationAttributeNormalizationException {
if (corAttr == null) {
throw new EamDbException("CorrelationAttribute is null");
}
@ -893,10 +892,8 @@ abstract class AbstractSqlEamDb implements EamDb {
* @return Number of unique tuples
*/
@Override
public Long getCountUniqueCaseDataSourceTuplesHavingTypeValue(CorrelationAttributeInstance.Type aType, String value) throws EamDbException {
if (aType == null) {
throw new EamDbException("Correlation type is null");
}
public Long getCountUniqueCaseDataSourceTuplesHavingTypeValue(CorrelationAttributeInstance.Type aType, String value) throws EamDbException, CorrelationAttributeNormalizationException {
String normalizedValue = CorrelationAttributeNormalizer.normalize(aType, value);
Connection conn = connect();
@ -914,7 +911,7 @@ abstract class AbstractSqlEamDb implements EamDb {
try {
preparedStatement = conn.prepareStatement(sql);
preparedStatement.setString(1, value);
preparedStatement.setString(1, normalizedValue);
resultSet = preparedStatement.executeQuery();
resultSet.next();
instanceCount = resultSet.getLong(1);
@ -1262,7 +1259,7 @@ abstract class AbstractSqlEamDb implements EamDb {
preparedQuery.setString(1, eamArtifact.getComment());
preparedQuery.setString(2, eamArtifact.getCorrelationCase().getCaseUUID());
preparedQuery.setString(3, eamArtifact.getCorrelationDataSource().getDeviceID());
preparedQuery.setString(4, eamArtifact.getCorrelationValue().toLowerCase());
preparedQuery.setString(4, eamArtifact.getCorrelationValue());
preparedQuery.setString(5, eamArtifact.getFilePath().toLowerCase());
preparedQuery.executeUpdate();
} catch (SQLException ex) {
@ -1289,20 +1286,14 @@ abstract class AbstractSqlEamDb implements EamDb {
*/
@Override
public CorrelationAttributeInstance getCorrelationAttributeInstance(CorrelationAttributeInstance.Type type, CorrelationCase correlationCase,
CorrelationDataSource correlationDataSource, String value, String filePath) throws EamDbException {
CorrelationDataSource correlationDataSource, String value, String filePath) throws EamDbException, CorrelationAttributeNormalizationException {
if (type == null) {
throw new EamDbException("Correlation type is null");
}
if (correlationCase == null) {
throw new EamDbException("Correlation case is null");
}
if (correlationDataSource == null) {
throw new EamDbException("Correlation data source is null");
}
if (value == null) {
throw new EamDbException("Correlation value is null");
}
if (filePath == null) {
throw new EamDbException("Correlation file path is null");
}
@ -1314,6 +1305,8 @@ abstract class AbstractSqlEamDb implements EamDb {
CorrelationAttributeInstance correlationAttributeInstance = null;
try {
String normalizedValue = CorrelationAttributeNormalizer.normalize(type, value);
String tableName = EamDbUtil.correlationTypeToInstanceTableName(type);
String sql
= "SELECT id, known_status, comment FROM "
@ -1326,7 +1319,7 @@ abstract class AbstractSqlEamDb implements EamDb {
preparedStatement = conn.prepareStatement(sql);
preparedStatement.setInt(1, correlationCase.getID());
preparedStatement.setInt(2, correlationDataSource.getID());
preparedStatement.setString(3, value.toLowerCase());
preparedStatement.setString(3, normalizedValue);
preparedStatement.setString(4, filePath.toLowerCase());
resultSet = preparedStatement.executeQuery();
if (resultSet.next()) {
@ -1457,10 +1450,8 @@ abstract class AbstractSqlEamDb implements EamDb {
* @return List with 0 or more matching eamArtifact instances.
*/
@Override
public List<CorrelationAttributeInstance> getArtifactInstancesKnownBad(CorrelationAttributeInstance.Type aType, String value) throws EamDbException {
if (aType == null) {
throw new EamDbException("Correlation type is null");
}
public List<CorrelationAttributeInstance> getArtifactInstancesKnownBad(CorrelationAttributeInstance.Type aType, String value) throws EamDbException, CorrelationAttributeNormalizationException {
String normalizedValue = CorrelationAttributeNormalizer.normalize(aType, value);
Connection conn = connect();
@ -1489,7 +1480,7 @@ abstract class AbstractSqlEamDb implements EamDb {
try {
preparedStatement = conn.prepareStatement(sql);
preparedStatement.setString(1, value);
preparedStatement.setString(1, normalizedValue);
preparedStatement.setByte(2, TskData.FileKnown.BAD.getFileKnownValue());
resultSet = preparedStatement.executeQuery();
while (resultSet.next()) {
@ -1552,8 +1543,12 @@ abstract class AbstractSqlEamDb implements EamDb {
preparedStatement.setByte(1, TskData.FileKnown.BAD.getFileKnownValue());
resultSet = preparedStatement.executeQuery();
while (resultSet.next()) {
artifactInstance = getEamArtifactInstanceFromResultSet(resultSet, aType);
artifactInstances.add(artifactInstance);
try {
artifactInstance = getEamArtifactInstanceFromResultSet(resultSet, aType);
artifactInstances.add(artifactInstance);
} catch (CorrelationAttributeNormalizationException ex) {
logger.log(Level.INFO, "Unable to get artifact instance from resultset.", ex);
}
}
} catch (SQLException ex) {
throw new EamDbException("Error getting notable artifact instances.", ex); // NON-NLS
@ -1575,10 +1570,9 @@ abstract class AbstractSqlEamDb implements EamDb {
* @return Number of matching eamArtifacts
*/
@Override
public Long getCountArtifactInstancesKnownBad(CorrelationAttributeInstance.Type aType, String value) throws EamDbException {
if (aType == null) {
throw new EamDbException("Correlation type is null");
}
public Long getCountArtifactInstancesKnownBad(CorrelationAttributeInstance.Type aType, String value) throws EamDbException, CorrelationAttributeNormalizationException {
String normalizedValue = CorrelationAttributeNormalizer.normalize(aType, value);
Connection conn = connect();
@ -1594,7 +1588,7 @@ abstract class AbstractSqlEamDb implements EamDb {
try {
preparedStatement = conn.prepareStatement(sql);
preparedStatement.setString(1, value);
preparedStatement.setString(1, normalizedValue);
preparedStatement.setByte(2, TskData.FileKnown.BAD.getFileKnownValue());
resultSet = preparedStatement.executeQuery();
resultSet.next();
@ -1623,10 +1617,9 @@ abstract class AbstractSqlEamDb implements EamDb {
* @throws EamDbException
*/
@Override
public List<String> getListCasesHavingArtifactInstancesKnownBad(CorrelationAttributeInstance.Type aType, String value) throws EamDbException {
if (aType == null) {
throw new EamDbException("Correlation type is null");
}
public List<String> getListCasesHavingArtifactInstancesKnownBad(CorrelationAttributeInstance.Type aType, String value) throws EamDbException, CorrelationAttributeNormalizationException {
String normalizedValue = CorrelationAttributeNormalizer.normalize(aType, value);
Connection conn = connect();
@ -1649,7 +1642,7 @@ abstract class AbstractSqlEamDb implements EamDb {
try {
preparedStatement = conn.prepareStatement(sql);
preparedStatement.setString(1, value);
preparedStatement.setString(1, normalizedValue);
preparedStatement.setByte(2, TskData.FileKnown.BAD.getFileKnownValue());
resultSet = preparedStatement.executeQuery();
while (resultSet.next()) {
@ -1768,7 +1761,7 @@ abstract class AbstractSqlEamDb implements EamDb {
* @throws EamDbException
*/
@Override
public boolean isFileHashInReferenceSet(String hash, int referenceSetID) throws EamDbException {
public boolean isFileHashInReferenceSet(String hash, int referenceSetID) throws EamDbException, CorrelationAttributeNormalizationException {
return isValueInReferenceSet(hash, referenceSetID, CorrelationAttributeInstance.FILES_TYPE_ID);
}
@ -1782,7 +1775,9 @@ abstract class AbstractSqlEamDb implements EamDb {
* @return true if the value is found in the reference set
*/
@Override
public boolean isValueInReferenceSet(String value, int referenceSetID, int correlationTypeID) throws EamDbException {
public boolean isValueInReferenceSet(String value, int referenceSetID, int correlationTypeID) throws EamDbException, CorrelationAttributeNormalizationException {
String normalizeValued = CorrelationAttributeNormalizer.normalize(this.getCorrelationTypeById(correlationTypeID), value);
Connection conn = connect();
@ -1795,13 +1790,13 @@ abstract class AbstractSqlEamDb implements EamDb {
try {
preparedStatement = conn.prepareStatement(String.format(sql, fileTableName));
preparedStatement.setString(1, value);
preparedStatement.setString(1, normalizeValued);
preparedStatement.setInt(2, referenceSetID);
resultSet = preparedStatement.executeQuery();
resultSet.next();
matchingInstances = resultSet.getLong(1);
} catch (SQLException ex) {
throw new EamDbException("Error determining if value (" + value + ") is in reference set " + referenceSetID, ex); // NON-NLS
throw new EamDbException("Error determining if value (" + normalizeValued + ") is in reference set " + referenceSetID, ex); // NON-NLS
} finally {
EamDbUtil.closeStatement(preparedStatement);
EamDbUtil.closeResultSet(resultSet);
@ -1820,10 +1815,10 @@ abstract class AbstractSqlEamDb implements EamDb {
* @return Global known status of the artifact
*/
@Override
public boolean isArtifactKnownBadByReference(CorrelationAttributeInstance.Type aType, String value) throws EamDbException {
if (aType == null) {
throw new EamDbException("Correlation type is null");
}
public boolean isArtifactKnownBadByReference(CorrelationAttributeInstance.Type aType, String value) throws EamDbException, CorrelationAttributeNormalizationException {
//this should be done here so that we can be certain that aType and value are valid before we proceed
String normalizeValued = CorrelationAttributeNormalizer.normalize(aType, value);
// TEMP: Only support file correlation type
if (aType.getId() != CorrelationAttributeInstance.FILES_TYPE_ID) {
@ -1839,7 +1834,7 @@ abstract class AbstractSqlEamDb implements EamDb {
try {
preparedStatement = conn.prepareStatement(String.format(sql, EamDbUtil.correlationTypeToReferenceTableName(aType)));
preparedStatement.setString(1, value);
preparedStatement.setString(1, normalizeValued);
preparedStatement.setByte(2, TskData.FileKnown.BAD.getFileKnownValue());
resultSet = preparedStatement.executeQuery();
resultSet.next();
@ -2420,10 +2415,8 @@ abstract class AbstractSqlEamDb implements EamDb {
* @throws EamDbException
*/
@Override
public List<EamGlobalFileInstance> getReferenceInstancesByTypeValue(CorrelationAttributeInstance.Type aType, String aValue) throws EamDbException {
if (aType == null) {
throw new EamDbException("Correlation type is null");
}
public List<EamGlobalFileInstance> getReferenceInstancesByTypeValue(CorrelationAttributeInstance.Type aType, String aValue) throws EamDbException, CorrelationAttributeNormalizationException {
String normalizeValued = CorrelationAttributeNormalizer.normalize(aType, aValue);
Connection conn = connect();
@ -2434,12 +2427,11 @@ abstract class AbstractSqlEamDb implements EamDb {
try {
preparedStatement1 = conn.prepareStatement(String.format(sql1, EamDbUtil.correlationTypeToReferenceTableName(aType)));
preparedStatement1.setString(1, aValue);
preparedStatement1.setString(1, normalizeValued);
resultSet = preparedStatement1.executeQuery();
while (resultSet.next()) {
globalFileInstances.add(getEamGlobalFileInstanceFromResultSet(resultSet));
}
return globalFileInstances;
} catch (SQLException ex) {
throw new EamDbException("Error getting reference instances by type and value.", ex); // NON-NLS
@ -2448,6 +2440,8 @@ abstract class AbstractSqlEamDb implements EamDb {
EamDbUtil.closeResultSet(resultSet);
EamDbUtil.closeConnection(conn);
}
return globalFileInstances;
}
/**
@ -2828,7 +2822,7 @@ abstract class AbstractSqlEamDb implements EamDb {
*
* @throws SQLException when an expected column name is not in the resultSet
*/
private CorrelationAttributeInstance getEamArtifactInstanceFromResultSet(ResultSet resultSet, CorrelationAttributeInstance.Type aType) throws SQLException, EamDbException {
private CorrelationAttributeInstance getEamArtifactInstanceFromResultSet(ResultSet resultSet, CorrelationAttributeInstance.Type aType) throws SQLException, EamDbException, CorrelationAttributeNormalizationException {
if (null == resultSet) {
return null;
}
@ -2876,7 +2870,7 @@ abstract class AbstractSqlEamDb implements EamDb {
);
}
private EamGlobalFileInstance getEamGlobalFileInstanceFromResultSet(ResultSet resultSet) throws SQLException, EamDbException {
private EamGlobalFileInstance getEamGlobalFileInstanceFromResultSet(ResultSet resultSet) throws SQLException, EamDbException, CorrelationAttributeNormalizationException {
if (null == resultSet) {
return null;
}

View File

@ -55,7 +55,7 @@ public class CorrelationAttributeInstance implements Serializable {
CorrelationCase eamCase,
CorrelationDataSource eamDataSource,
String filePath
) throws EamDbException {
) throws EamDbException, CorrelationAttributeNormalizationException {
this(correlationType, correlationValue, -1, eamCase, eamDataSource, filePath, null, TskData.FileKnown.UNKNOWN);
}
@ -67,7 +67,7 @@ public class CorrelationAttributeInstance implements Serializable {
String filePath,
String comment,
TskData.FileKnown knownStatus
) throws EamDbException {
) throws EamDbException, CorrelationAttributeNormalizationException {
this(correlationType, correlationValue, -1, eamCase, eamDataSource, filePath, comment, knownStatus);
}
@ -76,7 +76,7 @@ public class CorrelationAttributeInstance implements Serializable {
String correlationValue,
CorrelationCase correlationCase,
CorrelationDataSource fromTSKDataSource,
String string) throws EamDbException {
String string) throws EamDbException, CorrelationAttributeNormalizationException {
this(correlationType, correlationValue, -1, correlationCase, fromTSKDataSource, string, "", TskData.FileKnown.UNKNOWN);
}
@ -86,7 +86,7 @@ public class CorrelationAttributeInstance implements Serializable {
* @param aType CorrelationAttributeInstance.Type
* @param value correlation value
*/
public CorrelationAttributeInstance(Type aType, String value) throws EamDbException {
public CorrelationAttributeInstance(Type aType, String value) throws EamDbException, CorrelationAttributeNormalizationException {
this(aType, value, -1, null, null, "", "", TskData.FileKnown.UNKNOWN);
}
@ -99,17 +99,13 @@ public class CorrelationAttributeInstance implements Serializable {
String filePath,
String comment,
TskData.FileKnown knownStatus
) throws EamDbException {
) throws EamDbException, CorrelationAttributeNormalizationException {
if (filePath == null) {
throw new EamDbException("file path is null");
}
if (value == null) {
throw new EamDbException("correlation value is null");
}
this.correlationType = type;
this.correlationValue = value;
this.correlationValue = CorrelationAttributeNormalizer.normalize(type, value);
this.ID = instanceId;
this.correlationCase = eamCase;
this.correlationDataSource = eamDataSource;

View File

@ -0,0 +1,53 @@
/*
*
* 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.centralrepository.datamodel;
/**
* Thrown when a given value is not in the expected format.
*/
public class CorrelationAttributeNormalizationException extends Exception {
private static final long serialVersionUID = 1L;
/**
* Construct an exception with the given message.
* @param message error message
*/
public CorrelationAttributeNormalizationException(String message){
super(message);
}
/**
* Construct an exception with the given message and inner exception.
* @param message error message
* @param cause inner exception
*/
public CorrelationAttributeNormalizationException(String message, Throwable cause){
super(message, cause);
}
/**
* Construct an exception with the given inner exception.
* @param cause inner exception
*/
public CorrelationAttributeNormalizationException(Throwable cause){
super(cause);
}
}

View File

@ -0,0 +1,160 @@
/*
*
* 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.centralrepository.datamodel;
import java.util.List;
import java.util.Optional;
import org.apache.commons.validator.routines.DomainValidator;
import org.apache.commons.validator.routines.EmailValidator;
/**
* Provides functions for normalizing data by attribute type before insertion or querying.
*/
final public class CorrelationAttributeNormalizer {
/**
* This is a utility class - no need for constructing or subclassing, etc...
*/
private CorrelationAttributeNormalizer() { }
/**
* Normalize the data. Converts text to lower case, and ensures that the
* data is a valid string of the format expected given the attributeType.
*
* @param attributeType correlation type of data
* @param data data to normalize
*
* @return normalized data
*/
public static String normalize(CorrelationAttributeInstance.Type attributeType, String data) throws CorrelationAttributeNormalizationException {
if(attributeType == null){
throw new CorrelationAttributeNormalizationException("Attribute type was null.");
}
if(data == null){
throw new CorrelationAttributeNormalizationException("Data was null.");
}
switch(attributeType.getId()){
case CorrelationAttributeInstance.FILES_TYPE_ID:
return normalizeMd5(data);
case CorrelationAttributeInstance.DOMAIN_TYPE_ID:
return normalizeDomain(data);
case CorrelationAttributeInstance.EMAIL_TYPE_ID:
return normalizeEmail(data);
case CorrelationAttributeInstance.PHONE_TYPE_ID:
return normalizePhone(data);
case CorrelationAttributeInstance.USBID_TYPE_ID:
return normalizeUsbId(data);
default:
final String errorMessage = String.format(
"Validator function not found for attribute type: %s",
attributeType.getDisplayName());
throw new CorrelationAttributeNormalizationException(errorMessage);
}
}
/**
* Validate the data. Converts text to lower case, and ensures that the
* data is a valid string of the format expected given the attributeType.
*
* @param attributeTypeId correlation type of data
* @param data data to normalize
*
* @return normalized data
*/
public static String normalize(int attributeTypeId, String data) throws CorrelationAttributeNormalizationException {
try {
List<CorrelationAttributeInstance.Type> defaultTypes = CorrelationAttributeInstance.getDefaultCorrelationTypes();
Optional<CorrelationAttributeInstance.Type> typeOption = defaultTypes.stream().filter(attributeType -> attributeType.getId() == attributeTypeId).findAny();
if(typeOption.isPresent()){
CorrelationAttributeInstance.Type type = typeOption.get();
return CorrelationAttributeNormalizer.normalize(type, data);
} else {
throw new CorrelationAttributeNormalizationException(String.format("Given attributeTypeId did not correspond to any known Attribute: %s", attributeTypeId));
}
} catch (EamDbException ex) {
throw new CorrelationAttributeNormalizationException(ex);
}
}
/**
* Verify MD5 is the correct length and values. Make lower case.
*/
private static String normalizeMd5(String data) throws CorrelationAttributeNormalizationException {
final String validMd5Regex = "^[a-f0-9]{32}$";
final String dataLowered = data.toLowerCase();
if(dataLowered.matches(validMd5Regex)){
return dataLowered;
} else {
throw new CorrelationAttributeNormalizationException(String.format("Data purporting to be an MD5 was found not to comform to expected format: %s", data));
}
}
/**
* Verify there are no slashes or invalid domain name characters (such as '?' or \: ). Normalize to lower case.
*/
private static String normalizeDomain(String data) throws CorrelationAttributeNormalizationException {
DomainValidator validator = DomainValidator.getInstance(true);
if(validator.isValid(data)){
return data.toLowerCase();
} else {
final String validIpAddressRegex = "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$";
if(data.matches(validIpAddressRegex)){
return data;
} else {
throw new CorrelationAttributeNormalizationException(String.format("Data was expected to be a valid domain: %s", data));
}
}
}
/**
* Verify that there is an '@' and no invalid characters. Should normalize to lower case.
*/
private static String normalizeEmail(String data) throws CorrelationAttributeNormalizationException {
EmailValidator validator = EmailValidator.getInstance(true, true);
if(validator.isValid(data)){
return data.toLowerCase();
} else {
throw new CorrelationAttributeNormalizationException(String.format("Data was expected to be a valid email address: %s", data));
}
}
/**
* Verify it is only numbers and '+'. Strip spaces, dashes, and parentheses.
*/
private static String normalizePhone(String data) throws CorrelationAttributeNormalizationException {
if(data.matches("\\+?[0-9()\\-\\s]+")){
String phoneNumber = data.replaceAll("[^0-9\\+]", "");
return phoneNumber;
} else {
throw new CorrelationAttributeNormalizationException(String.format("Data was expected to be a valid phone number: %s", data));
}
}
/**
* Vacuous - will be replaced with something reasonable later.
*/
private static String normalizeUsbId(String data) throws CorrelationAttributeNormalizationException {
//TODO replace with correct usb id validation at a later date
return data;
}
}

View File

@ -213,7 +213,7 @@ public class EamArtifactUtil {
TskData.FileKnown.UNKNOWN
);
} catch (TskCoreException | EamDbException ex) {
} catch (TskCoreException | EamDbException | CorrelationAttributeNormalizationException ex) {
logger.log(Level.SEVERE, "Error creating artifact instance.", ex); // NON-NLS
return null;
} catch (NoCurrentCaseException ex) {
@ -267,7 +267,7 @@ public class EamArtifactUtil {
CorrelationAttributeInstance correlationAttributeInstance;
try {
correlationAttributeInstance = EamDb.getInstance().getCorrelationAttributeInstance(type, correlationCase, correlationDataSource, value, filePath);
} catch (EamDbException ex) {
} catch (EamDbException | CorrelationAttributeNormalizationException ex) {
logger.log(Level.WARNING, String.format(
"Correlation attribute could not be retrieved for '%s' (id=%d): %s",
content.getName(), content.getId(), ex.getMessage()));
@ -322,7 +322,7 @@ public class EamArtifactUtil {
CorrelationDataSource.fromTSKDataSource(correlationCase, af.getDataSource()),
af.getParentPath() + af.getName());
} catch (TskCoreException | EamDbException ex) {
} catch (TskCoreException | EamDbException | CorrelationAttributeNormalizationException ex) {
logger.log(Level.SEVERE, "Error making correlation attribute.", ex);
return null;
} catch (NoCurrentCaseException ex) {

View File

@ -244,7 +244,7 @@ public interface EamDb {
*
* @return List of artifact instances for a given type/value
*/
List<CorrelationAttributeInstance> getArtifactInstancesByTypeValue(CorrelationAttributeInstance.Type aType, String value) throws EamDbException;
List<CorrelationAttributeInstance> getArtifactInstancesByTypeValue(CorrelationAttributeInstance.Type aType, String value) throws EamDbException, CorrelationAttributeNormalizationException;
/**
* Retrieves eamArtifact instances from the database that are associated
@ -269,7 +269,7 @@ public interface EamDb {
* @return Number of artifact instances having ArtifactType and
* ArtifactValue.
*/
Long getCountArtifactInstancesByTypeValue(CorrelationAttributeInstance.Type aType, String value) throws EamDbException;
Long getCountArtifactInstancesByTypeValue(CorrelationAttributeInstance.Type aType, String value) throws EamDbException, CorrelationAttributeNormalizationException;
/**
* Calculate the percentage of data sources that have this attribute value.
@ -278,7 +278,7 @@ public interface EamDb {
*
* @return Int between 0 and 100
*/
int getFrequencyPercentage(CorrelationAttributeInstance corAttr) throws EamDbException;
int getFrequencyPercentage(CorrelationAttributeInstance corAttr) throws EamDbException, CorrelationAttributeNormalizationException;
/**
* Retrieves number of unique caseDisplayName / dataSource tuples in the
@ -290,7 +290,7 @@ public interface EamDb {
*
* @return Number of unique tuples
*/
Long getCountUniqueCaseDataSourceTuplesHavingTypeValue(CorrelationAttributeInstance.Type aType, String value) throws EamDbException;
Long getCountUniqueCaseDataSourceTuplesHavingTypeValue(CorrelationAttributeInstance.Type aType, String value) throws EamDbException, CorrelationAttributeNormalizationException;
/**
* Retrieves number of data sources in the database.
@ -358,7 +358,7 @@ public interface EamDb {
* @throws EamDbException
*/
CorrelationAttributeInstance getCorrelationAttributeInstance(CorrelationAttributeInstance.Type type, CorrelationCase correlationCase,
CorrelationDataSource correlationDataSource, String value, String filePath) throws EamDbException;
CorrelationDataSource correlationDataSource, String value, String filePath) throws EamDbException, CorrelationAttributeNormalizationException;
/**
* Sets an eamArtifact instance to the given known status. If eamArtifact
@ -378,7 +378,7 @@ public interface EamDb {
*
* @return List with 0 or more matching eamArtifact instances.
*/
List<CorrelationAttributeInstance> getArtifactInstancesKnownBad(CorrelationAttributeInstance.Type aType, String value) throws EamDbException;
List<CorrelationAttributeInstance> getArtifactInstancesKnownBad(CorrelationAttributeInstance.Type aType, String value) throws EamDbException, CorrelationAttributeNormalizationException;
/**
* Gets list of matching eamArtifact instances that have knownStatus =
@ -397,7 +397,7 @@ public interface EamDb {
*
* @return Number of matching eamArtifacts
*/
Long getCountArtifactInstancesKnownBad(CorrelationAttributeInstance.Type aType, String value) throws EamDbException;
Long getCountArtifactInstancesKnownBad(CorrelationAttributeInstance.Type aType, String value) throws EamDbException, CorrelationAttributeNormalizationException;
/**
* Gets list of distinct case display names, where each case has 1+ Artifact
@ -411,7 +411,7 @@ public interface EamDb {
*
* @throws EamDbException
*/
List<String> getListCasesHavingArtifactInstancesKnownBad(CorrelationAttributeInstance.Type aType, String value) throws EamDbException;
List<String> getListCasesHavingArtifactInstancesKnownBad(CorrelationAttributeInstance.Type aType, String value) throws EamDbException, CorrelationAttributeNormalizationException;
/**
* Remove a reference set and all values contained in it.
@ -462,7 +462,7 @@ public interface EamDb {
*
* @throws EamDbException
*/
public boolean isFileHashInReferenceSet(String hash, int referenceSetID) throws EamDbException;
public boolean isFileHashInReferenceSet(String hash, int referenceSetID) throws EamDbException, CorrelationAttributeNormalizationException;
/**
* Check if the given value is in a specific reference set
@ -473,7 +473,7 @@ public interface EamDb {
*
* @return true if the hash is found in the reference set
*/
public boolean isValueInReferenceSet(String value, int referenceSetID, int correlationTypeID) throws EamDbException;
public boolean isValueInReferenceSet(String value, int referenceSetID, int correlationTypeID) throws EamDbException, CorrelationAttributeNormalizationException;
/**
* Is the artifact known as bad according to the reference entries?
@ -483,7 +483,7 @@ public interface EamDb {
*
* @return Global known status of the artifact
*/
boolean isArtifactKnownBadByReference(CorrelationAttributeInstance.Type aType, String value) throws EamDbException;
boolean isArtifactKnownBadByReference(CorrelationAttributeInstance.Type aType, String value) throws EamDbException, CorrelationAttributeNormalizationException;
/**
* Add a new organization
@ -611,7 +611,7 @@ public interface EamDb {
*
* @throws EamDbException
*/
List<EamGlobalFileInstance> getReferenceInstancesByTypeValue(CorrelationAttributeInstance.Type aType, String aValue) throws EamDbException;
List<EamGlobalFileInstance> getReferenceInstancesByTypeValue(CorrelationAttributeInstance.Type aType, String aValue) throws EamDbException, CorrelationAttributeNormalizationException;
/**
* Add a new EamArtifact.Type to the db.

View File

@ -36,7 +36,7 @@ public class EamGlobalFileInstance {
int globalSetID,
String MD5Hash,
TskData.FileKnown knownStatus,
String comment) throws EamDbException {
String comment) throws EamDbException, CorrelationAttributeNormalizationException {
this(-1, globalSetID, MD5Hash, knownStatus, comment);
}
@ -45,17 +45,14 @@ public class EamGlobalFileInstance {
int globalSetID,
String MD5Hash,
TskData.FileKnown knownStatus,
String comment) throws EamDbException {
if(MD5Hash == null){
throw new EamDbException("null MD5 hash");
}
String comment) throws EamDbException, CorrelationAttributeNormalizationException {
if(knownStatus == null){
throw new EamDbException("null known status");
}
this.instanceID = instanceID;
this.globalSetID = globalSetID;
// Normalize hashes by lower casing
this.MD5Hash = MD5Hash.toLowerCase();
this.MD5Hash = CorrelationAttributeNormalizer.normalize(CorrelationAttributeInstance.FILES_TYPE_ID, MD5Hash);
this.knownStatus = knownStatus;
this.comment = comment;
}
@ -117,12 +114,8 @@ public class EamGlobalFileInstance {
/**
* @param MD5Hash the MD5Hash to set
*/
public void setMD5Hash(String MD5Hash) throws EamDbException {
if(MD5Hash == null){
throw new EamDbException("null MD5 hash");
}
// Normalize hashes by lower casing
this.MD5Hash = MD5Hash.toLowerCase();
public void setMD5Hash(String MD5Hash) throws CorrelationAttributeNormalizationException {
this.MD5Hash = CorrelationAttributeNormalizer.normalize(CorrelationAttributeInstance.FILES_TYPE_ID, MD5Hash);
}
/**

View File

@ -447,7 +447,7 @@ final class SqliteEamDb extends AbstractSqlEamDb {
* @return List of artifact instances for a given type/value
*/
@Override
public List<CorrelationAttributeInstance> getArtifactInstancesByTypeValue(CorrelationAttributeInstance.Type aType, String value) throws EamDbException {
public List<CorrelationAttributeInstance> getArtifactInstancesByTypeValue(CorrelationAttributeInstance.Type aType, String value) throws EamDbException, CorrelationAttributeNormalizationException {
try {
acquireSharedLock();
return super.getArtifactInstancesByTypeValue(aType, value);
@ -489,7 +489,7 @@ final class SqliteEamDb extends AbstractSqlEamDb {
* @throws EamDbException
*/
@Override
public Long getCountArtifactInstancesByTypeValue(CorrelationAttributeInstance.Type aType, String value) throws EamDbException {
public Long getCountArtifactInstancesByTypeValue(CorrelationAttributeInstance.Type aType, String value) throws EamDbException, CorrelationAttributeNormalizationException {
try {
acquireSharedLock();
return super.getCountArtifactInstancesByTypeValue(aType, value);
@ -499,7 +499,7 @@ final class SqliteEamDb extends AbstractSqlEamDb {
}
@Override
public int getFrequencyPercentage(CorrelationAttributeInstance corAttr) throws EamDbException {
public int getFrequencyPercentage(CorrelationAttributeInstance corAttr) throws EamDbException, CorrelationAttributeNormalizationException {
try {
acquireSharedLock();
return super.getFrequencyPercentage(corAttr);
@ -520,7 +520,7 @@ final class SqliteEamDb extends AbstractSqlEamDb {
* @throws EamDbException
*/
@Override
public Long getCountUniqueCaseDataSourceTuplesHavingTypeValue(CorrelationAttributeInstance.Type aType, String value) throws EamDbException {
public Long getCountUniqueCaseDataSourceTuplesHavingTypeValue(CorrelationAttributeInstance.Type aType, String value) throws EamDbException, CorrelationAttributeNormalizationException {
try {
acquireSharedLock();
return super.getCountUniqueCaseDataSourceTuplesHavingTypeValue(aType, value);
@ -617,7 +617,7 @@ final class SqliteEamDb extends AbstractSqlEamDb {
* @return List with 0 or more matching eamArtifact instances.
*/
@Override
public List<CorrelationAttributeInstance> getArtifactInstancesKnownBad(CorrelationAttributeInstance.Type aType, String value) throws EamDbException {
public List<CorrelationAttributeInstance> getArtifactInstancesKnownBad(CorrelationAttributeInstance.Type aType, String value) throws EamDbException, CorrelationAttributeNormalizationException {
try {
acquireSharedLock();
return super.getArtifactInstancesKnownBad(aType, value);
@ -654,7 +654,7 @@ final class SqliteEamDb extends AbstractSqlEamDb {
* @return Number of matching eamArtifacts
*/
@Override
public Long getCountArtifactInstancesKnownBad(CorrelationAttributeInstance.Type aType, String value) throws EamDbException {
public Long getCountArtifactInstancesKnownBad(CorrelationAttributeInstance.Type aType, String value) throws EamDbException, CorrelationAttributeNormalizationException {
try {
acquireSharedLock();
return super.getCountArtifactInstancesKnownBad(aType, value);
@ -676,7 +676,7 @@ final class SqliteEamDb extends AbstractSqlEamDb {
* @throws EamDbException
*/
@Override
public List<String> getListCasesHavingArtifactInstancesKnownBad(CorrelationAttributeInstance.Type aType, String value) throws EamDbException {
public List<String> getListCasesHavingArtifactInstancesKnownBad(CorrelationAttributeInstance.Type aType, String value) throws EamDbException, CorrelationAttributeNormalizationException {
try {
acquireSharedLock();
return super.getListCasesHavingArtifactInstancesKnownBad(aType, value);
@ -710,7 +710,7 @@ final class SqliteEamDb extends AbstractSqlEamDb {
* @return true if the hash is found in the reference set
*/
@Override
public boolean isValueInReferenceSet(String value, int referenceSetID, int correlationTypeID) throws EamDbException {
public boolean isValueInReferenceSet(String value, int referenceSetID, int correlationTypeID) throws EamDbException, CorrelationAttributeNormalizationException {
try {
acquireSharedLock();
return super.isValueInReferenceSet(value, referenceSetID, correlationTypeID);
@ -782,7 +782,7 @@ final class SqliteEamDb extends AbstractSqlEamDb {
* @return Global known status of the artifact
*/
@Override
public boolean isArtifactKnownBadByReference(CorrelationAttributeInstance.Type aType, String value) throws EamDbException {
public boolean isArtifactKnownBadByReference(CorrelationAttributeInstance.Type aType, String value) throws EamDbException, CorrelationAttributeNormalizationException {
try {
acquireSharedLock();
return super.isArtifactKnownBadByReference(aType, value);
@ -967,7 +967,7 @@ final class SqliteEamDb extends AbstractSqlEamDb {
* @throws EamDbException
*/
@Override
public List<EamGlobalFileInstance> getReferenceInstancesByTypeValue(CorrelationAttributeInstance.Type aType, String aValue) throws EamDbException {
public List<EamGlobalFileInstance> getReferenceInstancesByTypeValue(CorrelationAttributeInstance.Type aType, String aValue) throws EamDbException, CorrelationAttributeNormalizationException {
try {
acquireSharedLock();
return super.getReferenceInstancesByTypeValue(aType, aValue);

View File

@ -34,6 +34,7 @@ import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.casemodule.services.Blackboard;
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeNormalizationException;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.ingest.IngestManager;
import org.sleuthkit.autopsy.ingest.IngestServices;
@ -259,13 +260,18 @@ public class IngestEventsListener {
if (recentlyAddedCeArtifacts.add(eamArtifact.toString())) {
// Was it previously marked as bad?
// query db for artifact instances having this TYPE/VALUE and knownStatus = "Bad".
// if gettKnownStatus() is "Unknown" and this artifact instance was marked bad in a previous case,
// if getKnownStatus() is "Unknown" and this artifact instance was marked bad in a previous case,
// create TSK_INTERESTING_ARTIFACT_HIT artifact on BB.
if (flagNotableItemsEnabled) {
List<String> caseDisplayNames = dbManager.getListCasesHavingArtifactInstancesKnownBad(eamArtifact.getCorrelationType(), eamArtifact.getCorrelationValue());
if (!caseDisplayNames.isEmpty()) {
postCorrelatedBadArtifactToBlackboard(bbArtifact,
caseDisplayNames);
List<String> caseDisplayNames;
try {
caseDisplayNames = dbManager.getListCasesHavingArtifactInstancesKnownBad(eamArtifact.getCorrelationType(), eamArtifact.getCorrelationValue());
if (!caseDisplayNames.isEmpty()) {
postCorrelatedBadArtifactToBlackboard(bbArtifact,
caseDisplayNames);
}
} catch (CorrelationAttributeNormalizationException ex) {
LOGGER.log(Level.INFO, String.format("Unable to flag notable item: %s.", eamArtifact.toString()), ex);
}
}
eamArtifacts.add(eamArtifact);

View File

@ -28,6 +28,7 @@ import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.casemodule.services.Blackboard;
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeNormalizationException;
import org.sleuthkit.autopsy.core.RuntimeProperties;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.ingest.FileIngestModule;
@ -143,6 +144,9 @@ final class IngestModule implements FileIngestModule {
} catch (EamDbException ex) {
logger.log(Level.SEVERE, "Error searching database for artifact.", ex); // NON-NLS
return ProcessResult.ERROR;
} catch (CorrelationAttributeNormalizationException ex){
logger.log(Level.INFO, "Error searching database for artifact.", ex); // NON-NLS
return ProcessResult.ERROR;
}
}
@ -161,6 +165,9 @@ final class IngestModule implements FileIngestModule {
} catch (EamDbException ex) {
logger.log(Level.SEVERE, "Error adding artifact to bulk artifacts.", ex); // NON-NLS
return ProcessResult.ERROR;
} catch (CorrelationAttributeNormalizationException ex) {
logger.log(Level.INFO, "Error adding artifact to bulk artifacts.", ex); // NON-NLS
return ProcessResult.ERROR;
}
return ProcessResult.OK;

View File

@ -25,9 +25,12 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.logging.Level;
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance;
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeNormalizationException;
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb;
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException;
import org.sleuthkit.autopsy.coreutils.Logger;
/**
* Stores the results from the various types of common attribute searching
@ -35,6 +38,8 @@ import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException;
*/
final public class CommonAttributeSearchResults {
private static final Logger LOGGER = Logger.getLogger(CommonAttributeSearchResults.class.getName());
// maps instance count to list of attribute values.
private final Map<Integer, CommonAttributeValueList> instanceCountToAttributeValues;
@ -128,16 +133,20 @@ final public class CommonAttributeSearchResults {
for(CommonAttributeValue value : values.getDelayedMetadataList()){ // Need the real metadata
int frequencyPercentage = eamDb.getFrequencyPercentage(new CorrelationAttributeInstance(fileAttributeType, value.getValue()));
try {
int frequencyPercentage = eamDb.getFrequencyPercentage(new CorrelationAttributeInstance(fileAttributeType, value.getValue()));
if(frequencyPercentage > maximumPercentageThreshold){
if(itemsToRemove.containsKey(key)){
itemsToRemove.get(key).add(value);
} else {
List<CommonAttributeValue> toRemove = new ArrayList<>();
toRemove.add(value);
itemsToRemove.put(key, toRemove);
if(frequencyPercentage > maximumPercentageThreshold){
if(itemsToRemove.containsKey(key)){
itemsToRemove.get(key).add(value);
} else {
List<CommonAttributeValue> toRemove = new ArrayList<>();
toRemove.add(value);
itemsToRemove.put(key, toRemove);
}
}
} catch(CorrelationAttributeNormalizationException ex){
LOGGER.log(Level.WARNING, "Unable to determine frequency percentage attribute - frequency filter may not be accurate for these results.", ex);
}
}
}

View File

@ -27,6 +27,7 @@ import java.util.logging.Level;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance;
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance.Type;
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeNormalizationException;
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationCase;
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationDataSource;
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb;
@ -67,7 +68,7 @@ final class InterCaseSearchResultsProcessor {
* instances and generate nodes at the UI level.
*
* @param dataSources the cases to filter and correlate on
* @param theType the type of CR data to search
* @param theType the type of CR data to search
*/
InterCaseSearchResultsProcessor(Map<Long, String> dataSources, CorrelationAttributeInstance.Type theType) {
this.correlationType = theType;
@ -87,6 +88,7 @@ final class InterCaseSearchResultsProcessor {
.append(" GROUP BY value HAVING COUNT(DISTINCT case_id) > 1) ORDER BY value");
return sqlString.toString();
}
private String getSingleInterCaseWhereClause() {
String tableName = EamDbUtil.correlationTypeToInstanceTableName(correlationType);
StringBuilder sqlString = new StringBuilder(250);
@ -98,6 +100,7 @@ final class InterCaseSearchResultsProcessor {
.append(" AND (case_id=%s OR case_id=%s) GROUP BY value HAVING COUNT(DISTINCT case_id) > 1) ORDER BY value");
return sqlString.toString();
}
/**
* Used in the CentralRepoCommonAttributeInstance to find common attribute
* instances and generate nodes at the UI level.
@ -114,6 +117,7 @@ final class InterCaseSearchResultsProcessor {
* Finds a single CorrelationAttribute given an id.
*
* @param attrbuteId Row of CorrelationAttribute to retrieve from the EamDb
*
* @return CorrelationAttribute object representation of retrieved match
*/
CorrelationAttributeInstance findSingleCorrelationAttribute(int attrbuteId) {
@ -163,7 +167,7 @@ final class InterCaseSearchResultsProcessor {
* md5 and case.
*
* @param currentCase The current TSK Case.
* @param singleCase The case of interest. Matches must exist in this case.
* @param singleCase The case of interest. Matches must exist in this case.
*/
Map<Integer, CommonAttributeValueList> findSingleInterCaseCommonAttributeValues(Case currentCase, CorrelationCase singleCase) {
try {
@ -210,7 +214,7 @@ final class InterCaseSearchResultsProcessor {
}
//Add the final instances
CommonAttributeValueList value = new CommonAttributeValueList();
if(commonAttributeValue != null) {
if (commonAttributeValue != null) {
value.addMetadataToList(commonAttributeValue);
instanceCollatedCommonFiles.put(commonAttributeValue.getInstanceCount(), value);
}
@ -220,10 +224,13 @@ final class InterCaseSearchResultsProcessor {
}
/**
* Add a resultId to the list of matches for a given corValue, which counts to number of
* instances of that match, determining which InstanceCountNode the match will be added to.
* Add a resultId to the list of matches for a given corValue, which
* counts to number of instances of that match, determining which
* InstanceCountNode the match will be added to.
*
* @param corValue the value which matches
* @param resultId the CorrelationAttributeInstance id to be retrieved later.
* @param resultId the CorrelationAttributeInstance id to be retrieved
* later.
*/
private void countAndAddCommonAttributes(String corValue, int resultId) {
if (commonAttributeValue == null) {
@ -270,11 +277,15 @@ final class InterCaseSearchResultsProcessor {
while (resultSet.next()) {
CorrelationCase correlationCase = DbManager.getCaseById(InstanceTableCallback.getCaseId(resultSet));
CorrelationDataSource dataSource = DbManager.getDataSourceById(correlationCase, InstanceTableCallback.getDataSourceId(resultSet));
correlationAttributeInstance = DbManager.getCorrelationAttributeInstance(correlationType,
correlationCase,
dataSource,
InstanceTableCallback.getValue(resultSet),
InstanceTableCallback.getFilePath(resultSet));
try {
correlationAttributeInstance = DbManager.getCorrelationAttributeInstance(correlationType,
correlationCase,
dataSource,
InstanceTableCallback.getValue(resultSet),
InstanceTableCallback.getFilePath(resultSet));
} catch (CorrelationAttributeNormalizationException ex) {
LOGGER.log(Level.INFO, "Unable to get CorrelationAttributeInstance.", ex); // NON-NLS
}
}
} catch (SQLException | EamDbException ex) {

View File

@ -0,0 +1,50 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.5" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<Properties>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[100, 58]"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jScrollPane5" alignment="0" pref="907" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jScrollPane5" alignment="1" pref="435" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Container class="javax.swing.JScrollPane" name="jScrollPane5">
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JTextPane" name="jTextPane1">
<Properties>
<Property name="editable" type="boolean" value="false"/>
<Property name="name" type="java.lang.String" value="" noResource="true"/>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[600, 52]"/>
</Property>
</Properties>
</Component>
</SubComponents>
</Container>
</SubComponents>
</Form>

View File

@ -0,0 +1,466 @@
/*
* 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.contentviewers;
import java.awt.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import org.apache.commons.lang3.StringEscapeUtils;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.openide.nodes.Node;
import org.openide.util.lookup.ServiceProvider;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance;
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeNormalizationException;
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationCase;
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationDataSource;
import org.sleuthkit.autopsy.centralrepository.datamodel.EamArtifactUtil;
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb;
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardArtifactTag;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.ContentTag;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.Tag;
import org.sleuthkit.datamodel.TskCoreException;
/**
* Annotations view of file contents.
*/
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
@ServiceProvider(service = DataContentViewer.class, position = 8)
@NbBundle.Messages({
"AnnotationsContentViewer.title=Annotations",
"AnnotationsContentViewer.toolTip=Displays tags and comments associated with the selected content."
})
public class AnnotationsContentViewer extends javax.swing.JPanel implements DataContentViewer {
private static final Logger logger = Logger.getLogger(AnnotationsContentViewer.class.getName());
/**
* Creates an instance of AnnotationsContentViewer.
*/
public AnnotationsContentViewer() {
initComponents();
Utilities.configureTextPaneAsHtml(jTextPane1);
}
@Override
public void setNode(Node node) {
if ((node == null) || (!isSupported(node))) {
resetComponent();
return;
}
StringBuilder html = new StringBuilder();
BlackboardArtifact artifact = node.getLookup().lookup(BlackboardArtifact.class);
Content sourceFile = null;
try {
if (artifact != null) {
/*
* Get the source content based on the artifact to ensure we
* display the correct data instead of whatever was in the node.
*/
sourceFile = artifact.getSleuthkitCase().getAbstractFileById(artifact.getObjectID());
} else {
/*
* No artifact is present, so get the content based on what's
* present in the node. In this case, the selected item IS the
* source file.
*/
sourceFile = node.getLookup().lookup(AbstractFile.class);
}
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, String.format(
"Exception while trying to retrieve a Content instance from the BlackboardArtifact '%s' (id=%d).",
artifact.getDisplayName(), artifact.getArtifactID()), ex);
}
if (artifact != null) {
populateTagData(html, artifact, sourceFile);
} else {
populateTagData(html, sourceFile);
}
if (sourceFile instanceof AbstractFile) {
populateCentralRepositoryData(html, artifact, (AbstractFile) sourceFile);
}
setText(html.toString());
jTextPane1.setCaretPosition(0);
}
/**
* Populate the "Selected Item" sections with tag data for the supplied
* content.
*
* @param html The HTML text to update.
* @param content Selected content.
*/
private void populateTagData(StringBuilder html, Content content) {
try {
SleuthkitCase tskCase = Case.getCurrentCaseThrows().getSleuthkitCase();
startSection(html, "Selected Item");
List<ContentTag> fileTagsList = tskCase.getContentTagsByContent(content);
if (fileTagsList.isEmpty()) {
addMessage(html, "There are no tags for the selected content.");
} else {
for (ContentTag tag : fileTagsList) {
addTagEntry(html, tag);
}
}
endSection(html);
} catch (NoCurrentCaseException ex) {
logger.log(Level.SEVERE, "Exception while getting open case.", ex); // NON-NLS
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Exception while getting tags from the case database.", ex); //NON-NLS
}
}
/**
* Populate the "Selected Item" and "Source File" sections with tag data for
* a supplied artifact.
*
* @param html The HTML text to update.
* @param artifact A selected artifact.
* @param sourceFile The source content of the selected artifact.
*/
private void populateTagData(StringBuilder html, BlackboardArtifact artifact, Content sourceFile) {
try {
SleuthkitCase tskCase = Case.getCurrentCaseThrows().getSleuthkitCase();
startSection(html, "Selected Item");
List<BlackboardArtifactTag> artifactTagsList = tskCase.getBlackboardArtifactTagsByArtifact(artifact);
if (artifactTagsList.isEmpty()) {
addMessage(html, "There are no tags for the selected artifact.");
} else {
for (BlackboardArtifactTag tag : artifactTagsList) {
addTagEntry(html, tag);
}
}
endSection(html);
if (sourceFile != null) {
startSection(html, "Source File");
List<ContentTag> fileTagsList = tskCase.getContentTagsByContent(sourceFile);
if (fileTagsList.isEmpty()) {
addMessage(html, "There are no tags for the source content.");
} else {
for (ContentTag tag : fileTagsList) {
addTagEntry(html, tag);
}
}
endSection(html);
}
} catch (NoCurrentCaseException ex) {
logger.log(Level.SEVERE, "Exception while getting open case.", ex); // NON-NLS
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Exception while getting tags from the case database.", ex); //NON-NLS
}
}
/**
* Populate the "Central Repository Comments" section with data.
*
* @param html The HTML text to update.
* @param artifact A selected artifact (can be null).
* @param sourceFile A selected file, or a source file of the selected
* artifact.
*/
private void populateCentralRepositoryData(StringBuilder html, BlackboardArtifact artifact, AbstractFile sourceFile) {
if (EamDb.isEnabled()) {
startSection(html, "Central Repository Comments");
List<CorrelationAttributeInstance> instancesList = new ArrayList<>();
if (artifact != null) {
instancesList.addAll(EamArtifactUtil.makeInstancesFromBlackboardArtifact(artifact, false));
}
try {
List<CorrelationAttributeInstance.Type> artifactTypes = EamDb.getInstance().getDefinedCorrelationTypes();
String md5 = sourceFile.getMd5Hash();
if (md5 != null && !md5.isEmpty() && null != artifactTypes && !artifactTypes.isEmpty()) {
for (CorrelationAttributeInstance.Type attributeType : artifactTypes) {
if (attributeType.getId() == CorrelationAttributeInstance.FILES_TYPE_ID) {
CorrelationCase correlationCase = EamDb.getInstance().getCase(Case.getCurrentCase());
instancesList.add(new CorrelationAttributeInstance(
md5,
attributeType,
correlationCase,
CorrelationDataSource.fromTSKDataSource(correlationCase, sourceFile.getDataSource()),
sourceFile.getParentPath() + sourceFile.getName(),
"",
sourceFile.getKnown()));
break;
}
}
}
boolean commentDataFound = false;
for (CorrelationAttributeInstance instance : instancesList) {
List<CorrelationAttributeInstance> correlatedInstancesList =
EamDb.getInstance().getArtifactInstancesByTypeValue(instance.getCorrelationType(), instance.getCorrelationValue());
for (CorrelationAttributeInstance correlatedInstance : correlatedInstancesList) {
if (correlatedInstance.getComment() != null && correlatedInstance.getComment().isEmpty() == false) {
commentDataFound = true;
addCentralRepositoryEntry(html, correlatedInstance);
}
}
}
if (commentDataFound == false) {
addMessage(html, "There is no comment data for the selected content in the central repository.");
}
} catch (EamDbException | TskCoreException ex) {
logger.log(Level.SEVERE, "Error connecting to the central repository database.", ex); // NON-NLS
} catch (CorrelationAttributeNormalizationException ex) {
logger.log(Level.SEVERE, "Error normalizing instance from repository database.", ex); // NON-NLS
}
endSection(html);
}
}
/**
* Set the text of the text panel.
*
* @param text The text to set to the text panel.
*/
private void setText(String text) {
jTextPane1.setText("<html><body>" + text + "</body></html>"); //NON-NLS
}
/**
* Start a new data section.
*
* @param html The HTML text to add the section to.
* @param sectionName The name of the section.
*/
private void startSection(StringBuilder html, String sectionName) {
html.append("<p style=\"font-size:14px;font-weight:bold;\">")
.append(sectionName)
.append("</p><br>"); //NON-NLS
}
/**
* Add a message.
*
* @param html The HTML text to add the message to.
* @param message The message text.
*/
private void addMessage(StringBuilder html, String message) {
html.append("<p style=\"font-style:italic;\">")
.append(message)
.append("</p><br>"); //NON-NLS
}
/**
* Add a data table containing information about a tag.
*
* @param html The HTML text to add the table to.
* @param tag The tag whose information will be used to populate the table.
*/
@NbBundle.Messages({
"AnnotationsContentViewer.tagEntryDataLabel.tag=Tag:",
"AnnotationsContentViewer.tagEntryDataLabel.tagUser=Tag User:",
"AnnotationsContentViewer.tagEntryDataLabel.comment=Comment:"
})
private void addTagEntry(StringBuilder html, Tag tag) {
startTable(html);
addRow(html, Bundle.AnnotationsContentViewer_tagEntryDataLabel_tag(), tag.getName().getDisplayName());
addRow(html, Bundle.AnnotationsContentViewer_tagEntryDataLabel_tagUser(), tag.getUserName());
addRow(html, Bundle.AnnotationsContentViewer_tagEntryDataLabel_comment(), formatHtmlString(tag.getComment()));
endTable(html);
}
/**
* Add a data table containing information about a correlation attribute
* instance in the central repository.
*
* @param html The HTML text to add the table to.
* @param attributeInstance The attribute instance whose information will be
* used to populate the table.
* @param correlationType The correlation data type.
*/
@NbBundle.Messages({
"AnnotationsContentViewer.centralRepositoryEntryDataLabel.case=Case:",
"AnnotationsContentViewer.centralRepositoryEntryDataLabel.type=Type:",
"AnnotationsContentViewer.centralRepositoryEntryDataLabel.comment=Comment:",
"AnnotationsContentViewer.centralRepositoryEntryDataLabel.path=Path:"
})
private void addCentralRepositoryEntry(StringBuilder html, CorrelationAttributeInstance attributeInstance) {
startTable(html);
addRow(html, Bundle.AnnotationsContentViewer_centralRepositoryEntryDataLabel_case(), attributeInstance.getCorrelationCase().getDisplayName());
addRow(html, Bundle.AnnotationsContentViewer_centralRepositoryEntryDataLabel_type(), attributeInstance.getCorrelationType().getDisplayName());
addRow(html, Bundle.AnnotationsContentViewer_centralRepositoryEntryDataLabel_comment(), formatHtmlString(attributeInstance.getComment()));
addRow(html, Bundle.AnnotationsContentViewer_centralRepositoryEntryDataLabel_path(), attributeInstance.getFilePath());
endTable(html);
}
/**
* Start a data table.
*
* @param html The HTML text to add the table to.
*/
private void startTable(StringBuilder html) {
html.append("<table>"); //NON-NLS
}
/**
* Add a data row to a table.
*
* @param html The HTML text to add the row to.
* @param key The key for the left column of the data row.
* @param value The value for the right column of the data row.
*/
private void addRow(StringBuilder html, String key, String value) {
html.append("<tr><td valign=\"top\">"); //NON-NLS
html.append(key);
html.append("</td><td>"); //NON-NLS
html.append(value);
html.append("</td></tr>"); //NON-NLS
}
/**
* End a data table.
*
* @param html The HTML text on which to end a table.
*/
private void endTable(StringBuilder html) {
html.append("</table><br><br>"); //NON-NLS
}
/**
* End a data section.
*
* @param html The HTML text on which to end a section.
*/
private void endSection(StringBuilder html) {
html.append("<br>"); //NON-NLS
}
/**
* Apply escape sequence to special characters. Line feed and carriage
* return character combinations will be converted to HTML line breaks.
*
* @param text The text to format.
* @return The formatted text.
*/
private String formatHtmlString(String text) {
String formattedString = StringEscapeUtils.escapeHtml4(text);
return formattedString.replaceAll("(\r\n|\r|\n|\n\r)", "<br>");
}
/**
* 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
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
jScrollPane5 = new javax.swing.JScrollPane();
jTextPane1 = new javax.swing.JTextPane();
setPreferredSize(new java.awt.Dimension(100, 58));
jTextPane1.setEditable(false);
jTextPane1.setName(""); // NOI18N
jTextPane1.setPreferredSize(new java.awt.Dimension(600, 52));
jScrollPane5.setViewportView(jTextPane1);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane5, javax.swing.GroupLayout.DEFAULT_SIZE, 907, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane5, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 435, Short.MAX_VALUE)
);
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JScrollPane jScrollPane5;
private javax.swing.JTextPane jTextPane1;
// End of variables declaration//GEN-END:variables
@Override
public String getTitle() {
return Bundle.AnnotationsContentViewer_title();
}
@Override
public String getToolTip() {
return Bundle.AnnotationsContentViewer_toolTip();
}
@Override
public DataContentViewer createInstance() {
return new AnnotationsContentViewer();
}
@Override
public boolean isSupported(Node node) {
BlackboardArtifact artifact = node.getLookup().lookup(BlackboardArtifact.class);
try {
if (artifact != null) {
if (artifact.getSleuthkitCase().getAbstractFileById(artifact.getObjectID()) != null) {
return true;
}
} else {
if (node.getLookup().lookup(AbstractFile.class) != null) {
return true;
}
}
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, String.format(
"Exception while trying to retrieve a Content instance from the BlackboardArtifact '%s' (id=%d).",
artifact.getDisplayName(), artifact.getArtifactID()), ex);
}
return false;
}
@Override
public int isPreferred(Node node) {
return 1;
}
@Override
public Component getComponent() {
return this;
}
@Override
public void resetComponent() {
setText("");
}
}

View File

@ -86,6 +86,7 @@ HashDbImportDatabaseDialog.failedToGetDbPathMsg=Failed to get the path of the se
HashDbImportDatabaseDialog.importHashDbErr=Import Hash Set Error
HashDbImportDatabaseDialog.mustSelectHashDbFilePathMsg=A hash set file path must be selected.
HashDbImportDatabaseDialog.hashDbDoesNotExistMsg=The selected hash set does not exist.
HashDbImportDatabaseDialog.unableToCopyToUserDirMsg=Unable to copy the hash set to user configuration directory {0}.
HashDbImportDatabaseDialog.errorMessage.failedToOpenHashDbMsg=Failed to open hash set at {0}.
HashLookupModuleFactory.moduleName.text=Hash Lookup
HashLookupModuleFactory.moduleDescription.text=Identifies known and notable files using supplied hash sets, such as a standard NSRL hash set.
@ -237,3 +238,5 @@ HashDbCreateDatabaseDialog.lbOrg.text=Source Organization:
HashDbCreateDatabaseDialog.orgButton.text=Manage Organizations
HashDbCreateDatabaseDialog.databasePathLabel.text=Hash Set Path:
AddHashValuesToDatabaseDialog.okButton.text_2=OK
HashDbImportDatabaseDialog.saveInUserConfigFolderCheckbox.text=Copy hash set into user configuration folder
HashDbImportDatabaseDialog.saveInUserConfigFolderCheckbox.toolTipText=In Live Triage situations, this option ensures that path to the hash set will be valid

View File

@ -60,6 +60,7 @@ final class HashDbCreateDatabaseDialog extends javax.swing.JDialog {
private final static String LAST_FILE_PATH_KEY = "HashDbCreate_Path";
private EamOrganization selectedOrg = null;
private List<EamOrganization> orgs = null;
static final String HASH_DATABASE_DIR_NAME = "HashDatabases";
/**
* Displays a dialog that allows a user to create a new hash database and
@ -404,7 +405,7 @@ final class HashDbCreateDatabaseDialog extends javax.swing.JDialog {
private void saveAsButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveAsButtonActionPerformed
try {
String lastBaseDirectory = Paths.get(PlatformUtil.getUserConfigDirectory(), "HashDatabases").toString();
String lastBaseDirectory = Paths.get(PlatformUtil.getUserConfigDirectory(), HASH_DATABASE_DIR_NAME).toString();
if (ModuleSettings.settingExists(ModuleSettings.MAIN_SETTINGS, LAST_FILE_PATH_KEY)) {
lastBaseDirectory = ModuleSettings.getConfigSetting(ModuleSettings.MAIN_SETTINGS, LAST_FILE_PATH_KEY);
}

View File

@ -29,7 +29,7 @@
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
@ -86,6 +86,7 @@
</Group>
<Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="saveInUserConfigFolderCheckbox" min="-2" max="-2" attributes="0"/>
<Component id="jLabel2" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="readOnlyCheckbox" alignment="0" min="-2" max="-2" attributes="0"/>
<Group type="102" attributes="0">
@ -145,7 +146,9 @@
<Component id="readOnlyCheckbox" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="sendIngestMessagesCheckbox" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="39" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="saveInUserConfigFolderCheckbox" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="29" max="32767" attributes="0"/>
</Group>
<Group type="102" alignment="1" attributes="0">
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
@ -354,5 +357,15 @@
</Property>
</Properties>
</Component>
<Component class="javax.swing.JCheckBox" name="saveInUserConfigFolderCheckbox">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/modules/hashdatabase/Bundle.properties" key="HashDbImportDatabaseDialog.saveInUserConfigFolderCheckbox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/modules/hashdatabase/Bundle.properties" key="HashDbImportDatabaseDialog.saveInUserConfigFolderCheckbox.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
</SubComponents>
</Form>

View File

@ -27,6 +27,7 @@ import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.filechooser.FileNameExtensionFilter;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.openide.util.NbBundle;
import org.openide.windows.WindowManager;
@ -180,6 +181,7 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog {
fileTypeRadioButton = new javax.swing.JRadioButton();
centralRepoRadioButton = new javax.swing.JRadioButton();
jLabel4 = new javax.swing.JLabel();
saveInUserConfigFolderCheckbox = new javax.swing.JCheckBox();
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
@ -286,6 +288,9 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog {
org.openide.awt.Mnemonics.setLocalizedText(jLabel4, org.openide.util.NbBundle.getMessage(HashDbImportDatabaseDialog.class, "HashDbImportDatabaseDialog.jLabel4.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(saveInUserConfigFolderCheckbox, org.openide.util.NbBundle.getMessage(HashDbImportDatabaseDialog.class, "HashDbImportDatabaseDialog.saveInUserConfigFolderCheckbox.text")); // NOI18N
saveInUserConfigFolderCheckbox.setToolTipText(org.openide.util.NbBundle.getMessage(HashDbImportDatabaseDialog.class, "HashDbImportDatabaseDialog.saveInUserConfigFolderCheckbox.toolTipText")); // NOI18N
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
@ -334,6 +339,7 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog {
.addComponent(cancelButton))
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(saveInUserConfigFolderCheckbox)
.addComponent(jLabel2)
.addComponent(readOnlyCheckbox)
.addGroup(layout.createSequentialGroup()
@ -384,7 +390,9 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog {
.addComponent(readOnlyCheckbox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(sendIngestMessagesCheckbox)
.addGap(0, 39, Short.MAX_VALUE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(saveInUserConfigFolderCheckbox)
.addGap(0, 29, Short.MAX_VALUE))
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addGap(0, 0, Short.MAX_VALUE)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
@ -397,7 +405,7 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog {
}// </editor-fold>//GEN-END:initComponents
private void openButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_openButtonActionPerformed
String lastBaseDirectory = Paths.get(PlatformUtil.getUserConfigDirectory(), "HashDatabases").toString();
String lastBaseDirectory = Paths.get(PlatformUtil.getUserConfigDirectory(), HashDbCreateDatabaseDialog.HASH_DATABASE_DIR_NAME).toString();
if (ModuleSettings.settingExists(ModuleSettings.MAIN_SETTINGS, LAST_FILE_PATH_KEY)) {
lastBaseDirectory = ModuleSettings.getConfigSetting(ModuleSettings.MAIN_SETTINGS, LAST_FILE_PATH_KEY);
}
@ -492,6 +500,7 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog {
JOptionPane.ERROR_MESSAGE);
return;
}
File file = new File(selectedFilePath);
if (!file.exists()) {
JOptionPane.showMessageDialog(this,
@ -503,6 +512,22 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog {
return;
}
if (saveInUserConfigFolderCheckbox.isSelected()) {
// copy the hash database to user configuration directory and use that path instead (JIRA-4177)
String locationInUserConfigDir = Paths.get(PlatformUtil.getUserConfigDirectory(), HashDbCreateDatabaseDialog.HASH_DATABASE_DIR_NAME, hashSetNameTextField.getText(), file.getName()).toString();
try {
FileUtils.copyFile(file, new File(locationInUserConfigDir));
// update the hash database location
selectedFilePath = locationInUserConfigDir;
} catch (IOException ex) {
String errorMessage = NbBundle.getMessage(this.getClass(), "HashDbImportDatabaseDialog.unableToCopyToUserDirMsg", locationInUserConfigDir);
Logger.getLogger(HashDbImportDatabaseDialog.class.getName()).log(Level.SEVERE, errorMessage, ex);
JOptionPane.showMessageDialog(this, errorMessage, NbBundle.getMessage(this.getClass(), "HashDbImportDatabaseDialog.importHashDbErr"),
JOptionPane.ERROR_MESSAGE);
return;
}
}
KnownFilesType type;
if (knownRadioButton.isSelected()) {
type = KnownFilesType.KNOWN;
@ -622,6 +647,7 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog {
private javax.swing.JButton orgButton;
private javax.swing.JComboBox<String> orgComboBox;
private javax.swing.JCheckBox readOnlyCheckbox;
private javax.swing.JCheckBox saveInUserConfigFolderCheckbox;
private javax.swing.JCheckBox sendIngestMessagesCheckbox;
private javax.swing.ButtonGroup storageTypeButtonGroup;
private javax.swing.JTextField versionTextField;

View File

@ -39,6 +39,7 @@ import org.netbeans.api.progress.ProgressHandle;
import org.openide.util.NbBundle;
import org.openide.util.NbBundle.Messages;
import org.openide.windows.WindowManager;
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeNormalizationException;
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance;
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDb;
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException;
@ -1238,8 +1239,8 @@ public class HashDbManager implements PropertyChangeListener {
EamGlobalFileInstance fileInstance = new EamGlobalFileInstance(referenceSetID, file.getMd5Hash(),
type, comment);
EamDb.getInstance().addReferenceInstance(fileInstance,EamDb.getInstance().getCorrelationTypeById(CorrelationAttributeInstance.FILES_TYPE_ID));
} catch (EamDbException ex){
throw new TskCoreException("Error adding hashes to " + getDisplayName(), ex);
} catch (EamDbException | CorrelationAttributeNormalizationException ex){
throw new TskCoreException("Error adding hashes to " + getDisplayName(), ex); //NON-NLS
}
}
}
@ -1264,7 +1265,7 @@ public class HashDbManager implements PropertyChangeListener {
}
try {
globalFileInstances.add(new EamGlobalFileInstance(referenceSetID, hashEntry.getMd5Hash(), type, hashEntry.getComment()));
} catch (EamDbException ex){
} catch (EamDbException | CorrelationAttributeNormalizationException ex){
throw new TskCoreException("Error adding hashes to " + getDisplayName(), ex);
}
}
@ -1295,7 +1296,7 @@ public class HashDbManager implements PropertyChangeListener {
if (null != file.getMd5Hash()) {
try{
return EamDb.getInstance().isFileHashInReferenceSet(file.getMd5Hash(), this.referenceSetID);
} catch (EamDbException ex){
} catch (EamDbException | CorrelationAttributeNormalizationException ex){
Logger.getLogger(SleuthkitHashSet.class.getName()).log(Level.SEVERE, "Error performing central reposiotry hash lookup for hash "
+ file.getMd5Hash() + " in reference set " + referenceSetID, ex); //NON-NLS
throw new TskCoreException("Error performing central reposiotry hash lookup", ex);
@ -1327,7 +1328,7 @@ public class HashDbManager implements PropertyChangeListener {
// Make a bare-bones HashHitInfo for now
result = new HashHitInfo(file.getMd5Hash(), "", "");
}
} catch (EamDbException ex){
} catch (EamDbException | CorrelationAttributeNormalizationException ex){
Logger.getLogger(SleuthkitHashSet.class.getName()).log(Level.SEVERE, "Error performing central reposiotry hash lookup for hash "
+ file.getMd5Hash() + " in reference set " + referenceSetID, ex); //NON-NLS
throw new TskCoreException("Error performing central reposiotry hash lookup", ex);

View File

@ -63,6 +63,9 @@ final class HashLookupSettings implements Serializable {
private static final String configFilePath = PlatformUtil.getUserConfigDirectory() + File.separator + CONFIG_FILE_NAME;
private static final Logger logger = Logger.getLogger(HashDbManager.class.getName());
private static final String USER_DIR_PLACEHOLDER = "[UserConfigFolder]";
private static final String CURRENT_USER_DIR = PlatformUtil.getUserConfigDirectory();
private static final long serialVersionUID = 1L;
private final List<HashDbInfo> hashDbInfoList;
@ -126,6 +129,13 @@ final class HashLookupSettings implements Serializable {
try {
try (NbObjectInputStream in = new NbObjectInputStream(new FileInputStream(SERIALIZATION_FILE_PATH))) {
HashLookupSettings filesSetsSettings = (HashLookupSettings) in.readObject();
/* NOTE: to support JIRA-4177, we need to check if any of the hash
database paths are in Windows user directory. If so, we replace the path
with USER_DIR_PLACEHOLDER before saving to disk. When reading from disk,
USER_DIR_PLACEHOLDER needs to be replaced with current user directory path.
*/
convertPlaceholderToPath(filesSetsSettings);
return filesSetsSettings;
}
} catch (IOException | ClassNotFoundException ex) {
@ -282,8 +292,16 @@ final class HashLookupSettings implements Serializable {
*/
static boolean writeSettings(HashLookupSettings settings) {
/* NOTE: to support JIRA-4177, we need to check if any of the hash
database paths are in Windows user directory. If so, replace the path
with USER_DIR_PLACEHOLDER so that when it is read, it gets updated to be
the current user directory path.
*/
convertPathToPlaceholder(settings);
try (NbObjectOutputStream out = new NbObjectOutputStream(new FileOutputStream(SERIALIZATION_FILE_PATH))) {
out.writeObject(settings);
// restore the paths, in case they are going to be used somewhere
convertPlaceholderToPath(settings);
return true;
} catch (Exception ex) {
logger.log(Level.SEVERE, "Could not write hash set settings.");
@ -291,6 +309,47 @@ final class HashLookupSettings implements Serializable {
}
}
/**
* For file type hash sets, check if hash set paths needs to be modified
* per JIRA-4177. If the file path is in current Windows user directory,
* replace the path with USER_DIR_PLACEHOLDER.
*
* @param settings HashLookupSettings settings object to examiner and modify
*/
static void convertPathToPlaceholder(HashLookupSettings settings) {
for (HashDbInfo hashDbInfo : settings.getHashDbInfo()) {
if (hashDbInfo.isFileDatabaseType()) {
String dbPath = hashDbInfo.getPath();
if (dbPath.startsWith(CURRENT_USER_DIR)) {
// replace the current user directory with place holder
String remainingPath = dbPath.substring(CURRENT_USER_DIR.length());
hashDbInfo.setPath(USER_DIR_PLACEHOLDER + remainingPath);
}
}
}
}
/**
* For file type hash sets, check if hash set paths needs to be modified per
* JIRA-4177. Replace USER_DIR_PLACEHOLDER with path to current Windows user
* directory.
*
* @param settings HashLookupSettings settings object to examiner and modify
*/
static void convertPlaceholderToPath(HashLookupSettings settings) {
for (HashDbInfo hashDbInfo : settings.getHashDbInfo()) {
if (hashDbInfo.isFileDatabaseType()) {
String dbPath = hashDbInfo.getPath();
if (dbPath.startsWith(USER_DIR_PLACEHOLDER)) {
// replace the place holder with current user directory
String remainingPath = dbPath.substring(USER_DIR_PLACEHOLDER.length());
hashDbInfo.setPath(CURRENT_USER_DIR + remainingPath);
}
}
}
}
/**
* Represents the serializable information within a hash lookup in order to
* be written to disk. Used to hand off information when loading and saving
@ -308,7 +367,7 @@ final class HashLookupSettings implements Serializable {
private final HashDbManager.HashDb.KnownFilesType knownFilesType;
private boolean searchDuringIngest;
private final boolean sendIngestMessages;
private final String path;
private String path;
private final String version;
private final boolean readOnly;
private final int referenceSetID;
@ -447,6 +506,14 @@ final class HashLookupSettings implements Serializable {
return path;
}
/**
* Sets the path.
* @param path the path to set
*/
public void setPath(String path) {
this.path = path;
}
int getReferenceSetID(){
return referenceSetID;
}

View File

@ -1068,13 +1068,17 @@ class TableReportGenerator {
orderedRowData.add(makeCommaSeparatedList(getTags()));
} else if (BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID() == getArtifact().getArtifactTypeID()) {
String[] attributeDataArray = new String[3];
String[] attributeDataArray = new String[5];
// Array is used so that order of the attributes is maintained.
for (BlackboardAttribute attr : attributes) {
if (attr.getAttributeType().equals(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME))) {
attributeDataArray[0] = attr.getDisplayString();
} else if (attr.getAttributeType().equals(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CATEGORY))) {
attributeDataArray[1] = attr.getDisplayString();
} else if (attr.getAttributeType().equals(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT))) {
attributeDataArray[3] = attr.getDisplayString();
} else if (attr.getAttributeType().equals(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DESCRIPTION))) {
attributeDataArray[4] = attr.getDisplayString();
}
}
@ -1163,6 +1167,7 @@ class TableReportGenerator {
*
* @return List<String> row titles
*/
@Messages({"ReportGenerator.artTableColHdr.comment=Comment"})
private List<Column> getArtifactTableColumns(int artifactTypeId, Set<BlackboardAttribute.Type> attributeTypeSet) {
ArrayList<Column> columns = new ArrayList<>();
@ -1558,6 +1563,12 @@ class TableReportGenerator {
columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tskPath"),
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH)));
columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.comment"),
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT)));
columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.description"),
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DESCRIPTION)));
} else if (BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_ROUTE.getTypeID() == artifactTypeId) {
columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tskGpsRouteCategory"),
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CATEGORY)));

View File

@ -0,0 +1,315 @@
/*
*
* 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.centralrepository.datamodel;
import junit.framework.Test;
import org.junit.Assert;
import org.netbeans.junit.NbModuleSuite;
import org.netbeans.junit.NbTestCase;
import org.openide.util.Exceptions;
/**
* Tests for validation on each correlation attribute type.
*/
public class CorrelationAttributeNormalizerTest extends NbTestCase {
public static Test suite() {
NbModuleSuite.Configuration conf = NbModuleSuite.createConfiguration(CorrelationAttributeNormalizerTest.class).
clusters(".*").
enableModules(".*");
return conf.suite();
}
public CorrelationAttributeNormalizerTest(String name) {
super(name);
}
public void testValidateMd5() {
final String aValidHash = "e34a8899ef6468b74f8a1048419ccc8b"; //should pass
final String anInValidHash = "e34asdfa8899ef6468b74f8a1048419ccc8b"; //should fail
final String aValidHashWithCaps = "E34A8899EF6468B74F8A1048419CCC8B"; //should pass and be lowered
final String emptyHash = ""; //should fail
final String nullHash = null; //should fail
final int FILES_TYPE_ID = CorrelationAttributeInstance.FILES_TYPE_ID;
try {
assertTrue("This hash should just work", CorrelationAttributeNormalizer.normalize(FILES_TYPE_ID, aValidHash).equals(aValidHash));
} catch (CorrelationAttributeNormalizationException ex) {
Exceptions.printStackTrace(ex);
fail(ex.getMessage());
}
try {
assertTrue("This hash just needs to be converted to lower case", CorrelationAttributeNormalizer.normalize(CorrelationAttributeInstance.FILES_TYPE_ID, aValidHashWithCaps).equals(aValidHash));
} catch (CorrelationAttributeNormalizationException ex) {
Exceptions.printStackTrace(ex);
fail(ex.getMessage());
}
try {
CorrelationAttributeNormalizer.normalize(FILES_TYPE_ID, anInValidHash);
fail(THIS_SHOULD_HAVE_THROWN_AN_EXCEPTION);
} catch (CorrelationAttributeNormalizationException ex) {
assertTrue(WE_EXPECT_AN_EXCEPTION_HERE, true);
}
try {
CorrelationAttributeNormalizer.normalize(FILES_TYPE_ID, emptyHash);
fail(THIS_SHOULD_HAVE_THROWN_AN_EXCEPTION);
} catch (CorrelationAttributeNormalizationException ex) {
assertTrue(WE_EXPECT_AN_EXCEPTION_HERE, true);
}
try {
CorrelationAttributeNormalizer.normalize(FILES_TYPE_ID, nullHash);
fail(THIS_SHOULD_HAVE_THROWN_AN_EXCEPTION);
} catch (CorrelationAttributeNormalizationException ex) {
assertTrue(WE_EXPECT_AN_EXCEPTION_HERE, true);
}
}
private static final String WE_EXPECT_AN_EXCEPTION_HERE = "We expect an exception here.";
private static final String THIS_SHOULD_HAVE_THROWN_AN_EXCEPTION = "This should have thrown an exception.";
public void testValidateDomain() {
final String goodDomainOne = "www.test.com"; //should pass
final String badDomainTwo = "http://www.test.com"; //should fail (includes protocol)
final String goodDomainThree = "test.com"; //should pass
final String badDomainFour = "http://1270.0.1"; //should fail
final String badDomainFive = "?>\\/)(*&.com"; //should fail
final String badDomainSix = null; //should fail
final String badDomainSeven = ""; //should fail
final String badDomainEight = "HTTP://tests.com"; //should fail
final String badDomainNine = "http://www.test.com/aPage?aQuestion=aParam&anotherQuestion=anotherParam"; //should fail
final String goodDomainTen = "WWW.TEST.COM"; //should pass but be lowered
final String goodDomainEleven = "TEST.COM"; //should pass but be lowered
final int DOMAIN_TYPE_ID = CorrelationAttributeInstance.DOMAIN_TYPE_ID;
try {
assertTrue(THIS_DOMAIN_SHOULD_PASS, CorrelationAttributeNormalizer.normalize(DOMAIN_TYPE_ID, goodDomainOne).equals(goodDomainOne));
} catch (CorrelationAttributeNormalizationException ex) {
Exceptions.printStackTrace(ex);
fail(ex.getMessage());
}
try {
CorrelationAttributeNormalizer.normalize(DOMAIN_TYPE_ID, badDomainTwo);
fail(THIS_SHOULD_HAVE_THROWN_AN_EXCEPTION);
} catch (CorrelationAttributeNormalizationException ex) {
assertTrue(WE_EXPECT_AN_EXCEPTION_HERE, true);
}
try {
assertTrue(THIS_DOMAIN_SHOULD_PASS, CorrelationAttributeNormalizer.normalize(DOMAIN_TYPE_ID, goodDomainThree).equals(goodDomainThree));
} catch (CorrelationAttributeNormalizationException ex) {
Exceptions.printStackTrace(ex);
fail(ex.getMessage());
}
try {
assertTrue(THIS_DOMAIN_SHOULD_PASS, CorrelationAttributeNormalizer.normalize(DOMAIN_TYPE_ID, badDomainFour).equals(badDomainFour));
fail(THIS_SHOULD_HAVE_THROWN_AN_EXCEPTION);
} catch (CorrelationAttributeNormalizationException ex) {
assertTrue(WE_EXPECT_AN_EXCEPTION_HERE, true);
}
try {
CorrelationAttributeNormalizer.normalize(DOMAIN_TYPE_ID, badDomainFive);
fail(THIS_SHOULD_HAVE_THROWN_AN_EXCEPTION);
} catch (CorrelationAttributeNormalizationException ex) {
assertTrue(WE_EXPECT_AN_EXCEPTION_HERE, true);
}
try {
CorrelationAttributeNormalizer.normalize(DOMAIN_TYPE_ID, badDomainSix);
fail(THIS_SHOULD_HAVE_THROWN_AN_EXCEPTION);
} catch (CorrelationAttributeNormalizationException ex) {
assertTrue(WE_EXPECT_AN_EXCEPTION_HERE, true);
}
try {
CorrelationAttributeNormalizer.normalize(DOMAIN_TYPE_ID, badDomainSeven);
fail(THIS_SHOULD_HAVE_THROWN_AN_EXCEPTION);
} catch (CorrelationAttributeNormalizationException ex) {
assertTrue(WE_EXPECT_AN_EXCEPTION_HERE, true);
}
try {
CorrelationAttributeNormalizer.normalize(DOMAIN_TYPE_ID, badDomainEight);
fail("This should have thrown an exception");
} catch (CorrelationAttributeNormalizationException ex) {
assertTrue(WE_EXPECT_AN_EXCEPTION_HERE, true);
}
try {
CorrelationAttributeNormalizer.normalize(DOMAIN_TYPE_ID, badDomainNine);
fail("This should have thrown an exception");
} catch (CorrelationAttributeNormalizationException ex) {
assertTrue(WE_EXPECT_AN_EXCEPTION_HERE, true);
}
try {
assertTrue(THIS_DOMAIN_SHOULD_PASS, CorrelationAttributeNormalizer.normalize(DOMAIN_TYPE_ID, goodDomainTen).equals(goodDomainTen.toLowerCase()));
} catch (CorrelationAttributeNormalizationException ex) {
Exceptions.printStackTrace(ex);
fail(ex.getMessage());
}
try {
assertTrue(THIS_DOMAIN_SHOULD_PASS, CorrelationAttributeNormalizer.normalize(DOMAIN_TYPE_ID, goodDomainEleven).equals(goodDomainEleven.toLowerCase()));
} catch (CorrelationAttributeNormalizationException ex) {
Exceptions.printStackTrace(ex);
fail(ex.getMessage());
}
}
private static final String THIS_DOMAIN_SHOULD_PASS = "This domain should pass.";
public void testValidateEmail() {
final String goodEmailOne = "bsweeney@cipehrtechsolutions.com"; //should pass
final String goodEmailTwo = "BSWEENEY@ciphertechsolutions.com"; //should pass and be lowered
final String badEmailThree = ""; //should fail
final String badEmailFour = null; //should fail
final String badEmailFive = "asdf"; //should fail
final String goodEmailSix = "asdf@asdf"; //TODO looks bad but the lib accepts it...
final String badEmailSeven = "asdf.asdf"; //should
final int EMAIL_TYPE_ID = CorrelationAttributeInstance.EMAIL_TYPE_ID;
try {
assertTrue("This email should pass.", CorrelationAttributeNormalizer.normalize(EMAIL_TYPE_ID, goodEmailOne).equals(goodEmailOne));
} catch (CorrelationAttributeNormalizationException ex) {
Exceptions.printStackTrace(ex);
fail(ex.getMessage());
}
try {
assertTrue("This email should pass.", CorrelationAttributeNormalizer.normalize(EMAIL_TYPE_ID, goodEmailTwo).equals(goodEmailTwo.toLowerCase()));
} catch (CorrelationAttributeNormalizationException ex) {
Exceptions.printStackTrace(ex);
fail(ex.getMessage());
}
try {
CorrelationAttributeNormalizer.normalize(EMAIL_TYPE_ID, badEmailThree);
fail(THIS_SHOULD_HAVE_THROWN_AN_EXCEPTION);
} catch (CorrelationAttributeNormalizationException ex) {
assertTrue(WE_EXPECT_AN_EXCEPTION_HERE, true);
}
try {
CorrelationAttributeNormalizer.normalize(EMAIL_TYPE_ID, badEmailFour);
fail(THIS_SHOULD_HAVE_THROWN_AN_EXCEPTION);
} catch (CorrelationAttributeNormalizationException ex) {
assertTrue(WE_EXPECT_AN_EXCEPTION_HERE, true);
}
try {
CorrelationAttributeNormalizer.normalize(EMAIL_TYPE_ID, badEmailFive);
fail(THIS_SHOULD_HAVE_THROWN_AN_EXCEPTION);
} catch (CorrelationAttributeNormalizationException ex) {
assertTrue(WE_EXPECT_AN_EXCEPTION_HERE, true);
}
try { //TODO consider a better library?
assertTrue("This email should pass", CorrelationAttributeNormalizer.normalize(EMAIL_TYPE_ID, goodEmailSix).equals(goodEmailSix));
} catch (CorrelationAttributeNormalizationException ex) {
fail(ex.getMessage());
}
try {
CorrelationAttributeNormalizer.normalize(EMAIL_TYPE_ID, badEmailSeven);
fail(THIS_SHOULD_HAVE_THROWN_AN_EXCEPTION);
} catch (CorrelationAttributeNormalizationException ex) {
assertTrue(WE_EXPECT_AN_EXCEPTION_HERE, true);
}
}
public void testValidatePhone() {
final String goodPnOne = "19784740486";
final String goodPnTwo = "1(978) 474-0486";
final String goodPnThree = "+19784740486";
final String goodPnFour = "1 978-474-0486";
final String badPnFive = "9879879819784740486";
final String goodPnSix = "+1(978) 474-0486";
final String goodPnSeven = "+1(978) 474-0486";
final String badPnEight = "asdfasdfasdf";
final String badPnNine = "asdf19784740486adsf";
final int PHONE_TYPE_ID = CorrelationAttributeInstance.PHONE_TYPE_ID;
try {
assertTrue(THIS_PHONE_NUMBER_SHOULD_PASS, CorrelationAttributeNormalizer.normalize(PHONE_TYPE_ID, goodPnOne).equals(goodPnOne));
} catch (CorrelationAttributeNormalizationException ex) {
Exceptions.printStackTrace(ex);
fail(ex.getMessage());
}
try {
assertTrue(THIS_PHONE_NUMBER_SHOULD_PASS, CorrelationAttributeNormalizer.normalize(PHONE_TYPE_ID, goodPnTwo).equals(goodPnOne));
} catch (CorrelationAttributeNormalizationException ex) {
Exceptions.printStackTrace(ex);
fail(ex.getMessage());
}
try {
assertTrue(THIS_PHONE_NUMBER_SHOULD_PASS, CorrelationAttributeNormalizer.normalize(PHONE_TYPE_ID, goodPnThree).equals(goodPnThree));
} catch (CorrelationAttributeNormalizationException ex) {
Exceptions.printStackTrace(ex);
fail(ex.getMessage());
}
try {
assertTrue(THIS_PHONE_NUMBER_SHOULD_PASS, CorrelationAttributeNormalizer.normalize(PHONE_TYPE_ID, goodPnFour).equals(goodPnOne));
} catch (CorrelationAttributeNormalizationException ex) {
Exceptions.printStackTrace(ex);
fail(ex.getMessage());
}
try {
CorrelationAttributeNormalizer.normalize(PHONE_TYPE_ID, badPnFive);
//fail("This should have thrown an exception."); //this will eventually pass when we do a better job at this
} catch (CorrelationAttributeNormalizationException ex) {
assertTrue(WE_EXPECT_AN_EXCEPTION_HERE, true);
}
try {
assertTrue(THIS_PHONE_NUMBER_SHOULD_PASS, CorrelationAttributeNormalizer.normalize(PHONE_TYPE_ID, goodPnSix).equals(goodPnThree));
} catch (CorrelationAttributeNormalizationException ex) {
Exceptions.printStackTrace(ex);
fail(ex.getMessage());
}
try {
assertTrue(THIS_PHONE_NUMBER_SHOULD_PASS, CorrelationAttributeNormalizer.normalize(PHONE_TYPE_ID, goodPnSeven).equals(goodPnThree));
} catch (CorrelationAttributeNormalizationException ex) {
Exceptions.printStackTrace(ex);
fail(ex.getMessage());
}
try {
CorrelationAttributeNormalizer.normalize(PHONE_TYPE_ID, badPnEight);
fail("This should have thrown an exception.");
} catch (CorrelationAttributeNormalizationException ex) {
assertTrue(WE_EXPECT_AN_EXCEPTION_HERE, true);
}
try {
CorrelationAttributeNormalizer.normalize(PHONE_TYPE_ID, badPnNine);
fail("This should have thrown an exception.");
} catch (CorrelationAttributeNormalizationException ex) {
assertTrue(WE_EXPECT_AN_EXCEPTION_HERE, true);
}
}
private static final String THIS_PHONE_NUMBER_SHOULD_PASS = "This phone number should pass.";
public void testValidateUsbId() {
//TODO will need to be updated once usb validation does somethign interesting
final String goodIdOne = "0202:AAFF"; //should pass
/*final String goodIdTwo = "0202:aaff"; //should pass
final String badIdThree = "0202:axxf"; //should fail
final String badIdFour = ""; //should fail
final String badIdFive = null; //should fail
final String goodIdSix = "0202 AAFF"; //should pass
final String goodIdSeven = "0202AAFF"; //should pass
final String goodIdEight = "0202-AAFF"; //should pass*/
final int USBID_TYPE_ID = CorrelationAttributeInstance.USBID_TYPE_ID;
try {
assertTrue(THIS_USB_ID_SHOULD_PASS, CorrelationAttributeNormalizer.normalize(USBID_TYPE_ID, goodIdOne).equals(goodIdOne));
} catch (CorrelationAttributeNormalizationException ex) {
Assert.fail(ex.getMessage());
}
}
private static final String THIS_USB_ID_SHOULD_PASS = "This USB ID should pass.";
}

View File

@ -44,10 +44,13 @@ import org.sleuthkit.datamodel.TskCoreException;
* Search for commonality in different sorts of attributes (files, usb devices,
* emails, domains). Observe that frequency filtering works for various types.
*
* ***NOTE*** These tests are presently disabled because we have not figured out
* the best way to load all the necessary modules and run them during an ingest
* from within the test packages. See InterCaseTestUtils constructor for more
* notes in this situation.
* TODO (JIRA-4166): The following tests are commented out because the
* functional test framework needs to be able to configure the keyword search
* ingest module to produce instances of the correlation attributes for the
* tests. This cannot be easily done at present because the keyword search
* module resides in an NBM with a dependency on the Autopsy-Core NBM; the
* otherwise obvious solution of publicly exposing the keyword search module
* settings fails due to a circular dependency.
*
*/
public class CommonAttributeSearchInterCaseTests extends NbTestCase {
@ -61,7 +64,7 @@ public class CommonAttributeSearchInterCaseTests extends NbTestCase {
return conf.suite();
}
public CommonAttributeSearchInterCaseTests(String name) {
public CommonAttributeSearchInterCaseTests(String name) {
super(name);
this.utils = new InterCaseTestUtils(this);
}
@ -141,7 +144,7 @@ public class CommonAttributeSearchInterCaseTests extends NbTestCase {
* Test that the frequency filter behaves reasonably for attributes other
* than the file type.
*/
public void testTwo(){
public void testTwo() {
try {
Map<Long, String> dataSources = this.utils.getDataSourceMap();