diff --git a/Core/build.xml b/Core/build.xml index 428f6248b2..2c461a5017 100644 --- a/Core/build.xml +++ b/Core/build.xml @@ -103,10 +103,10 @@ - + + + + diff --git a/Core/ivy.xml b/Core/ivy.xml index 1ed71d69cf..c60161dd90 100644 --- a/Core/ivy.xml +++ b/Core/ivy.xml @@ -7,12 +7,8 @@ - - - - @@ -27,6 +23,7 @@ + @@ -34,5 +31,7 @@ + + diff --git a/Core/nbproject/project.properties b/Core/nbproject/project.properties index 90ce31dab9..335ff4fbc3 100644 --- a/Core/nbproject/project.properties +++ b/Core/nbproject/project.properties @@ -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 diff --git a/Core/nbproject/project.xml b/Core/nbproject/project.xml index 303d14422c..d5d64228b6 100644 --- a/Core/nbproject/project.xml +++ b/Core/nbproject/project.xml @@ -356,6 +356,10 @@ ext/cxf-rt-transports-http-3.0.16.jar release/modules/ext/cxf-rt-transports-http-3.0.16.jar + + ext/commons-validator-1.6.jar + release/modules/ext/commons-validator-1.6.jar + ext/curator-framework-2.8.0.jar release/modules/ext/curator-framework-2.8.0.jar diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/AddEditCentralRepoCommentAction.java b/Core/src/org/sleuthkit/autopsy/centralrepository/AddEditCentralRepoCommentAction.java index bdbf6a60b0..80bf479d1b 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/AddEditCentralRepoCommentAction.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/AddEditCentralRepoCommentAction.java @@ -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); diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.form b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.form index 9c42be16a8..828048ff5b 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.form +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.form @@ -80,7 +80,7 @@ - + @@ -106,7 +106,7 @@ - + diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java index 9da0b577b3..f22d02cd49 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java @@ -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; } @@ -427,9 +433,9 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi if (bbArtifact != null && EamDb.isEnabled()) { ret.addAll(EamArtifactUtil.makeInstancesFromBlackboardArtifact(bbArtifact, false)); } - + // we can correlate based on the MD5 if it is enabled - if (this.file != null && EamDb.isEnabled()) { + if (this.file != null && EamDb.isEnabled()) { try { List artifactTypes = EamDb.getInstance().getDefinedCorrelationTypes(); @@ -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; } } - } diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java index 288363fe95..833c27ffcc 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/AbstractSqlEamDb.java @@ -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 getArtifactInstancesByTypeValue(CorrelationAttributeInstance.Type aType, String value) throws EamDbException { - if (aType == null) { - throw new EamDbException("Correlation type is null"); - } + public List getArtifactInstancesByTypeValue(CorrelationAttributeInstance.Type aType, String value) throws EamDbException, CorrelationAttributeNormalizationException { + + String normalizedValue = CorrelationAttributeNormalizer.normalize(aType, value); + Connection conn = connect(); List 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 { - - if (type == null) { - throw new EamDbException("Correlation type is null"); - } + CorrelationDataSource correlationDataSource, String value, String filePath) throws EamDbException, CorrelationAttributeNormalizationException { + 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 getArtifactInstancesKnownBad(CorrelationAttributeInstance.Type aType, String value) throws EamDbException { - if (aType == null) { - throw new EamDbException("Correlation type is null"); - } + public List 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 getListCasesHavingArtifactInstancesKnownBad(CorrelationAttributeInstance.Type aType, String value) throws EamDbException { - if (aType == null) { - throw new EamDbException("Correlation type is null"); - } + public List 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,8 +1775,10 @@ 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(); Long matchingInstances = 0L; @@ -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,11 +1815,11 @@ 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) { return false; @@ -1837,9 +1832,9 @@ abstract class AbstractSqlEamDb implements EamDb { ResultSet resultSet = null; String sql = "SELECT count(*) FROM %s WHERE value=? AND known_status=?"; - try { + 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 getReferenceInstancesByTypeValue(CorrelationAttributeInstance.Type aType, String aValue) throws EamDbException { - if (aType == null) { - throw new EamDbException("Correlation type is null"); - } + public List 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; } diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeInstance.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeInstance.java index 6949f55011..261f8c4112 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeInstance.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeInstance.java @@ -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; diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeNormalizationException.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeNormalizationException.java new file mode 100644 index 0000000000..7bdd56e4a3 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeNormalizationException.java @@ -0,0 +1,53 @@ +/* + * + * Autopsy Forensic Browser + * + * Copyright 2018 Basis Technology Corp. + * Contact: carrier sleuthkit 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); + } +} diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeNormalizer.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeNormalizer.java new file mode 100644 index 0000000000..772e1c517e --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeNormalizer.java @@ -0,0 +1,160 @@ +/* + * + * Autopsy Forensic Browser + * + * Copyright 2018 Basis Technology Corp. + * Contact: carrier sleuthkit 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 defaultTypes = CorrelationAttributeInstance.getDefaultCorrelationTypes(); + Optional 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; + } +} diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamArtifactUtil.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamArtifactUtil.java index 48aea257ba..0ebc39744f 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamArtifactUtil.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamArtifactUtil.java @@ -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) { diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDb.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDb.java index a58daa4b9b..d7b725109b 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDb.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamDb.java @@ -244,7 +244,7 @@ public interface EamDb { * * @return List of artifact instances for a given type/value */ - List getArtifactInstancesByTypeValue(CorrelationAttributeInstance.Type aType, String value) throws EamDbException; + List 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 getArtifactInstancesKnownBad(CorrelationAttributeInstance.Type aType, String value) throws EamDbException; + List 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 getListCasesHavingArtifactInstancesKnownBad(CorrelationAttributeInstance.Type aType, String value) throws EamDbException; + List 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 getReferenceInstancesByTypeValue(CorrelationAttributeInstance.Type aType, String aValue) throws EamDbException; + List getReferenceInstancesByTypeValue(CorrelationAttributeInstance.Type aType, String aValue) throws EamDbException, CorrelationAttributeNormalizationException; /** * Add a new EamArtifact.Type to the db. diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamGlobalFileInstance.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamGlobalFileInstance.java index 3c538e67c8..9f51752251 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamGlobalFileInstance.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/EamGlobalFileInstance.java @@ -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); } /** diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDb.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDb.java index d300964b5f..4805e4e0b0 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDb.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteEamDb.java @@ -447,7 +447,7 @@ final class SqliteEamDb extends AbstractSqlEamDb { * @return List of artifact instances for a given type/value */ @Override - public List getArtifactInstancesByTypeValue(CorrelationAttributeInstance.Type aType, String value) throws EamDbException { + public List 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 getArtifactInstancesKnownBad(CorrelationAttributeInstance.Type aType, String value) throws EamDbException { + public List 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 getListCasesHavingArtifactInstancesKnownBad(CorrelationAttributeInstance.Type aType, String value) throws EamDbException { + public List 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 getReferenceInstancesByTypeValue(CorrelationAttributeInstance.Type aType, String aValue) throws EamDbException { + public List getReferenceInstancesByTypeValue(CorrelationAttributeInstance.Type aType, String aValue) throws EamDbException, CorrelationAttributeNormalizationException { try { acquireSharedLock(); return super.getReferenceInstancesByTypeValue(aType, aValue); diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/IngestEventsListener.java b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/IngestEventsListener.java index e432c4bf6b..ccca659574 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/IngestEventsListener.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/IngestEventsListener.java @@ -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; @@ -123,19 +124,19 @@ public class IngestEventsListener { public synchronized static int getCeModuleInstanceCount() { return correlationModuleInstanceCount; } - + /** * Are notable items being flagged? - * + * * @return True if flagging notable items; otherwise false. */ public synchronized static boolean isFlagNotableItems() { return flagNotableItems; } - + /** * Configure the listener to flag notable items or not. - * + * * @param value True to flag notable items; otherwise false. */ public synchronized static void setFlagNotableItems(boolean value) { @@ -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 caseDisplayNames = dbManager.getListCasesHavingArtifactInstancesKnownBad(eamArtifact.getCorrelationType(), eamArtifact.getCorrelationValue()); - if (!caseDisplayNames.isEmpty()) { - postCorrelatedBadArtifactToBlackboard(bbArtifact, - caseDisplayNames); + List 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); diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/IngestModule.java b/Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/IngestModule.java index 441380bcc6..21baf59454 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/IngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/IngestModule.java @@ -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; diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CaseDBCommonAttributeInstanceNode.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CaseDBCommonAttributeInstanceNode.java index f105d72498..c184f30231 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CaseDBCommonAttributeInstanceNode.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CaseDBCommonAttributeInstanceNode.java @@ -88,4 +88,4 @@ public class CaseDBCommonAttributeInstanceNode extends FileNode { return sheet; } -} +} \ No newline at end of file diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeSearchResults.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeSearchResults.java index 3900fc9b03..036b97a92a 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeSearchResults.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/CommonAttributeSearchResults.java @@ -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 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 toRemove = new ArrayList<>(); - toRemove.add(value); - itemsToRemove.put(key, toRemove); + if(frequencyPercentage > maximumPercentageThreshold){ + if(itemsToRemove.containsKey(key)){ + itemsToRemove.get(key).add(value); + } else { + List 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); } } } diff --git a/Core/src/org/sleuthkit/autopsy/commonfilesearch/InterCaseSearchResultsProcessor.java b/Core/src/org/sleuthkit/autopsy/commonfilesearch/InterCaseSearchResultsProcessor.java index 6e5880b2a1..d258db2cc1 100644 --- a/Core/src/org/sleuthkit/autopsy/commonfilesearch/InterCaseSearchResultsProcessor.java +++ b/Core/src/org/sleuthkit/autopsy/commonfilesearch/InterCaseSearchResultsProcessor.java @@ -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; @@ -44,7 +45,7 @@ import org.sleuthkit.datamodel.HashUtility; final class InterCaseSearchResultsProcessor { private Map dataSources; - + /** * The CorrelationAttributeInstance.Type this Processor will query on */ @@ -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 dataSources, CorrelationAttributeInstance.Type theType) { this.correlationType = theType; @@ -75,7 +76,7 @@ final class InterCaseSearchResultsProcessor { interCaseWhereClause = getInterCaseWhereClause(); singleInterCaseWhereClause = getSingleInterCaseWhereClause(); } - + private String getInterCaseWhereClause() { String tableName = EamDbUtil.correlationTypeToInstanceTableName(correlationType); StringBuilder sqlString = new StringBuilder(250); @@ -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,10 +100,11 @@ 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. - * + * * @param theType the type of CR data to search */ InterCaseSearchResultsProcessor(CorrelationAttributeInstance.Type theType) { @@ -114,11 +117,12 @@ 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) { try { - + InterCaseCommonAttributeRowCallback instancetableCallback = new InterCaseCommonAttributeRowCallback(); EamDb DbManager = EamDb.getInstance(); DbManager.processInstanceTableWhere(correlationType, String.format("id = %s", attrbuteId), instancetableCallback); @@ -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 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) { diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.form b/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.form new file mode 100755 index 0000000000..4fe61b2fb5 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.form @@ -0,0 +1,50 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java new file mode 100755 index 0000000000..f4f1d0380c --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java @@ -0,0 +1,466 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2018 Basis Technology Corp. + * Contact: carrier sleuthkit 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 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 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 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 instancesList = new ArrayList<>(); + if (artifact != null) { + instancesList.addAll(EamArtifactUtil.makeInstancesFromBlackboardArtifact(artifact, false)); + } + try { + List 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 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("" + text + ""); //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("

") + .append(sectionName) + .append("


"); //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("

") + .append(message) + .append("


"); //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(""); //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(""); //NON-NLS + } + + /** + * End a data table. + * + * @param html The HTML text on which to end a table. + */ + private void endTable(StringBuilder html) { + html.append("
"); //NON-NLS + html.append(key); + html.append(""); //NON-NLS + html.append(value); + html.append("


"); //NON-NLS + } + + /** + * End a data section. + * + * @param html The HTML text on which to end a section. + */ + private void endSection(StringBuilder html) { + html.append("
"); //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)", "
"); + } + + /** + * 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") + // //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) + ); + }// //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(""); + } +} diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/contentviewers/Bundle_ja.properties index 38f772cbf0..b033af82f9 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/Bundle_ja.properties +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/Bundle_ja.properties @@ -46,4 +46,4 @@ Metadata.toolTip=\u30d5\u30a1\u30a4\u30eb\u306e\u30e1\u30bf\u30c7\u30fc\u30bf\u3 Metadata.tableRowTitle.type=\u30bf\u30a4\u30d7 Metadata.nodeText.exceptionNotice.text=\u30d5\u30a1\u30a4\u30eb\u30e1\u30bf\u30c7\u30fc\u30bf\u3092\u53d6\u5f97\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\uff1a Metadata.nodeText.text=Sleuth Kit istat\u30c4\u30fc\u30eb\u304b\u3089\uff1a -Metadata.nodeText.nonFilePassedIn=\u5165\u529b\u3055\u308c\u305f\u3082\u306e\u306f\u30d5\u30a1\u30a4\u30eb\u3067\u306f\u3042\u308a\u307e\u305b\u3093 \ No newline at end of file +Metadata.nodeText.nonFilePassedIn=\u5165\u529b\u3055\u308c\u305f\u3082\u306e\u306f\u30d5\u30a1\u30a4\u30eb\u3067\u306f\u3042\u308a\u307e\u305b\u3093 diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle.properties b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle.properties index 5b8d772f9d..e81e5d2fc0 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle.properties @@ -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 diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.java index a20d0bf5a7..fd4978ef09 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbCreateDatabaseDialog.java @@ -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 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); } diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.form b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.form index fe5cedc889..e285e99a12 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.form +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.form @@ -29,7 +29,7 @@ - + @@ -86,6 +86,7 @@ + @@ -145,7 +146,9 @@ - + + + @@ -354,5 +357,15 @@ + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java index d779629846..db27f27365 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java @@ -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 { }// //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 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; diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java index f2baef923b..00003da9e7 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbManager.java @@ -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; @@ -644,7 +645,7 @@ public class HashDbManager implements PropertyChangeListener { return true; } - private String getValidFilePath(String hashSetName, String configuredPath) { + private String getValidFilePath(String hashSetName, String configuredPath) { // Check the configured path. File database = new File(configuredPath); if (database.exists()) { @@ -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); diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettings.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettings.java index 081ff5017c..15407a881a 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettings.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettings.java @@ -62,6 +62,9 @@ final class HashLookupSettings implements Serializable { private static final String CONFIG_FILE_NAME = "hashsets.xml"; //NON-NLS 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 hashDbInfoList; @@ -122,10 +125,17 @@ final class HashLookupSettings implements Serializable { * @throws HashLookupSettingsException If there's a problem importing the * settings */ - private static HashLookupSettings readSerializedSettings() throws HashLookupSettingsException { + private static HashLookupSettings readSerializedSettings() throws HashLookupSettingsException { 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,13 +309,54 @@ 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 * hash lookups. */ static final class HashDbInfo implements Serializable { - + enum DatabaseType{ FILE, CENTRAL_REPOSITORY @@ -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; @@ -345,7 +404,7 @@ final class HashLookupSettings implements Serializable { this.searchDuringIngest = searchDuringIngest; this.sendIngestMessages = sendIngestMessages; this.path = ""; - dbType = DatabaseType.CENTRAL_REPOSITORY; + dbType = DatabaseType.CENTRAL_REPOSITORY; } HashDbInfo(HashDbManager.HashDb db) throws TskCoreException{ @@ -445,6 +504,14 @@ final class HashLookupSettings implements Serializable { */ String getPath() { return path; + } + + /** + * Sets the path. + * @param path the path to set + */ + public void setPath(String path) { + this.path = path; } int getReferenceSetID(){ diff --git a/Core/src/org/sleuthkit/autopsy/report/TableReportGenerator.java b/Core/src/org/sleuthkit/autopsy/report/TableReportGenerator.java index 69384bfe0c..722af5494a 100644 --- a/Core/src/org/sleuthkit/autopsy/report/TableReportGenerator.java +++ b/Core/src/org/sleuthkit/autopsy/report/TableReportGenerator.java @@ -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 row titles */ + @Messages({"ReportGenerator.artTableColHdr.comment=Comment"}) private List getArtifactTableColumns(int artifactTypeId, Set attributeTypeSet) { ArrayList columns = new ArrayList<>(); @@ -1557,6 +1562,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"), diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java index 543eb59de5..db3c6d18ec 100755 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDatamodelTest.java @@ -29,7 +29,10 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.sql.ResultSet; import java.sql.SQLException; +import java.util.Iterator; +import java.util.Random; import java.util.stream.Collectors; +import java.util.stream.IntStream; import junit.framework.Test; import junit.framework.TestCase; import org.apache.commons.io.FileUtils; @@ -164,7 +167,6 @@ public class CentralRepoDatamodelTest extends TestCase { Exceptions.printStackTrace(ex); Assert.fail(ex.getMessage()); } - } @Override @@ -233,7 +235,7 @@ public class CentralRepoDatamodelTest extends TestCase { for (CorrelationAttributeInstance a : attrs) { assertTrue("Artifact did not have expected BAD status", a.getKnownStatus().equals(TskData.FileKnown.BAD)); } - } catch (EamDbException ex) { + } catch (EamDbException | CorrelationAttributeNormalizationException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex.getMessage()); } @@ -258,10 +260,10 @@ public class CentralRepoDatamodelTest extends TestCase { } else if (case2.getCaseUUID().equals(a.getCorrelationCase().getCaseUUID())) { assertTrue("Artifact did not have expected KNOWN status", a.getKnownStatus().equals(TskData.FileKnown.KNOWN)); } else { - Assert.fail("getArtifactInstancesByTypeValue returned unexpected case"); + fail("getArtifactInstancesByTypeValue returned unexpected case"); } } - } catch (EamDbException ex) { + } catch (EamDbException | CorrelationAttributeNormalizationException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex.getMessage()); } @@ -278,71 +280,79 @@ public class CentralRepoDatamodelTest extends TestCase { List attrs = EamDb.getInstance().getArtifactInstancesByTypeValue(fileType, hashToChangeToNotable); assertTrue("getArtifactInstancesByTypeValue returned " + attrs.size() + " values - expected 1", attrs.size() == 1); assertTrue("Artifact status did not change to BAD", attrs.get(0).getKnownStatus().equals(TskData.FileKnown.BAD)); - } catch (EamDbException ex) { + } catch (EamDbException | CorrelationAttributeNormalizationException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex.getMessage()); } // Try to update artifact with two CorrelationAttributeInstance instances - // This appears to no longer be a valid test, already moved fail to the catch since it no longe fails. try { - CorrelationAttributeInstance attr1 = new CorrelationAttributeInstance("badHash", fileType, case1, dataSource1fromCase1, "badPath", + CorrelationAttributeInstance attr1 = new CorrelationAttributeInstance(randomHash(), fileType, case1, dataSource1fromCase1, BAD_PATH, "", TskData.FileKnown.KNOWN); - CorrelationAttributeInstance attr2 = new CorrelationAttributeInstance("badHash", fileType, case1, dataSource1fromCase2, "badPath", + CorrelationAttributeInstance attr2 = new CorrelationAttributeInstance(randomHash(), fileType, case1, dataSource1fromCase2, BAD_PATH, "", TskData.FileKnown.KNOWN); EamDb.getInstance().setAttributeInstanceKnownStatus(attr1, TskData.FileKnown.BAD); EamDb.getInstance().setAttributeInstanceKnownStatus(attr2, TskData.FileKnown.BAD); - } catch (EamDbException ex) { + } catch (EamDbException | CorrelationAttributeNormalizationException ex) { Assert.fail("setArtifactInstanceKnownStatus threw an exception for sequential Correlation Attribute Instances updates"); } // Try to update null artifact try { EamDb.getInstance().setAttributeInstanceKnownStatus(null, TskData.FileKnown.BAD); - Assert.fail("setArtifactInstanceKnownStatus failed to throw exception for null correlation attribute"); + fail("setArtifactInstanceKnownStatus failed to throw exception for null correlation attribute"); } catch (EamDbException ex) { // This is the expected behavior } // Try to update artifact with null known status try { - CorrelationAttributeInstance attr = new CorrelationAttributeInstance("badHash", fileType, case1, dataSource1fromCase1, "badPath", + CorrelationAttributeInstance attr = new CorrelationAttributeInstance(randomHash(), fileType, case1, dataSource1fromCase1, BAD_PATH, "", TskData.FileKnown.KNOWN); EamDb.getInstance().setAttributeInstanceKnownStatus(attr, null); - Assert.fail("setArtifactInstanceKnownStatus failed to throw exception for null known status"); + fail("setArtifactInstanceKnownStatus failed to throw exception for null known status"); } catch (EamDbException ex) { // This is the expected behavior + } catch (CorrelationAttributeNormalizationException ex) { + Exceptions.printStackTrace(ex); + fail(ex.getMessage()); } // Try to update artifact with null case try { - CorrelationAttributeInstance attr = new CorrelationAttributeInstance("badHash", fileType, null, dataSource1fromCase1, "badPath", + CorrelationAttributeInstance attr = new CorrelationAttributeInstance(randomHash(), fileType, null, dataSource1fromCase1, BAD_PATH, "", TskData.FileKnown.KNOWN); EamDb.getInstance().setAttributeInstanceKnownStatus(attr, TskData.FileKnown.BAD); - Assert.fail("setArtifactInstanceKnownStatus failed to throw exception for null case"); + fail("setArtifactInstanceKnownStatus failed to throw exception for null case"); } catch (EamDbException ex) { // This is the expected behavior + } catch (CorrelationAttributeNormalizationException ex) { + Exceptions.printStackTrace(ex); + fail(ex.getMessage()); } // Try to update artifact with null data source try { - CorrelationAttributeInstance attr = new CorrelationAttributeInstance("badHash", fileType, case1, null, "badPath", + CorrelationAttributeInstance attr = new CorrelationAttributeInstance(randomHash(), fileType, case1, null, BAD_PATH, "", TskData.FileKnown.KNOWN); EamDb.getInstance().setAttributeInstanceKnownStatus(attr, TskData.FileKnown.BAD); - Assert.fail("setArtifactInstanceKnownStatus failed to throw exception for null case"); + fail("setArtifactInstanceKnownStatus failed to throw exception for null case"); } catch (EamDbException ex) { // This is the expected behavior + } catch (CorrelationAttributeNormalizationException ex) { + Exceptions.printStackTrace(ex); + fail(ex.getMessage()); } // Test getting two notable instances try { List attrs = EamDb.getInstance().getArtifactInstancesKnownBad(fileType, notableHashInBothCases); assertTrue("getArtifactInstancesKnownBad returned " + attrs.size() + " values - expected 2", attrs.size() == 2); - } catch (EamDbException ex) { + } catch (EamDbException | CorrelationAttributeNormalizationException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex.getMessage()); } @@ -351,7 +361,7 @@ public class CentralRepoDatamodelTest extends TestCase { try { List attrs = EamDb.getInstance().getArtifactInstancesKnownBad(fileType, notableHashInOneCaseKnownOther); assertTrue("getArtifactInstancesKnownBad returned " + attrs.size() + " values - expected 1", attrs.size() == 1); - } catch (EamDbException ex) { + } catch (EamDbException | CorrelationAttributeNormalizationException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex.getMessage()); } @@ -359,15 +369,22 @@ public class CentralRepoDatamodelTest extends TestCase { // Test getting notable instances with null type try { EamDb.getInstance().getArtifactInstancesKnownBad(null, notableHashInOneCaseKnownOther); - Assert.fail("getArtifactInstancesKnownBad failed to throw exception for null type"); - } catch (EamDbException ex) { + fail("getArtifactInstancesKnownBad failed to throw exception for null type"); + } catch (CorrelationAttributeNormalizationException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + fail("should have got CentralRepoValidationException"); } - // Test getting notable instances with null value (should work fine) + // Test getting notable instances with null value try { - List attrs = EamDb.getInstance().getArtifactInstancesKnownBad(fileType, null); - assertTrue("getArtifactInstancesKnownBad returned " + attrs.size() + " values - expected ", attrs.isEmpty()); + EamDb.getInstance().getArtifactInstancesKnownBad(fileType, null); + fail("should get an exception for null inout"); + } catch (CorrelationAttributeNormalizationException ex) { + //this is expecpted + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } catch (EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex.getMessage()); @@ -377,7 +394,7 @@ public class CentralRepoDatamodelTest extends TestCase { try { long count = EamDb.getInstance().getCountArtifactInstancesKnownBad(fileType, notableHashInBothCases); assertTrue("getCountArtifactInstancesKnownBad returned " + count + " values - expected 2", count == 2); - } catch (EamDbException ex) { + } catch (EamDbException | CorrelationAttributeNormalizationException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex.getMessage()); } @@ -386,7 +403,7 @@ public class CentralRepoDatamodelTest extends TestCase { try { long count = EamDb.getInstance().getCountArtifactInstancesKnownBad(fileType, notableHashInOneCaseKnownOther); assertTrue("getCountArtifactInstancesKnownBad returned " + count + " values - expected 1", count == 1); - } catch (EamDbException ex) { + } catch (EamDbException | CorrelationAttributeNormalizationException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex.getMessage()); } @@ -394,25 +411,31 @@ public class CentralRepoDatamodelTest extends TestCase { // Test getting notable instance count with null type try { EamDb.getInstance().getCountArtifactInstancesKnownBad(null, notableHashInOneCaseKnownOther); - Assert.fail("getCountArtifactInstancesKnownBad failed to throw exception for null type"); - } catch (EamDbException ex) { - // This is the expected behavior - } - - // Test getting notable instance count with null value (should work fine) - try { - long count = EamDb.getInstance().getCountArtifactInstancesKnownBad(fileType, null); - assertTrue("getCountArtifactInstancesKnownBad returned " + count + " values - expected ", count == 0); + fail("getCountArtifactInstancesKnownBad failed to throw exception for null type"); } catch (EamDbException ex) { Exceptions.printStackTrace(ex); - Assert.fail(ex.getMessage()); + fail(ex.getMessage()); + } catch (CorrelationAttributeNormalizationException ex){ + // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); + } + + // Test getting notable instance count with null value (should throw an exception) + try { + EamDb.getInstance().getCountArtifactInstancesKnownBad(fileType, null); + } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + fail(ex.getMessage()); + } catch (CorrelationAttributeNormalizationException ex){ + // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } // Test getting cases with notable instances (all instances are notable) try { List cases = EamDb.getInstance().getListCasesHavingArtifactInstancesKnownBad(fileType, notableHashInBothCases); assertTrue("getListCasesHavingArtifactInstancesKnownBad returned " + cases.size() + " values - expected 2", cases.size() == 2); - } catch (EamDbException ex) { + } catch (EamDbException | CorrelationAttributeNormalizationException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex.getMessage()); } @@ -422,7 +445,7 @@ public class CentralRepoDatamodelTest extends TestCase { List cases = EamDb.getInstance().getListCasesHavingArtifactInstancesKnownBad(fileType, notableHashInOneCaseKnownOther); assertTrue("getListCasesHavingArtifactInstancesKnownBad returned " + cases.size() + " values - expected 1", cases.size() == 1); assertTrue("getListCasesHavingArtifactInstancesKnownBad returned unexpected case " + cases.get(0), case1.getDisplayName().equals(cases.get(0))); - } catch (EamDbException ex) { + } catch (EamDbException | CorrelationAttributeNormalizationException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex.getMessage()); } @@ -430,20 +453,28 @@ public class CentralRepoDatamodelTest extends TestCase { // Test getting cases with null type try { EamDb.getInstance().getListCasesHavingArtifactInstancesKnownBad(null, notableHashInOneCaseKnownOther); - Assert.fail("getListCasesHavingArtifactInstancesKnownBad failed to throw exception for null type"); + fail("getListCasesHavingArtifactInstancesKnownBad failed to throw exception for null type"); } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + fail(ex.getMessage()); + } catch (CorrelationAttributeNormalizationException ex){ // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } - // Test getting cases with null value (should work fine) + // Test getting cases with null value (should throw exception) try { List cases = EamDb.getInstance().getListCasesHavingArtifactInstancesKnownBad(fileType, null); assertTrue("getListCasesHavingArtifactInstancesKnownBad returned " + cases.size() + " values - expected ", cases.isEmpty()); } catch (EamDbException ex) { Exceptions.printStackTrace(ex); - Assert.fail(ex.getMessage()); + fail(ex.getMessage()); + } catch (CorrelationAttributeNormalizationException ex){ + // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } } + private static final String BAD_PATH = "badPath"; /** * Test the methods associated with bulk artifacts (addAttributeInstanceBulk and @@ -476,7 +507,7 @@ public class CentralRepoDatamodelTest extends TestCase { // Create the first list, which will have (bulkThreshold / 2) entries List list1 = new ArrayList<>(); for (int i = 0; i < DEFAULT_BULK_THRESHOLD / 2; i++) { - String value = "bulkInsertValue1_" + String.valueOf(i); + String value = randomHash(); String path = "C:\\bulkInsertPath1\\file" + String.valueOf(i); CorrelationAttributeInstance attr = new CorrelationAttributeInstance(value, fileType, case1, dataSource1fromCase1, path); @@ -495,7 +526,7 @@ public class CentralRepoDatamodelTest extends TestCase { // Make a second list with length equal to bulkThreshold List list2 = new ArrayList<>(); for (int i = 0; i < DEFAULT_BULK_THRESHOLD; i++) { - String value = "bulkInsertValue2_" + String.valueOf(i); + String value = randomHash(); String path = "C:\\bulkInsertPath2\\file" + String.valueOf(i); CorrelationAttributeInstance attr = new CorrelationAttributeInstance(value, fileType, case1, dataSource1fromCase1, path); @@ -517,57 +548,77 @@ public class CentralRepoDatamodelTest extends TestCase { int expectedCount = list1.size() + list2.size(); assertTrue("Artifact count " + count + " does not match expected count " + expectedCount, count == expectedCount); - } catch (EamDbException ex) { + } catch (EamDbException | CorrelationAttributeNormalizationException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex.getMessage()); } // Test preparing artifact with null type try { - CorrelationAttributeInstance attr = new CorrelationAttributeInstance(null, "value"); + CorrelationAttributeInstance attr = new CorrelationAttributeInstance(null, randomHash()); EamDb.getInstance().addAttributeInstanceBulk(attr); - Assert.fail("prepareBulkArtifact failed to throw exception for null type"); + fail("prepareBulkArtifact failed to throw exception for null type"); } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + fail(ex.getMessage()); + } catch (CorrelationAttributeNormalizationException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } // Test preparing artifact with null case try { - CorrelationAttributeInstance attr = new CorrelationAttributeInstance("value", fileType, null, dataSource1fromCase1, "path"); + CorrelationAttributeInstance attr = new CorrelationAttributeInstance(randomHash(), fileType, null, dataSource1fromCase1, "path"); EamDb.getInstance().addAttributeInstanceBulk(attr); EamDb.getInstance().commitAttributeInstancesBulk(); - Assert.fail("bulkInsertArtifacts failed to throw exception for null case"); + fail("bulkInsertArtifacts failed to throw exception for null case"); } catch (EamDbException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); + } catch (CorrelationAttributeNormalizationException ex) { + Exceptions.printStackTrace(ex); + fail(ex.getMessage()); } // Test preparing artifact with null data source try { - CorrelationAttributeInstance attr = new CorrelationAttributeInstance("value", fileType, case1, null, "path"); + CorrelationAttributeInstance attr = new CorrelationAttributeInstance(randomHash(), fileType, case1, null, "path"); EamDb.getInstance().addAttributeInstanceBulk(attr); EamDb.getInstance().commitAttributeInstancesBulk(); - Assert.fail("prepareBulkArtifact failed to throw exception for null data source"); + fail("prepareBulkArtifact failed to throw exception for null data source"); } catch (EamDbException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); + } catch (CorrelationAttributeNormalizationException ex) { + Exceptions.printStackTrace(ex); + fail(ex.getMessage()); } // Test preparing artifact with null path // CorrelationAttributeInstance will throw an exception try { - CorrelationAttributeInstance attr = new CorrelationAttributeInstance("value", fileType, case1, dataSource1fromCase1, null); - Assert.fail("CorrelationAttributeInstance failed to throw exception for null path"); + new CorrelationAttributeInstance(randomHash(), fileType, case1, dataSource1fromCase1, null); + fail("CorrelationAttributeInstance failed to throw exception for null path"); } catch (EamDbException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); + } catch (CorrelationAttributeNormalizationException ex) { + Exceptions.printStackTrace(ex); + fail(ex.getMessage()); } // Test preparing artifact with null known status try { - CorrelationAttributeInstance attr = new CorrelationAttributeInstance("value", fileType, case1, dataSource1fromCase1, "path", "comment", null); + CorrelationAttributeInstance attr = new CorrelationAttributeInstance(randomHash(), fileType, case1, dataSource1fromCase1, "path", "comment", null); EamDb.getInstance().addAttributeInstanceBulk(attr); EamDb.getInstance().commitAttributeInstancesBulk(); - Assert.fail("prepareBulkArtifact failed to throw exception for null known status"); + fail("prepareBulkArtifact failed to throw exception for null known status"); } catch (EamDbException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); + } catch (CorrelationAttributeNormalizationException ex) { + Exceptions.printStackTrace(ex); + fail(ex.getMessage()); } } @@ -659,7 +710,7 @@ public class CentralRepoDatamodelTest extends TestCase { try { CorrelationAttributeInstance attr = new CorrelationAttributeInstance(onlyInDataSource3Hash, fileType, case2, dataSource1fromCase2, onlyInDataSource3Path); EamDb.getInstance().addArtifactInstance(attr); - } catch (EamDbException ex) { + } catch (EamDbException | CorrelationAttributeNormalizationException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex.getMessage()); } @@ -673,7 +724,7 @@ public class CentralRepoDatamodelTest extends TestCase { CorrelationAttributeInstance attr3 = new CorrelationAttributeInstance(inAllDataSourcesHash, fileType, case2, dataSource1fromCase2, inAllDataSourcesPath); EamDb.getInstance().addArtifactInstance(attr3); - } catch (EamDbException ex) { + } catch (EamDbException | CorrelationAttributeNormalizationException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex.getMessage()); } @@ -685,7 +736,7 @@ public class CentralRepoDatamodelTest extends TestCase { CorrelationAttributeInstance attr2 = new CorrelationAttributeInstance(inDataSource1twiceHash, fileType, case1, dataSource1fromCase1, inDataSource1twicePath2); EamDb.getInstance().addArtifactInstance(attr2); - } catch (EamDbException ex) { + } catch (EamDbException | CorrelationAttributeNormalizationException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex.getMessage()); } @@ -695,7 +746,7 @@ public class CentralRepoDatamodelTest extends TestCase { try { CorrelationAttributeInstance attr = new CorrelationAttributeInstance(emailValue, emailType, case1, dataSource1fromCase1, emailPath); EamDb.getInstance().addArtifactInstance(attr); - } catch (EamDbException ex) { + } catch (EamDbException | CorrelationAttributeNormalizationException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex.getMessage()); } @@ -708,7 +759,7 @@ public class CentralRepoDatamodelTest extends TestCase { case1, dataSource1fromCase1, phonePath); EamDb.getInstance().addArtifactInstance(attr); - } catch (EamDbException ex) { + } catch (EamDbException | CorrelationAttributeNormalizationException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex.getMessage()); } @@ -720,7 +771,7 @@ public class CentralRepoDatamodelTest extends TestCase { EamDb.getInstance().getCorrelationTypeById(CorrelationAttributeInstance.DOMAIN_TYPE_ID), case1, dataSource1fromCase1, domainPath); EamDb.getInstance().addArtifactInstance(attr); - } catch (EamDbException ex) { + } catch (EamDbException | CorrelationAttributeNormalizationException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex.getMessage()); } @@ -733,95 +784,117 @@ public class CentralRepoDatamodelTest extends TestCase { case1, dataSource1fromCase1, devIdPath); EamDb.getInstance().addArtifactInstance(attr); - } catch (EamDbException ex) { + } catch (EamDbException | CorrelationAttributeNormalizationException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex.getMessage()); } - // Test CorrelationAttributeInstance failure cases - // Create an attribute to use in the next few tests - CorrelationAttributeInstance failAttr; + // Test CorrelationAttributeInstance creation try { - failAttr = new CorrelationAttributeInstance(fileType, "badInstances"); - } catch (EamDbException ex) { + new CorrelationAttributeInstance(fileType, randomHash()); + } catch (CorrelationAttributeNormalizationException | EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex.getMessage()); - return; } // Test adding instance with null case try { - CorrelationAttributeInstance failAttrInst = new CorrelationAttributeInstance("badInstances", fileType, null, dataSource1fromCase2, "badPath"); + CorrelationAttributeInstance failAttrInst = new CorrelationAttributeInstance("badInstances", fileType, null, dataSource1fromCase2, BAD_PATH); EamDb.getInstance().addArtifactInstance(failAttrInst); - Assert.fail("addArtifact failed to throw exception for null case"); + fail("addArtifact failed to throw exception for null case"); } catch (EamDbException ex) { + fail("was expecting to get CorrelationAttributeNormalizationException"); + } catch (CorrelationAttributeNormalizationException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } // Test adding instance with invalid case ID try { CorrelationCase badCase = new CorrelationCase("badCaseUuid", "badCaseName"); - CorrelationAttributeInstance failAttrInst2 = new CorrelationAttributeInstance("badInstances", fileType, badCase, dataSource1fromCase2, "badPath"); + CorrelationAttributeInstance failAttrInst2 = new CorrelationAttributeInstance(randomHash(), fileType, badCase, dataSource1fromCase2, BAD_PATH); EamDb.getInstance().addArtifactInstance(failAttrInst2); - Assert.fail("addArtifact failed to throw exception for invalid case"); + fail("addArtifact failed to throw exception for invalid case"); } catch (EamDbException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); + } catch (CorrelationAttributeNormalizationException ex) { + fail("was expecting to get EamDbException"); } // Test adding instance with null data source try { - CorrelationAttributeInstance failAttrInst3 = new CorrelationAttributeInstance("badInstances", fileType, case1, null, "badPath"); + CorrelationAttributeInstance failAttrInst3 = new CorrelationAttributeInstance(randomHash(), fileType, case1, null, BAD_PATH); EamDb.getInstance().addArtifactInstance(failAttrInst3); - Assert.fail("addArtifact failed to throw exception for null data source"); + fail("addArtifact failed to throw exception for null data source"); } catch (EamDbException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); + } catch (CorrelationAttributeNormalizationException ex) { + fail("was expecting to get EamDbException"); } // Test adding instance with invalid data source ID try { CorrelationDataSource badDS = new CorrelationDataSource(case1, "badDSUuid", "badDSName"); - CorrelationAttributeInstance failAttrInst4 = new CorrelationAttributeInstance("badInstances", fileType, case1, badDS, "badPath"); + CorrelationAttributeInstance failAttrInst4 = new CorrelationAttributeInstance(randomHash(), fileType, case1, badDS, BAD_PATH); EamDb.getInstance().addArtifactInstance(failAttrInst4); - Assert.fail("addArtifact failed to throw exception for invalid data source"); + fail("addArtifact failed to throw exception for invalid data source"); } catch (EamDbException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); + } catch (CorrelationAttributeNormalizationException ex) { + fail("was expecting to get EamDbException"); } // Test adding instance with null path // This will fail in the CorrelationAttributeInstance constructor try { - new CorrelationAttributeInstance("badInstances", fileType, case1, dataSource1fromCase1, null); - Assert.fail("CorrelationAttributeInstance failed to throw exception for null path"); + new CorrelationAttributeInstance(randomHash(), fileType, case1, dataSource1fromCase1, null); + fail("CorrelationAttributeInstance failed to throw exception for null path"); } catch (EamDbException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); + } catch (CorrelationAttributeNormalizationException ex) { + fail("was expecting to get EamDbException"); } // Test adding instance with null known status try { CorrelationAttributeInstance failAttrInst5 = new CorrelationAttributeInstance("badInstances", fileType, case1, dataSource1fromCase1, null, "comment", null); EamDb.getInstance().addArtifactInstance(failAttrInst5); - Assert.fail("addArtifact failed to throw exception for null known status"); + fail("addArtifact failed to throw exception for null known status"); } catch (EamDbException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); + } catch (CorrelationAttributeNormalizationException ex) { + fail("was expecting to get EamDbException"); } // Test CorrelationAttribute failure cases // Test null type try { - CorrelationAttributeInstance attr = new CorrelationAttributeInstance(null, "badInstances"); + CorrelationAttributeInstance attr = new CorrelationAttributeInstance(null, randomHash()); EamDb.getInstance().addArtifactInstance(attr); - Assert.fail("addArtifact failed to throw exception for null type"); + fail("addArtifact failed to throw exception for null type"); } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + fail(ex.getMessage()); + } catch (CorrelationAttributeNormalizationException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } // Test null value // This will fail in the CorrelationAttribute constructor try { new CorrelationAttributeInstance(fileType, null); - Assert.fail("addArtifactInsance failed to throw exception for null value"); - } catch (EamDbException ex) { + fail("addArtifact failed to throw exception for null value"); + } catch (CorrelationAttributeNormalizationException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); + } catch (EamDbException ex) { + fail("expected to get CorrelationAttributeNormalizationException"); } // Test getting instances with expected results @@ -834,37 +907,45 @@ public class CentralRepoDatamodelTest extends TestCase { assertTrue("getArtifactInstancesByTypeValue returned instance with unexpected path " + inst.getFilePath(), inAllDataSourcesPath.equalsIgnoreCase(inst.getFilePath())); } - } catch (EamDbException ex) { + } catch (EamDbException | CorrelationAttributeNormalizationException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex.getMessage()); } - // Test getting instances expecting no results + // Test getting instances with mismatched data / data-type and expect an exception try { - List instances = EamDb.getInstance().getArtifactInstancesByTypeValue( - emailType, inAllDataSourcesHash); - assertTrue("getArtifactInstancesByTypeValue returned " + instances.size() + " results - expected 0", instances.isEmpty()); + EamDb.getInstance().getArtifactInstancesByTypeValue(emailType, inAllDataSourcesHash); + fail("we should get an exception"); } catch (EamDbException ex) { Exceptions.printStackTrace(ex); - Assert.fail(ex.getMessage()); + fail(ex.getMessage()); + } catch (CorrelationAttributeNormalizationException ex){ + //this is expected + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } // Test getting instances with null type try { EamDb.getInstance().getArtifactInstancesByTypeValue(null, inAllDataSourcesHash); - Assert.fail("getArtifactInstancesByTypeValue failed to throw exception for null type"); + fail("getArtifactInstancesByTypeValue failed to throw exception for null type"); } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + fail(ex.getMessage()); + } catch (CorrelationAttributeNormalizationException ex){ // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } // Test getting instances with null value - // Should just return nothing try { - List instances = EamDb.getInstance().getArtifactInstancesByTypeValue(fileType, null); - assertTrue("getArtifactInstancesByTypeValue returned non-empty list for null value", instances.isEmpty()); + EamDb.getInstance().getArtifactInstancesByTypeValue(fileType, null); + fail("this should produce an exception"); } catch (EamDbException ex) { Exceptions.printStackTrace(ex); - Assert.fail(ex.getMessage()); + fail(ex.getMessage()); + } catch(CorrelationAttributeNormalizationException ex){ + //this is expected + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } // Test getting instances with path that should produce results @@ -888,33 +969,35 @@ public class CentralRepoDatamodelTest extends TestCase { // Test getting instances with null type try { EamDb.getInstance().getArtifactInstancesByPath(null, inAllDataSourcesPath); - Assert.fail("getArtifactInstancesByPath failed to throw exception for null type"); + fail("getArtifactInstancesByPath failed to throw exception for null type"); } catch (EamDbException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } // Test getting instances with null path try { EamDb.getInstance().getArtifactInstancesByPath(fileType, null); - Assert.fail("getArtifactInstancesByPath failed to throw exception for null path"); + fail("getArtifactInstancesByPath failed to throw exception for null path"); } catch (EamDbException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } // Test getting instance count with path that should produce results try { long count = EamDb.getInstance().getCountArtifactInstancesByTypeValue(fileType, inAllDataSourcesHash); assertTrue("getCountArtifactInstancesByTypeValue returned " + count + " - expected 3", count == 3); - } catch (EamDbException ex) { + } catch (EamDbException | CorrelationAttributeNormalizationException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex.getMessage()); } // Test getting instance count with path that should not produce results try { - long count = EamDb.getInstance().getCountArtifactInstancesByTypeValue(fileType, "xyz"); + long count = EamDb.getInstance().getCountArtifactInstancesByTypeValue(fileType, randomHash()); assertTrue("getCountArtifactInstancesByTypeValue returned " + count + " - expected 0", count == 0); - } catch (EamDbException ex) { + } catch (EamDbException | CorrelationAttributeNormalizationException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex.getMessage()); } @@ -922,17 +1005,25 @@ public class CentralRepoDatamodelTest extends TestCase { // Test getting instance count with null type try { EamDb.getInstance().getCountArtifactInstancesByTypeValue(null, inAllDataSourcesHash); - Assert.fail("getCountArtifactInstancesByTypeValue failed to throw exception for null type"); + fail("getCountArtifactInstancesByTypeValue failed to throw exception for null type"); } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + fail(ex.getMessage()); + } catch(CorrelationAttributeNormalizationException ex){ // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } // Test getting instance count with null value try { EamDb.getInstance().getCountArtifactInstancesByTypeValue(fileType, null); - Assert.fail("getCountArtifactInstancesByTypeValue failed to throw exception for null value"); + fail("getCountArtifactInstancesByTypeValue failed to throw exception for null value"); } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + fail(ex.getMessage()); + } catch(CorrelationAttributeNormalizationException ex){ // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } // Test getting frequency of value that is in all three data sources @@ -940,7 +1031,7 @@ public class CentralRepoDatamodelTest extends TestCase { CorrelationAttributeInstance attr = new CorrelationAttributeInstance(fileType, inAllDataSourcesHash); int freq = EamDb.getInstance().getFrequencyPercentage(attr); assertTrue("getFrequencyPercentage returned " + freq + " - expected 100", freq == 100); - } catch (EamDbException ex) { + } catch (EamDbException | CorrelationAttributeNormalizationException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex.getMessage()); } @@ -950,7 +1041,7 @@ public class CentralRepoDatamodelTest extends TestCase { CorrelationAttributeInstance attr = new CorrelationAttributeInstance(fileType, inDataSource1twiceHash); int freq = EamDb.getInstance().getFrequencyPercentage(attr); assertTrue("getFrequencyPercentage returned " + freq + " - expected 33", freq == 33); - } catch (EamDbException ex) { + } catch (EamDbException | CorrelationAttributeNormalizationException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex.getMessage()); } @@ -960,17 +1051,17 @@ public class CentralRepoDatamodelTest extends TestCase { CorrelationAttributeInstance attr = new CorrelationAttributeInstance(emailType, emailValue); int freq = EamDb.getInstance().getFrequencyPercentage(attr); assertTrue("getFrequencyPercentage returned " + freq + " - expected 33", freq == 33); - } catch (EamDbException ex) { + } catch (EamDbException | CorrelationAttributeNormalizationException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex.getMessage()); } // Test getting frequency of non-existent value try { - CorrelationAttributeInstance attr = new CorrelationAttributeInstance(fileType, "randomValue"); + CorrelationAttributeInstance attr = new CorrelationAttributeInstance(fileType, randomHash()); int freq = EamDb.getInstance().getFrequencyPercentage(attr); assertTrue("getFrequencyPercentage returned " + freq + " - expected 0", freq == 0); - } catch (EamDbException ex) { + } catch (EamDbException | CorrelationAttributeNormalizationException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex.getMessage()); } @@ -979,17 +1070,22 @@ public class CentralRepoDatamodelTest extends TestCase { try { CorrelationAttributeInstance attr = new CorrelationAttributeInstance(null, "randomValue"); EamDb.getInstance().getFrequencyPercentage(attr); - Assert.fail("getFrequencyPercentage failed to throw exception for null type"); - } catch (EamDbException ex) { + fail("getFrequencyPercentage failed to throw exception for null type"); + } catch (EamDbException | CorrelationAttributeNormalizationException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } // Test getting frequency with null attribute try { EamDb.getInstance().getFrequencyPercentage(null); - Assert.fail("getFrequencyPercentage failed to throw exception for null attribute"); + fail("getFrequencyPercentage failed to throw exception for null attribute"); } catch (EamDbException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); + } catch (CorrelationAttributeNormalizationException ex) { + Exceptions.printStackTrace(ex); + fail(ex.getMessage()); } // Test updating a correlation attribute instance comment @@ -1006,7 +1102,7 @@ public class CentralRepoDatamodelTest extends TestCase { usbDeviceType, case1, dataSource1fromCase1, devIdValue, devIdPath); assertEquals("updateAttributeInstanceComment did not set comment to \"new comment\".", "new comment", correlationAttribute.getComment()); - } catch (EamDbException ex) { + } catch (EamDbException | CorrelationAttributeNormalizationException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex.getMessage()); } @@ -1042,7 +1138,7 @@ public class CentralRepoDatamodelTest extends TestCase { try { long count = EamDb.getInstance().getCountUniqueCaseDataSourceTuplesHavingTypeValue(fileType, inAllDataSourcesHash); assertTrue("getCountUniqueCaseDataSourceTuplesHavingTypeValue returned " + count + " - expected 3", count == 3); - } catch (EamDbException ex) { + } catch (EamDbException | CorrelationAttributeNormalizationException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex.getMessage()); } @@ -1051,35 +1147,42 @@ public class CentralRepoDatamodelTest extends TestCase { try { long count = EamDb.getInstance().getCountUniqueCaseDataSourceTuplesHavingTypeValue(fileType, inDataSource1twiceHash); assertTrue("getCountUniqueCaseDataSourceTuplesHavingTypeValue returned " + count + " - expected 1", count == 1); - } catch (EamDbException ex) { + } catch (EamDbException | CorrelationAttributeNormalizationException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex.getMessage()); } // Test getting data source count for entry that is not in any data sources try { - long count = EamDb.getInstance().getCountUniqueCaseDataSourceTuplesHavingTypeValue(fileType, "abcdef"); + long count = EamDb.getInstance().getCountUniqueCaseDataSourceTuplesHavingTypeValue(fileType, randomHash()); assertTrue("getCountUniqueCaseDataSourceTuplesHavingTypeValue returned " + count + " - expected 0", count == 0); - } catch (EamDbException ex) { + } catch (EamDbException | CorrelationAttributeNormalizationException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex.getMessage()); } // Test getting data source count for null type try { - EamDb.getInstance().getCountUniqueCaseDataSourceTuplesHavingTypeValue(null, "abcdef"); - Assert.fail("getCountUniqueCaseDataSourceTuplesHavingTypeValue failed to throw exception for null type"); + EamDb.getInstance().getCountUniqueCaseDataSourceTuplesHavingTypeValue(null, randomHash()); + fail("getCountUniqueCaseDataSourceTuplesHavingTypeValue failed to throw exception for null type"); } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + fail(ex.getMessage()); + } catch (CorrelationAttributeNormalizationException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } // Test getting data source count for null value try { - long count = EamDb.getInstance().getCountUniqueCaseDataSourceTuplesHavingTypeValue(fileType, null); - assertTrue("getCountUniqueCaseDataSourceTuplesHavingTypeValue returned " + count + " - expected 0", count == 0); + EamDb.getInstance().getCountUniqueCaseDataSourceTuplesHavingTypeValue(fileType, null); + fail("we should get an exception here"); } catch (EamDbException ex) { Exceptions.printStackTrace(ex); - Assert.fail(ex.getMessage()); + fail(ex.getMessage()); + } catch (CorrelationAttributeNormalizationException ex) { + //this is expected + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } // Test running processinstance which queries all rows from instances table @@ -1096,16 +1199,17 @@ public class CentralRepoDatamodelTest extends TestCase { int count2 = instancetableCallback.getCounterNamingConvention(); assertTrue("Process Instance count with filepath naming convention: " + count2 + "-expected 2", count2 == 2); assertTrue("Process Instance count with filepath without naming convention: " + count1 + "-expected greater than 0", count1 > 0); - } catch (EamDbException ex) { + } catch (EamDbException | CorrelationAttributeNormalizationException ex) { Exceptions.printStackTrace(ex); } try { //test null inputs EamDb.getInstance().processInstanceTable(null, null); - Assert.fail("processinstance method failed to throw exception for null type value"); + fail("processinstance method failed to throw exception for null type value"); } catch (EamDbException ex) { - // This is the expected + // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } // Test running processinstance which queries all rows from instances table @@ -1122,16 +1226,17 @@ public class CentralRepoDatamodelTest extends TestCase { int count2 = instancetableCallback.getCounterNamingConvention(); assertTrue("Process Instance count with filepath naming convention: " + count2 + "-expected 2", count2 == 2); assertTrue("Process Instance count with filepath without naming convention: " + count1 + "-expected greater than 0", count1 > 0); - } catch (EamDbException ex) { + } catch (EamDbException | CorrelationAttributeNormalizationException ex) { Exceptions.printStackTrace(ex); } try { //test null inputs EamDb.getInstance().processInstanceTableWhere(null, null, null); - Assert.fail("processinstance method failed to throw exception for null type value"); + fail("processinstance method failed to throw exception for null type value"); } catch (EamDbException ex) { - // This is the expected + // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } } @@ -1178,18 +1283,20 @@ public class CentralRepoDatamodelTest extends TestCase { try { CorrelationAttributeInstance.Type temp = new CorrelationAttributeInstance.Type(customTypeName, customTypeDb, false, false); EamDb.getInstance().newCorrelationType(temp); - Assert.fail("newCorrelationType failed to throw exception for duplicate name/db table"); + fail("newCorrelationType failed to throw exception for duplicate name/db table"); } catch (EamDbException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } // Test new type with null name try { CorrelationAttributeInstance.Type temp = new CorrelationAttributeInstance.Type(null, "temp_type", false, false); EamDb.getInstance().newCorrelationType(temp); - Assert.fail("newCorrelationType failed to throw exception for null name table"); + fail("newCorrelationType failed to throw exception for null name table"); } catch (EamDbException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } // Test new type with null db name @@ -1199,14 +1306,16 @@ public class CentralRepoDatamodelTest extends TestCase { Assert.fail("CorrelationAttributeInstance.Type failed to throw exception for null db table name"); } catch (EamDbException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } // Test new type with null type try { EamDb.getInstance().newCorrelationType(null); - Assert.fail("newCorrelationType failed to throw exception for null type"); + fail("newCorrelationType failed to throw exception for null type"); } catch (EamDbException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } // Test getting all correlation types @@ -1255,9 +1364,10 @@ public class CentralRepoDatamodelTest extends TestCase { // Test getting the type with a invalid ID try { EamDb.getInstance().getCorrelationTypeById(5555); - Assert.fail("getCorrelationTypeById failed to throw exception for invalid ID"); + fail("getCorrelationTypeById failed to throw exception for invalid ID"); } catch (EamDbException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } // Test updating a valid type @@ -1298,18 +1408,20 @@ public class CentralRepoDatamodelTest extends TestCase { try { customType.setDisplayName(null); EamDb.getInstance().updateCorrelationType(customType); - Assert.fail("updateCorrelationType failed to throw exception for null name"); + fail("updateCorrelationType failed to throw exception for null name"); } catch (EamDbException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } // Test updating a null type try { customType.setDisplayName(null); EamDb.getInstance().updateCorrelationType(customType); - Assert.fail("updateCorrelationType failed to throw exception for null type"); + fail("updateCorrelationType failed to throw exception for null type"); } catch (EamDbException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } } @@ -1373,26 +1485,29 @@ public class CentralRepoDatamodelTest extends TestCase { try { EamOrganization temp = new EamOrganization(orgAname); EamDb.getInstance().newOrganization(temp); - Assert.fail("newOrganization failed to throw exception for duplicate org name"); + fail("newOrganization failed to throw exception for duplicate org name"); } catch (EamDbException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } // Test adding null organization try { EamDb.getInstance().newOrganization(null); - Assert.fail("newOrganization failed to throw exception for null org"); + fail("newOrganization failed to throw exception for null org"); } catch (EamDbException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } // Test adding organization with null name try { EamOrganization temp = new EamOrganization(null); EamDb.getInstance().newOrganization(temp); - Assert.fail("newOrganization failed to throw exception for null name"); + fail("newOrganization failed to throw exception for null name"); } catch (EamDbException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } // Test getting organizations @@ -1422,9 +1537,10 @@ public class CentralRepoDatamodelTest extends TestCase { // Test getting org with invalid ID try { EamDb.getInstance().getOrganizationByID(12345); - Assert.fail("getOrganizationByID failed to throw exception for invalid ID"); + fail("getOrganizationByID failed to throw exception for invalid ID"); } catch (EamDbException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } // Test updating valid org @@ -1457,17 +1573,19 @@ public class CentralRepoDatamodelTest extends TestCase { try { EamOrganization temp = new EamOrganization("invalidOrg"); EamDb.getInstance().updateOrganization(temp); - Assert.fail("updateOrganization worked for invalid ID"); + fail("updateOrganization worked for invalid ID"); } catch (EamDbException ex) { // this is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } // Test updating null org try { EamDb.getInstance().updateOrganization(null); - Assert.fail("updateOrganization failed to throw exception for null org"); + fail("updateOrganization failed to throw exception for null org"); } catch (EamDbException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } // Test updating org to null name @@ -1475,9 +1593,10 @@ public class CentralRepoDatamodelTest extends TestCase { EamOrganization copyOfA = EamDb.getInstance().getOrganizationByID(orgA.getOrgID()); copyOfA.setName(null); EamDb.getInstance().updateOrganization(copyOfA); - Assert.fail("updateOrganization failed to throw exception for null name"); + fail("updateOrganization failed to throw exception for null name"); } catch (EamDbException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } // Test deleting existing org that isn't in use @@ -1505,26 +1624,29 @@ public class CentralRepoDatamodelTest extends TestCase { // It should now throw an exception if we try to delete it EamDb.getInstance().deleteOrganization(inUseOrg); - Assert.fail("deleteOrganization failed to throw exception for in use organization"); + fail("deleteOrganization failed to throw exception for in use organization"); } catch (EamDbException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } // Test deleting non-existent org try { EamOrganization temp = new EamOrganization("temp"); EamDb.getInstance().deleteOrganization(temp); - Assert.fail("deleteOrganization failed to throw exception for non-existent organization"); + fail("deleteOrganization failed to throw exception for non-existent organization"); } catch (EamDbException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } // Test deleting null org try { EamDb.getInstance().deleteOrganization(null); - Assert.fail("deleteOrganization failed to throw exception for null organization"); + fail("deleteOrganization failed to throw exception for null organization"); } catch (EamDbException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } } @@ -1626,7 +1748,7 @@ public class CentralRepoDatamodelTest extends TestCase { temp = new EamGlobalFileInstance(knownSet1id, knownHash1, TskData.FileKnown.KNOWN, "comment5"); EamDb.getInstance().addReferenceInstance(temp, fileType); - } catch (EamDbException ex) { + } catch (EamDbException | CorrelationAttributeNormalizationException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex.getMessage()); } @@ -1635,9 +1757,13 @@ public class CentralRepoDatamodelTest extends TestCase { try { EamGlobalFileInstance temp = new EamGlobalFileInstance(2345, inAllSetsHash, TskData.FileKnown.BAD, "comment"); EamDb.getInstance().addReferenceInstance(temp, fileType); - Assert.fail("addReferenceInstance failed to throw exception for invalid ID"); + fail("addReferenceInstance failed to throw exception for invalid ID"); } catch (EamDbException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); + } catch (CorrelationAttributeNormalizationException ex) { + Exceptions.printStackTrace(ex); + fail(ex.getMessage()); } // Test creating file instance with null hash @@ -1645,9 +1771,13 @@ public class CentralRepoDatamodelTest extends TestCase { // call addReferenceInstance and just test the EamGlobalFileInstance constructor try { new EamGlobalFileInstance(notableSet1id, null, TskData.FileKnown.BAD, "comment"); - Assert.fail("EamGlobalFileInstance failed to throw exception for null hash"); + fail("EamGlobalFileInstance failed to throw exception for null hash"); } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + fail(ex.getMessage()); + } catch (CorrelationAttributeNormalizationException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } // Test adding file instance with null known status @@ -1655,27 +1785,34 @@ public class CentralRepoDatamodelTest extends TestCase { // call addReferenceInstance and just test the EamGlobalFileInstance constructor try { new EamGlobalFileInstance(notableSet1id, inAllSetsHash, null, "comment"); - Assert.fail("EamGlobalFileInstance failed to throw exception for null type"); + fail("EamGlobalFileInstance failed to throw exception for null type"); } catch (EamDbException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); + } catch (CorrelationAttributeNormalizationException ex) { + Exceptions.printStackTrace(ex); + fail(ex.getMessage()); } // Test adding file instance with null correlation type try { EamGlobalFileInstance temp = new EamGlobalFileInstance(notableSet1id, inAllSetsHash, TskData.FileKnown.BAD, "comment"); EamDb.getInstance().addReferenceInstance(temp, null); - Assert.fail("addReferenceInstance failed to throw exception for null type"); + fail("addReferenceInstance failed to throw exception for null type"); } catch (EamDbException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); + } catch (CorrelationAttributeNormalizationException ex) { + Exceptions.printStackTrace(ex); + fail(ex.getMessage()); } // Test bulk insert with large valid set try { // Create a list of global file instances. Make enough that the bulk threshold should be hit once. Set instances = new HashSet<>(); - String bulkTestHash = "bulktesthash_"; for (int i = 0; i < DEFAULT_BULK_THRESHOLD * 1.5; i++) { - String hash = bulkTestHash + String.valueOf(i); + String hash = randomHash(); instances.add(new EamGlobalFileInstance(notableSet2id, hash, TskData.FileKnown.BAD, null)); } @@ -1684,10 +1821,10 @@ public class CentralRepoDatamodelTest extends TestCase { // There's no way to get a count of the number of entries in the database, so just do a spot check if (DEFAULT_BULK_THRESHOLD > 10) { - String hash = bulkTestHash + "10"; + String hash = instances.stream().findFirst().get().getMD5Hash(); assertTrue("Sample bulk insert instance not found", EamDb.getInstance().isFileHashInReferenceSet(hash, notableSet2id)); } - } catch (EamDbException ex) { + } catch (EamDbException | CorrelationAttributeNormalizationException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex.getMessage()); } @@ -1695,43 +1832,51 @@ public class CentralRepoDatamodelTest extends TestCase { // Test bulk add file instance with null list try { EamDb.getInstance().bulkInsertReferenceTypeEntries(null, fileType); - Assert.fail("bulkInsertReferenceTypeEntries failed to throw exception for null list"); + fail("bulkInsertReferenceTypeEntries failed to throw exception for null list"); } catch (EamDbException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } // Test bulk add file instance with invalid reference set ID try { Set tempSet = new HashSet<>(Arrays.asList(new EamGlobalFileInstance(2345, inAllSetsHash, TskData.FileKnown.BAD, "comment"))); EamDb.getInstance().bulkInsertReferenceTypeEntries(tempSet, fileType); - Assert.fail("bulkInsertReferenceTypeEntries failed to throw exception for invalid ID"); + fail("bulkInsertReferenceTypeEntries failed to throw exception for invalid ID"); } catch (EamDbException ex) { // This is the expected behavior + } catch (CorrelationAttributeNormalizationException ex) { + Exceptions.printStackTrace(ex); + fail(ex.getMessage()); } // Test bulk add file instance with null correlation type try { Set tempSet = new HashSet<>(Arrays.asList(new EamGlobalFileInstance(notableSet1id, inAllSetsHash, TskData.FileKnown.BAD, "comment"))); EamDb.getInstance().bulkInsertReferenceTypeEntries(tempSet, null); - Assert.fail("bulkInsertReferenceTypeEntries failed to throw exception for null type"); + fail("bulkInsertReferenceTypeEntries failed to throw exception for null type"); } catch (EamDbException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); + } catch (CorrelationAttributeNormalizationException ex) { + Exceptions.printStackTrace(ex); + fail(ex.getMessage()); } // Test getting reference instances with valid data try { List temp = EamDb.getInstance().getReferenceInstancesByTypeValue(fileType, inAllSetsHash); assertTrue("getReferenceInstancesByTypeValue returned " + temp.size() + " instances - expected 3", temp.size() == 3); - } catch (EamDbException ex) { + } catch (EamDbException | CorrelationAttributeNormalizationException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex.getMessage()); } // Test getting reference instances with non-existent data try { - List temp = EamDb.getInstance().getReferenceInstancesByTypeValue(fileType, "testHash"); + List temp = EamDb.getInstance().getReferenceInstancesByTypeValue(fileType, randomHash()); assertTrue("getReferenceInstancesByTypeValue returned " + temp.size() + " instances for non-existent value - expected 0", temp.isEmpty()); - } catch (EamDbException ex) { + } catch (EamDbException | CorrelationAttributeNormalizationException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex.getMessage()); } @@ -1739,32 +1884,40 @@ public class CentralRepoDatamodelTest extends TestCase { // Test getting reference instances an invalid type (the email table is not yet implemented) try { EamDb.getInstance().getReferenceInstancesByTypeValue(emailType, inAllSetsHash); - Assert.fail("getReferenceInstancesByTypeValue failed to throw exception for invalid table"); - } catch (EamDbException ex) { + fail("getReferenceInstancesByTypeValue failed to throw exception for invalid table"); + } catch (EamDbException | CorrelationAttributeNormalizationException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } // Test getting reference instances with null type try { EamDb.getInstance().getReferenceInstancesByTypeValue(null, inAllSetsHash); - Assert.fail("getReferenceInstancesByTypeValue failed to throw exception for null type"); + fail("getReferenceInstancesByTypeValue failed to throw exception for null type"); } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + fail(ex.getMessage()); + } catch (CorrelationAttributeNormalizationException ex){ // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } // Test getting reference instances with null value try { List temp = EamDb.getInstance().getReferenceInstancesByTypeValue(fileType, null); - assertTrue("getReferenceInstancesByTypeValue returned non-empty list given null value", temp.isEmpty()); + fail("we should get an exception here"); } catch (EamDbException ex) { Exceptions.printStackTrace(ex); - Assert.fail(ex.getMessage()); + fail(ex.getMessage()); + } catch(CorrelationAttributeNormalizationException ex){ + //this is expected + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } // Test checking existing hash/ID try { assertTrue("isFileHashInReferenceSet returned false for valid data", EamDb.getInstance().isFileHashInReferenceSet(knownHash1, knownSet1id)); - } catch (EamDbException ex) { + } catch (EamDbException | CorrelationAttributeNormalizationException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex.getMessage()); } @@ -1772,7 +1925,7 @@ public class CentralRepoDatamodelTest extends TestCase { // Test checking non-existent (but valid) hash/ID try { assertFalse("isFileHashInReferenceSet returned true for non-existent data", EamDb.getInstance().isFileHashInReferenceSet(knownHash1, notableSet1id)); - } catch (EamDbException ex) { + } catch (EamDbException | CorrelationAttributeNormalizationException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex.getMessage()); } @@ -1780,24 +1933,28 @@ public class CentralRepoDatamodelTest extends TestCase { // Test checking invalid reference set ID try { assertFalse("isFileHashInReferenceSet returned true for invalid data", EamDb.getInstance().isFileHashInReferenceSet(knownHash1, 5678)); - } catch (EamDbException ex) { + } catch (EamDbException | CorrelationAttributeNormalizationException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex.getMessage()); } // Test checking null hash try { - assertFalse("isFileHashInReferenceSet returned true for null hash", EamDb.getInstance().isFileHashInReferenceSet(null, knownSet1id)); + EamDb.getInstance().isFileHashInReferenceSet(null, knownSet1id); + fail("This should throw an exception"); } catch (EamDbException ex) { Exceptions.printStackTrace(ex); - Assert.fail(ex.getMessage()); + fail(ex.getMessage()); + } catch(CorrelationAttributeNormalizationException ex){ + //this is expected + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } // Test checking existing hash/ID try { assertTrue("isValueInReferenceSet returned false for valid data", EamDb.getInstance().isValueInReferenceSet(knownHash1, knownSet1id, fileType.getId())); - } catch (EamDbException ex) { + } catch (EamDbException | CorrelationAttributeNormalizationException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex.getMessage()); } @@ -1806,7 +1963,7 @@ public class CentralRepoDatamodelTest extends TestCase { try { assertFalse("isValueInReferenceSet returned true for non-existent data", EamDb.getInstance().isValueInReferenceSet(knownHash1, notableSet1id, fileType.getId())); - } catch (EamDbException ex) { + } catch (EamDbException | CorrelationAttributeNormalizationException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex.getMessage()); } @@ -1815,33 +1972,40 @@ public class CentralRepoDatamodelTest extends TestCase { try { assertFalse("isValueInReferenceSet returned true for invalid data", EamDb.getInstance().isValueInReferenceSet(knownHash1, 5678, fileType.getId())); - } catch (EamDbException ex) { + } catch (EamDbException | CorrelationAttributeNormalizationException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex.getMessage()); } // Test checking null hash try { - assertFalse("isValueInReferenceSet returned true for null value", - EamDb.getInstance().isValueInReferenceSet(null, knownSet1id, fileType.getId())); + EamDb.getInstance().isValueInReferenceSet(null, knownSet1id, fileType.getId()); + fail("we should get an exception here"); } catch (EamDbException ex) { Exceptions.printStackTrace(ex); - Assert.fail(ex.getMessage()); + fail(ex.getMessage()); + } catch (CorrelationAttributeNormalizationException ex){ + //this is expected + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } // Test checking invalid type try { EamDb.getInstance().isValueInReferenceSet(knownHash1, knownSet1id, emailType.getId()); - Assert.fail("isValueInReferenceSet failed to throw exception for invalid type"); + fail("isValueInReferenceSet failed to throw exception for invalid type"); } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + fail(ex.getMessage()); + } catch (CorrelationAttributeNormalizationException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } // Test known bad with notable data try { assertTrue("isArtifactKnownBadByReference returned false for notable value", EamDb.getInstance().isArtifactKnownBadByReference(fileType, notableHash1)); - } catch (EamDbException ex) { + } catch (EamDbException | CorrelationAttributeNormalizationException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex.getMessage()); } @@ -1850,7 +2014,7 @@ public class CentralRepoDatamodelTest extends TestCase { try { assertFalse("isArtifactKnownBadByReference returned true for known value", EamDb.getInstance().isArtifactKnownBadByReference(fileType, knownHash1)); - } catch (EamDbException ex) { + } catch (EamDbException | CorrelationAttributeNormalizationException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex.getMessage()); } @@ -1858,35 +2022,46 @@ public class CentralRepoDatamodelTest extends TestCase { // Test known bad with non-existent data try { assertFalse("isArtifactKnownBadByReference returned true for non-existent value", - EamDb.getInstance().isArtifactKnownBadByReference(fileType, "abcdef")); - } catch (EamDbException ex) { + EamDb.getInstance().isArtifactKnownBadByReference(fileType, randomHash())); + } catch (EamDbException | CorrelationAttributeNormalizationException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex.getMessage()); } // Test known bad with null hash try { - assertFalse("isArtifactKnownBadByReference returned true for null value", - EamDb.getInstance().isArtifactKnownBadByReference(fileType, null)); + EamDb.getInstance().isArtifactKnownBadByReference(fileType, null); + fail("we should have thrown an exception"); } catch (EamDbException ex) { Exceptions.printStackTrace(ex); - Assert.fail(ex.getMessage()); + fail(ex.getMessage()); + } catch (CorrelationAttributeNormalizationException ex) { + //this is expected + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } // Test known bad with null type try { EamDb.getInstance().isArtifactKnownBadByReference(null, knownHash1); - Assert.fail("isArtifactKnownBadByReference failed to throw exception from null type"); + fail("isArtifactKnownBadByReference failed to throw exception from null type"); } catch (EamDbException ex) { + Exceptions.printStackTrace(ex); + fail(ex.getMessage()); + } catch (CorrelationAttributeNormalizationException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } // Test known bad with invalid type try { - assertFalse("isArtifactKnownBadByReference returned true for invalid type", EamDb.getInstance().isArtifactKnownBadByReference(emailType, null)); + EamDb.getInstance().isArtifactKnownBadByReference(emailType, null); + fail("should get an exception here"); } catch (EamDbException ex) { Exceptions.printStackTrace(ex); - Assert.fail(ex.getMessage()); + fail(ex.getMessage()); + } catch (CorrelationAttributeNormalizationException ex) { + //this is expected + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } } @@ -1960,9 +2135,10 @@ public class CentralRepoDatamodelTest extends TestCase { try { EamGlobalSet temp = new EamGlobalSet(org1.getOrgID(), set1name, "1.0", TskData.FileKnown.BAD, false, fileType); EamDb.getInstance().newReferenceSet(temp); - Assert.fail("newReferenceSet failed to throw exception from duplicate name/version pair"); + fail("newReferenceSet failed to throw exception from duplicate name/version pair"); } catch (EamDbException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } // Test creating a reference set with the same name but different version @@ -1979,43 +2155,47 @@ public class CentralRepoDatamodelTest extends TestCase { try { EamGlobalSet temp = new EamGlobalSet(5000, "tempName", "", TskData.FileKnown.BAD, false, fileType); EamDb.getInstance().newReferenceSet(temp); - Assert.fail("newReferenceSet failed to throw exception from invalid org ID"); + fail("newReferenceSet failed to throw exception from invalid org ID"); } catch (EamDbException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } // Test creating a reference set with null name try { EamGlobalSet temp = new EamGlobalSet(org2.getOrgID(), null, "", TskData.FileKnown.BAD, false, fileType); EamDb.getInstance().newReferenceSet(temp); - Assert.fail("newReferenceSet failed to throw exception from null name"); + fail("newReferenceSet failed to throw exception from null name"); } catch (EamDbException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } // Test creating a reference set with null version try { EamGlobalSet temp = new EamGlobalSet(org2.getOrgID(), "tempName", null, TskData.FileKnown.BAD, false, fileType); EamDb.getInstance().newReferenceSet(temp); - Assert.fail("newReferenceSet failed to throw exception from null version"); + fail("newReferenceSet failed to throw exception from null version"); } catch (EamDbException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } // Test creating a reference set with null file known status try { EamGlobalSet temp = new EamGlobalSet(org2.getOrgID(), "tempName", "", null, false, fileType); EamDb.getInstance().newReferenceSet(temp); - Assert.fail("newReferenceSet failed to throw exception from null file known status"); + fail("newReferenceSet failed to throw exception from null file known status"); } catch (EamDbException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } // Test creating a reference set with null file type try { EamGlobalSet temp = new EamGlobalSet(org2.getOrgID(), "tempName", "", TskData.FileKnown.BAD, false, null); EamDb.getInstance().newReferenceSet(temp); - Assert.fail("newReferenceSet failed to throw exception from null file type"); + fail("newReferenceSet failed to throw exception from null file type"); } catch (EamDbException ex) { // This is the expected behavior } @@ -2125,9 +2305,10 @@ public class CentralRepoDatamodelTest extends TestCase { // Test null argument to getAllReferenceSets try { EamDb.getInstance().getAllReferenceSets(null); - Assert.fail("getAllReferenceSets failed to throw exception from null type argument"); + fail("getAllReferenceSets failed to throw exception from null type argument"); } catch (EamDbException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } // Test deleting an existing reference set @@ -2172,9 +2353,10 @@ public class CentralRepoDatamodelTest extends TestCase { // Test getting reference set organization for non-existent reference set try { EamDb.getInstance().getReferenceSetOrganization(4567); - Assert.fail("getReferenceSetOrganization failed to throw exception for invalid reference set ID"); + fail("getReferenceSetOrganization failed to throw exception for invalid reference set ID"); } catch (EamDbException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } } @@ -2217,7 +2399,7 @@ public class CentralRepoDatamodelTest extends TestCase { try { CorrelationDataSource temp = new CorrelationDataSource(case2, dataSourceAid, dataSourceAname); EamDb.getInstance().newDataSource(temp); - Assert.fail("newDataSource did not throw exception from duplicate data source"); + fail("newDataSource did not throw exception from duplicate data source"); } catch (EamDbException ex) { // This is the expected behavior } @@ -2237,27 +2419,30 @@ public class CentralRepoDatamodelTest extends TestCase { CorrelationCase correlationCase = new CorrelationCase("1", "test"); CorrelationDataSource temp = new CorrelationDataSource(correlationCase, "tempID", "tempName"); EamDb.getInstance().newDataSource(temp); - Assert.fail("newDataSource did not throw exception from invalid case ID"); + fail("newDataSource did not throw exception from invalid case ID"); } catch (EamDbException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } // Test creating a data source with null device ID try { CorrelationDataSource temp = new CorrelationDataSource(case2, null, "tempName"); EamDb.getInstance().newDataSource(temp); - Assert.fail("newDataSource did not throw exception from null device ID"); + fail("newDataSource did not throw exception from null device ID"); } catch (EamDbException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } // Test creating a data source with null name try { CorrelationDataSource temp = new CorrelationDataSource(case2, "tempID", null); EamDb.getInstance().newDataSource(temp); - Assert.fail("newDataSource did not throw exception from null name"); + fail("newDataSource did not throw exception from null name"); } catch (EamDbException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } // Test getting a data source with valid case and ID @@ -2281,9 +2466,10 @@ public class CentralRepoDatamodelTest extends TestCase { // Test getting a data source with a null case try { EamDb.getInstance().getDataSource(null, dataSourceAid); - Assert.fail("getDataSource did not throw exception from null case"); + fail("getDataSource did not throw exception from null case"); } catch (EamDbException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } // Test getting a data source with null ID @@ -2378,18 +2564,20 @@ public class CentralRepoDatamodelTest extends TestCase { try { CorrelationCase tempCase = new CorrelationCase(null, "nullUuidCase"); EamDb.getInstance().newCase(tempCase); - Assert.fail("newCase did not throw expected exception from null uuid"); + fail("newCase did not throw expected exception from null uuid"); } catch (EamDbException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } // Test null name try { CorrelationCase tempCase = new CorrelationCase("nullCaseUuid", null); EamDb.getInstance().newCase(tempCase); - Assert.fail("newCase did not throw expected exception from null name"); + fail("newCase did not throw expected exception from null name"); } catch (EamDbException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } // Test creating a case with an already used UUID @@ -2421,9 +2609,10 @@ public class CentralRepoDatamodelTest extends TestCase { try { Case nullCase = null; EamDb.getInstance().newCase(nullCase); - Assert.fail("newCase did not throw expected exception from null case"); + fail("newCase did not throw expected exception from null case"); } catch (EamDbException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } // Test update case @@ -2471,9 +2660,10 @@ public class CentralRepoDatamodelTest extends TestCase { // Test update case with null case try { EamDb.getInstance().updateCase(null); - Assert.fail("updateCase did not throw expected exception from null case"); + fail("updateCase did not throw expected exception from null case"); } catch (EamDbException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } // Test getting a case from an Autopsy case @@ -2554,9 +2744,10 @@ public class CentralRepoDatamodelTest extends TestCase { // Test bulk case insert with null list try { EamDb.getInstance().bulkInsertCases(null); - Assert.fail("bulkInsertCases did not throw expected exception from null list"); + fail("bulkInsertCases did not throw expected exception from null list"); } catch (EamDbException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } } finally { try { @@ -2608,7 +2799,7 @@ public class CentralRepoDatamodelTest extends TestCase { // Test null name try { EamDb.getInstance().newDbInfo(null, value1); - Assert.fail("newDbInfo did not throw expected exception from null name"); + fail("newDbInfo did not throw expected exception from null name"); } catch (EamDbException ex) { // This is the expected behavior } @@ -2616,9 +2807,10 @@ public class CentralRepoDatamodelTest extends TestCase { // Test null value try { EamDb.getInstance().newDbInfo(name2, null); - Assert.fail("newDbInfo did not throw expected exception from null value"); + fail("newDbInfo did not throw expected exception from null value"); } catch (EamDbException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } // Try getting the dbInfo entry that should exist @@ -2660,9 +2852,10 @@ public class CentralRepoDatamodelTest extends TestCase { // Try updating an existing value to null try { EamDb.getInstance().updateDbInfo(name1, null); - Assert.fail("updateDbInfo did not throw expected exception from null value"); + fail("updateDbInfo did not throw expected exception from null value"); } catch (EamDbException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } // Try updating a null name @@ -2677,11 +2870,33 @@ public class CentralRepoDatamodelTest extends TestCase { // Try updating the value for a non-existant name try { EamDb.getInstance().updateDbInfo(name1, null); - Assert.fail("updateDbInfo did not throw expected exception from non-existent name"); + fail("updateDbInfo did not throw expected exception from non-existent name"); } catch (EamDbException ex) { // This is the expected behavior + assertTrue(THIS_IS_THE_EXPECTED_BEHAVIOR, true); } } + private static final String THIS_IS_THE_EXPECTED_BEHAVIOR = "This is the expected behavior."; + + private static String randomHash() { + + String[] chars = {"a", "b", "c", "d", "e", "f", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"}; + + Random random = new Random(); + IntStream ints = random.ints(32, 0, chars.length - 1); + + Iterator it = ints.iterator(); + + StringBuilder md5 = new StringBuilder(32); + + while(it.hasNext()){ + Integer i = it.next(); + String character = chars[i]; + md5.append(character); + } + + return md5.toString(); + } public class AttributeInstanceTableCallback implements InstanceTableCallback { @@ -2710,7 +2925,5 @@ public class CentralRepoDatamodelTest extends TestCase { public int getCounterNamingConvention(){ return counterNamingConvention; } - } - -} +} \ No newline at end of file diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeNormalizerTest.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeNormalizerTest.java new file mode 100644 index 0000000000..76d28e7ea6 --- /dev/null +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeNormalizerTest.java @@ -0,0 +1,315 @@ +/* + * + * Autopsy Forensic Browser + * + * Copyright 2018 Basis Technology Corp. + * Contact: carrier sleuthkit 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."; +} diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/CommonAttributeSearchInterCaseTests.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/CommonAttributeSearchInterCaseTests.java index dd72c6501d..966d0b8bce 100644 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/CommonAttributeSearchInterCaseTests.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonfilessearch/CommonAttributeSearchInterCaseTests.java @@ -1,16 +1,16 @@ /* - * + * * Autopsy Forensic Browser - * + * * Copyright 2018 Basis Technology Corp. * Contact: carrier sleuthkit 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. @@ -43,12 +43,15 @@ 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); } @@ -100,10 +103,10 @@ public class CommonAttributeSearchInterCaseTests extends NbTestCase { /** * Run a search on the given type and ensure that all results are off that * type. - * + * * No frequency filtering applied. - * - * @param type + * + * @param type */ private void assertResultsAreOfType(CorrelationAttributeInstance.Type type) { @@ -115,7 +118,7 @@ public class CommonAttributeSearchInterCaseTests extends NbTestCase { CommonAttributeSearchResults metadata = builder.findMatches(); metadata.size(); - + assertFalse(verifyInstanceCount(metadata, 0)); assertTrue(this.utils.areAllResultsOfType(metadata, type)); @@ -136,33 +139,33 @@ public class CommonAttributeSearchInterCaseTests extends NbTestCase { // assertResultsAreOfType(this.utils.EMAIL_TYPE); // assertResultsAreOfType(this.utils.PHONE_TYPE); } - + /** * Test that the frequency filter behaves reasonably for attributes other * than the file type. */ - public void testTwo(){ + public void testTwo() { try { Map dataSources = this.utils.getDataSourceMap(); - + AbstractCommonAttributeSearcher builder; CommonAttributeSearchResults metadata; - + builder = new AllInterCaseCommonAttributeSearcher(dataSources, false, false, this.utils.USB_ID_TYPE, 100); metadata = builder.findMatches(); metadata.size(); //assertTrue("This should yield 13 results.", verifyInstanceCount(metadata, 13)); - + builder = new AllInterCaseCommonAttributeSearcher(dataSources, false, false, this.utils.USB_ID_TYPE, 20); metadata = builder.findMatches(); metadata.size(); //assertTrue("This should yield no results.", verifyInstanceCount(metadata, 0)); - + builder = new AllInterCaseCommonAttributeSearcher(dataSources, false, false, this.utils.USB_ID_TYPE, 90); metadata = builder.findMatches(); metadata.size(); //assertTrue("This should yield 2 results.", verifyInstanceCount(metadata, 2)); - + } catch (TskCoreException | NoCurrentCaseException | SQLException | EamDbException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex.getMessage());