Merge pull request #3961 from APriestman/4006_adHocKWinReport

4006 Show ad hoc keyword hits in report.
This commit is contained in:
Richard Cordovano
2018-07-13 18:18:40 -04:00
committed by GitHub
@@ -44,6 +44,7 @@ import org.sleuthkit.autopsy.casemodule.services.TagsManager;
import org.sleuthkit.autopsy.coreutils.ImageUtils;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.datamodel.ContentUtils;
import static org.sleuthkit.autopsy.casemodule.services.TagsManager.getNotableTagLabel;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.Account;
import org.sleuthkit.datamodel.BlackboardArtifact;
@@ -53,6 +54,7 @@ import org.sleuthkit.datamodel.BlackboardAttribute.Type;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.ContentTag;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TagName;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskData;
@@ -538,6 +540,65 @@ class TableReportGenerator {
logger.log(Level.SEVERE, "Exception while getting open case: ", ex); //NON-NLS
return;
}
// Get a list of all selected tag IDs
String tagIDList = "";
if( ! tagNamesFilter.isEmpty()) {
try {
Map<String, TagName> tagNamesMap = Case.getCurrentCaseThrows().getServices().getTagsManager().getDisplayNamesToTagNamesMap();
for(String tagDisplayName : tagNamesFilter) {
if(tagNamesMap.containsKey(tagDisplayName)) {
if (! tagIDList.isEmpty()) {
tagIDList += ",";
}
tagIDList += tagNamesMap.get(tagDisplayName).getId();
} else {
// If the tag name ends with "(Notable)", try stripping that off
if(tagDisplayName.endsWith(getNotableTagLabel())) {
String editedDisplayName = tagDisplayName.substring(0, tagDisplayName.length() - getNotableTagLabel().length());
if(tagNamesMap.containsKey(editedDisplayName)) {
if (! tagIDList.isEmpty()) {
tagIDList += ",";
}
tagIDList += tagNamesMap.get(editedDisplayName).getId();
}
}
}
}
} catch (NoCurrentCaseException | TskCoreException ex) {
logger.log(Level.SEVERE, "Exception while getting tag info - proceeding without tag filter: ", ex); //NON-NLS
tagIDList = "";
}
}
// Check if there are any ad-hoc results
String adHocCountQuery = "SELECT COUNT(*) FROM " + //NON-NLS
"(SELECT art.artifact_id FROM blackboard_artifacts AS art, blackboard_attributes AS att1 ";//NON-NLS
if (!tagIDList.isEmpty()) {
adHocCountQuery += ", blackboard_artifact_tags as tag "; //NON-NLS
}
adHocCountQuery += "WHERE (att1.artifact_id = art.artifact_id) AND (art.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID() + ") "; // NON-NLS
if (!tagIDList.isEmpty()) {
adHocCountQuery += " AND (art.artifact_id = tag.artifact_id) AND (tag.tag_name_id IN (" + tagIDList + ")) "; //NON-NLS
}
adHocCountQuery += "EXCEPT " + // NON-NLS
"SELECT art.artifact_id FROM blackboard_artifacts AS art, blackboard_attributes AS att1 WHERE (att1.artifact_id = art.artifact_id) AND (art.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID() + ") AND (att1.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID() + ")) "; //NON-NLS
int adHocCount = 0;
try (SleuthkitCase.CaseDbQuery dbQuery = openCase.getSleuthkitCase().executeQuery(adHocCountQuery)) {
ResultSet adHocCountResultSet = dbQuery.getResultSet();
if (adHocCountResultSet.next()) {
adHocCount = adHocCountResultSet.getInt(1); //NON-NLS
} else {
throw new TskCoreException("Error counting ad hoc keywords");
}
} catch (TskCoreException | SQLException ex) {
errorList.add(NbBundle.getMessage(this.getClass(), "ReportGenerator.errList.failedQueryKWLists"));
logger.log(Level.SEVERE, "Failed to count ad hoc searches with query " + adHocCountQuery, ex); //NON-NLS
return;
}
// Create the query to get the keyword list names
if (openCase.getCaseType() == Case.CaseType.MULTI_USER_CASE) {
orderByClause = "ORDER BY convert_to(att.value_text, 'SQL_ASCII') ASC NULLS FIRST"; //NON-NLS
} else {
@@ -546,16 +607,25 @@ class TableReportGenerator {
String keywordListQuery
= "SELECT att.value_text AS list "
+ //NON-NLS
"FROM blackboard_attributes AS att, blackboard_artifacts AS art "
+ //NON-NLS
"WHERE att.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID() + " "
"FROM blackboard_attributes AS att, blackboard_artifacts AS art "; // NON-NLS
if(! tagIDList.isEmpty()) {
keywordListQuery += ", blackboard_artifact_tags as tag "; //NON-NLS
}
keywordListQuery += "WHERE att.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID() + " "
+ //NON-NLS
"AND art.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID() + " "
+ //NON-NLS
"AND att.artifact_id = art.artifact_id "
+ //NON-NLS
"GROUP BY list " + orderByClause; //NON-NLS
"AND att.artifact_id = art.artifact_id ";
if (! tagIDList.isEmpty()) {
keywordListQuery += "AND (art.artifact_id = tag.artifact_id) " + //NON-NLS
"AND (tag.tag_name_id IN (" + tagIDList + ")) "; //NON-NLS
}
if (adHocCount > 0) {
keywordListQuery += " UNION SELECT \"\" AS list ";
}
keywordListQuery += "GROUP BY list " + orderByClause; //NON-NLS
// Make the table of contents links for each list type
try (SleuthkitCase.CaseDbQuery dbQuery = openCase.getSleuthkitCase().executeQuery(keywordListQuery)) {
ResultSet listsRs = dbQuery.getResultSet();
List<String> lists = new ArrayList<>();
@@ -579,6 +649,7 @@ class TableReportGenerator {
return;
}
// Query for keywords, grouped by list
if (openCase.getCaseType() == Case.CaseType.MULTI_USER_CASE) {
orderByClause = "ORDER BY convert_to(att3.value_text, 'SQL_ASCII') ASC NULLS FIRST, " //NON-NLS
+ "convert_to(att1.value_text, 'SQL_ASCII') ASC NULLS FIRST, " //NON-NLS
@@ -588,9 +659,10 @@ class TableReportGenerator {
} else {
orderByClause = "ORDER BY list ASC, keyword ASC, parent_path ASC, name ASC, preview ASC"; //NON-NLS
}
// Query for keywords, grouped by list
String keywordsQuery
= "SELECT art.artifact_id, art.obj_id, att1.value_text AS keyword, att2.value_text AS preview, att3.value_text AS list, f.name AS name, f.parent_path AS parent_path "
// Query for keywords that are part of a list
String keywordListsQuery
= "SELECT art.artifact_id AS artifact_id, art.obj_id AS obj_id, att1.value_text AS keyword, att2.value_text AS preview, att3.value_text AS list, f.name AS name, f.parent_path AS parent_path "
+ //NON-NLS
"FROM blackboard_artifacts AS art, blackboard_attributes AS att1, blackboard_attributes AS att2, blackboard_attributes AS att3, tsk_files AS f "
+ //NON-NLS
@@ -608,9 +680,24 @@ class TableReportGenerator {
+ //NON-NLS
"AND (att3.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID() + ") "
+ //NON-NLS
"AND (art.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID() + ") "
+ //NON-NLS
orderByClause; //NON-NLS
"AND (art.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID() + ") ";
// Query for keywords that are not part of a list
String keywordAdHocQuery =
"SELECT art.artifact_id AS artifact_id, art.obj_id AS obj_id, att1.value_text AS keyword, att2.value_text AS preview, \"\" AS list, f.name AS name, f.parent_path AS parent_path " + // NON-NLS
"FROM blackboard_artifacts AS art, blackboard_attributes AS att1, blackboard_attributes AS att2, tsk_files AS f " + // NON-NLS
"WHERE " + // NON-NLS
" (art.artifact_id IN (SELECT art.artifact_id FROM blackboard_artifacts AS art, blackboard_attributes AS att1 WHERE (att1.artifact_id = art.artifact_id) AND (art.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID() + ") " + // NON-NLS
"EXCEPT " + // NON-NLS
"SELECT art.artifact_id FROM blackboard_artifacts AS art, blackboard_attributes AS att1 WHERE (att1.artifact_id = art.artifact_id) AND (art.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID() + ") AND (att1.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID() + "))) " + //NON-NLS
"AND (att1.artifact_id = art.artifact_id) " + //NON-NLS
"AND (att2.artifact_id = art.artifact_id) " + //NON-NLS
"AND (f.obj_id = art.obj_id) " + //NON-NLS
"AND (att1.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD.getTypeID() + ") " + // NON-NLS
"AND (att2.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_PREVIEW.getTypeID() + ") " + // NON-NLS
"AND (art.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID() + ") "; // NON-NLS
String keywordsQuery = keywordListsQuery + " UNION " + keywordAdHocQuery + orderByClause;
try (SleuthkitCase.CaseDbQuery dbQuery = openCase.getSleuthkitCase().executeQuery(keywordsQuery)) {
ResultSet resultSet = dbQuery.getResultSet();
@@ -1623,14 +1710,15 @@ class TableReportGenerator {
private HashSet<String> getUniqueTagNames(long artifactId) throws TskCoreException {
HashSet<String> uniqueTagNames = new HashSet<>();
String query = "SELECT display_name, artifact_id FROM tag_names AS tn, blackboard_artifact_tags AS bat "
String query = "SELECT display_name, artifact_id, knownStatus FROM tag_names AS tn, blackboard_artifact_tags AS bat "
+ //NON-NLS
"WHERE tn.tag_name_id = bat.tag_name_id AND bat.artifact_id = " + artifactId; //NON-NLS
try (SleuthkitCase.CaseDbQuery dbQuery = Case.getCurrentCaseThrows().getSleuthkitCase().executeQuery(query)) {
ResultSet tagNameRows = dbQuery.getResultSet();
while (tagNameRows.next()) {
uniqueTagNames.add(tagNameRows.getString("display_name")); //NON-NLS
String notableString = tagNameRows.getInt("knownStatus") == TskData.FileKnown.BAD.ordinal() ? getNotableTagLabel() : "";
uniqueTagNames.add(tagNameRows.getString("display_name") + notableString); //NON-NLS
}
} catch (TskCoreException | SQLException | NoCurrentCaseException ex) {
throw new TskCoreException("Error getting tag names for artifact: ", ex);