19 package org.sleuthkit.autopsy.discovery.search;
21 import java.sql.ResultSet;
22 import java.sql.SQLException;
23 import java.util.ArrayList;
24 import java.util.Arrays;
25 import java.util.HashMap;
26 import java.util.HashSet;
27 import java.util.Iterator;
28 import java.util.List;
31 import java.util.logging.Level;
32 import org.openide.util.NbBundle;
47 import java.util.StringJoiner;
124 static class DataSourceAttribute
extends AttributeType {
127 public DiscoveryKeyUtils.GroupKey getGroupKey(Result result) {
128 return new DiscoveryKeyUtils.DataSourceGroupKey(result);
135 static class FileTypeAttribute
extends AttributeType {
138 public DiscoveryKeyUtils.GroupKey getGroupKey(Result file) {
139 return new DiscoveryKeyUtils.FileTypeGroupKey(file);
146 static class KeywordListAttribute
extends AttributeType {
149 public DiscoveryKeyUtils.GroupKey getGroupKey(Result file) {
150 return new DiscoveryKeyUtils.KeywordListGroupKey((ResultFile) file);
154 public void addAttributeToResults(List<Result> results, SleuthkitCase caseDb,
155 CentralRepository centralRepoDb)
throws DiscoveryException {
159 String selectQuery =
createSetNameClause(results, BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID(),
160 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID());
162 SetKeywordListNamesCallback callback =
new SetKeywordListNamesCallback(results);
164 caseDb.getCaseDbAccessManager().select(selectQuery, callback);
165 }
catch (TskCoreException ex) {
166 throw new DiscoveryException(
"Error looking up keyword list attributes", ex);
177 List<Result> resultFiles;
185 this.resultFiles = resultFiles;
192 Map<Long, ResultFile> tempMap =
new HashMap<>();
193 for (
Result result : resultFiles) {
203 Long objId = rs.getLong(
"object_id");
204 String keywordListName = rs.getString(
"set_name");
208 }
catch (SQLException ex) {
209 logger.log(Level.SEVERE,
"Unable to get object_id or set_name from result set", ex);
212 }
catch (SQLException ex) {
213 logger.log(Level.SEVERE,
"Failed to get keyword list names", ex);
224 static final int BATCH_SIZE = 50;
226 static final int DOMAIN_BATCH_SIZE = 500;
234 public void addAttributeToResults(List<Result> results, SleuthkitCase caseDb,
235 CentralRepository centralRepoDb)
throws DiscoveryException {
236 if (centralRepoDb == null) {
237 for (Result result : results) {
238 if (result.getFrequency() == SearchData.Frequency.UNKNOWN && result.getKnown() == TskData.FileKnown.KNOWN) {
239 result.setFrequency(SearchData.Frequency.KNOWN);
243 processResultFilesForCR(results, centralRepoDb);
255 private void processResultFilesForCR(List<Result> results,
256 CentralRepository centralRepoDb)
throws DiscoveryException {
257 List<ResultFile> currentFiles =
new ArrayList<>();
258 Set<String> hashesToLookUp =
new HashSet<>();
259 List<ResultDomain> domainsToQuery =
new ArrayList<>();
260 for (Result result : results) {
261 if (result.getKnown() == TskData.FileKnown.KNOWN) {
262 result.setFrequency(SearchData.Frequency.KNOWN);
265 if (result.getType() != SearchData.Type.DOMAIN) {
266 ResultFile file = (ResultFile) result;
267 if (file.getFrequency() == SearchData.Frequency.UNKNOWN
268 && file.getFirstInstance().getMd5Hash() != null
269 && !file.getFirstInstance().getMd5Hash().isEmpty()) {
270 hashesToLookUp.add(file.getFirstInstance().getMd5Hash());
271 currentFiles.add(file);
274 if (hashesToLookUp.size() >= BATCH_SIZE) {
277 hashesToLookUp.clear();
278 currentFiles.clear();
281 ResultDomain domainInstance = (ResultDomain) result;
282 if (domainInstance.getFrequency() != SearchData.Frequency.UNKNOWN) {
286 domainsToQuery.add(domainInstance);
288 if (domainsToQuery.size() == DOMAIN_BATCH_SIZE) {
291 domainsToQuery.clear();
310 if (domainsToQuery.isEmpty()) {
314 final Map<String, List<ResultDomain>> resultDomainTable =
new HashMap<>();
315 final StringJoiner joiner =
new StringJoiner(
", ");
320 final String domainValue = domainInstance.getDomain();
322 final List<ResultDomain> bucket = resultDomainTable.getOrDefault(normalizedDomain,
new ArrayList<>());
323 bucket.add(domainInstance);
324 resultDomainTable.put(normalizedDomain, bucket);
325 joiner.add(
"'" + normalizedDomain +
"'");
327 logger.log(Level.INFO, String.format(
"Domain [%s] failed normalization, skipping...", domainInstance.getDomain()));
332 final String domainFrequencyQuery =
" value AS domain_name, COUNT(*) AS frequency "
333 +
"FROM " + tableName +
" "
334 +
"WHERE value IN (" + joiner +
") "
338 centralRepository.processSelectClause(domainFrequencyQuery, frequencyCallback);
340 if (frequencyCallback.getCause() != null) {
341 throw frequencyCallback.getCause();
368 while (resultSet.next()) {
369 String domain = resultSet.getString(
"domain_name");
370 Long frequency = resultSet.getLong(
"frequency");
372 List<ResultDomain> domainInstances = domainLookup.get(domain);
377 }
catch (SQLException ex) {
387 SQLException getCause() {
398 private final List<ResultFile>
files;
406 this.files =
new ArrayList<>(
files);
413 while (resultSet.next()) {
414 String hash = resultSet.getString(1);
415 int count = resultSet.getInt(2);
416 for (Iterator<ResultFile> iterator = files.iterator(); iterator.hasNext();) {
429 }
catch (SQLException ex) {
430 logger.log(Level.WARNING,
"Error getting frequency counts from Central Repository", ex);
445 return new DiscoveryKeyUtils.HashHitsGroupKey((ResultFile) result);
449 public void addAttributeToResults(List<Result> results, SleuthkitCase caseDb,
450 CentralRepository centralRepoDb)
throws DiscoveryException {
454 String selectQuery =
createSetNameClause(results, BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID(),
455 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID());
457 HashSetNamesCallback callback =
new HashSetNamesCallback(results);
459 caseDb.getCaseDbAccessManager().select(selectQuery, callback);
460 }
catch (TskCoreException ex) {
461 throw new DiscoveryException(
"Error looking up hash set attributes", ex);
471 List<Result> results;
479 this.results = results;
486 Map<Long, ResultFile> tempMap =
new HashMap<>();
487 for (
Result result : results) {
497 Long objId = rs.getLong(
"object_id");
498 String hashSetName = rs.getString(
"set_name");
500 tempMap.get(objId).addHashSetName(hashSetName);
502 }
catch (SQLException ex) {
503 logger.log(Level.SEVERE,
"Unable to get object_id or set_name from result set", ex);
506 }
catch (SQLException ex) {
507 logger.log(Level.SEVERE,
"Failed to get hash set names", ex);
516 static class InterestingItemAttribute
extends AttributeType {
524 public void addAttributeToResults(List<Result> results, SleuthkitCase caseDb,
525 CentralRepository centralRepoDb)
throws DiscoveryException {
529 String selectQuery =
createSetNameClause(results, BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID(),
530 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID());
532 InterestingFileSetNamesCallback callback =
new InterestingFileSetNamesCallback(results);
534 caseDb.getCaseDbAccessManager().select(selectQuery, callback);
535 }
catch (TskCoreException ex) {
536 throw new DiscoveryException(
"Error looking up interesting file set attributes", ex);
547 List<Result> results;
556 this.results = results;
563 Map<Long, ResultFile> tempMap =
new HashMap<>();
564 for (
Result result : results) {
574 Long objId = rs.getLong(
"object_id");
575 String setName = rs.getString(
"set_name");
577 tempMap.get(objId).addInterestingSetName(setName);
579 }
catch (SQLException ex) {
580 logger.log(Level.SEVERE,
"Unable to get object_id or set_name from result set", ex);
583 }
catch (SQLException ex) {
584 logger.log(Level.SEVERE,
"Failed to get interesting file set names", ex);
593 static class MostRecentActivityDateAttribute
extends AttributeType {
605 static class FirstActivityDateAttribute
extends AttributeType {
608 public DiscoveryKeyUtils.GroupKey getGroupKey(Result result) {
609 return new DiscoveryKeyUtils.FirstActivityDateGroupKey(result);
617 static class NumberOfVisitsAttribute
extends AttributeType {
620 public DiscoveryKeyUtils.GroupKey getGroupKey(Result result) {
621 return new DiscoveryKeyUtils.NumberOfVisitsGroupKey(result);
628 static class ObjectDetectedAttribute
extends AttributeType {
631 public DiscoveryKeyUtils.GroupKey getGroupKey(Result file) {
632 return new DiscoveryKeyUtils.ObjectDetectedGroupKey((ResultFile) file);
636 public void addAttributeToResults(List<Result> results, SleuthkitCase caseDb,
637 CentralRepository centralRepoDb)
throws DiscoveryException {
641 String selectQuery =
createSetNameClause(results, BlackboardArtifact.ARTIFACT_TYPE.TSK_OBJECT_DETECTED.getTypeID(),
642 BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DESCRIPTION.getTypeID());
644 ObjectDetectedNamesCallback callback =
new ObjectDetectedNamesCallback(results);
646 caseDb.getCaseDbAccessManager().select(selectQuery, callback);
647 }
catch (TskCoreException ex) {
648 throw new DiscoveryException(
"Error looking up object detected attributes", ex);
659 List<Result> results;
667 this.results = results;
674 Map<Long, ResultFile> tempMap =
new HashMap<>();
675 for (
Result result : results) {
685 Long objId = rs.getLong(
"object_id");
686 String setName = rs.getString(
"set_name");
688 tempMap.get(objId).addObjectDetectedName(setName);
690 }
catch (SQLException ex) {
691 logger.log(Level.SEVERE,
"Unable to get object_id or set_name from result set", ex);
694 }
catch (SQLException ex) {
695 logger.log(Level.SEVERE,
"Failed to get object detected names", ex);
712 public void addAttributeToResults(List<Result> results, SleuthkitCase caseDb,
713 CentralRepository centralRepoDb)
throws DiscoveryException {
716 for (Result result : results) {
720 ResultFile file = (ResultFile) result;
721 List<ContentTag> contentTags = caseDb.getContentTagsByContent(file.getFirstInstance());
723 for (ContentTag tag : contentTags) {
724 result.
addTagName(tag.getName().getDisplayName());
727 }
catch (TskCoreException ex) {
728 throw new DiscoveryException(
"Error looking up file tag attributes", ex);
737 "DiscoveryAttributes.GroupingAttributeType.fileType.displayName=File Type",
738 "DiscoveryAttributes.GroupingAttributeType.frequency.displayName=Past Occurrences",
739 "DiscoveryAttributes.GroupingAttributeType.keywordList.displayName=Keyword",
740 "DiscoveryAttributes.GroupingAttributeType.size.displayName=File Size",
741 "DiscoveryAttributes.GroupingAttributeType.datasource.displayName=Data Source",
742 "DiscoveryAttributes.GroupingAttributeType.parent.displayName=Parent Folder",
743 "DiscoveryAttributes.GroupingAttributeType.hash.displayName=Hash Set",
744 "DiscoveryAttributes.GroupingAttributeType.interestingItem.displayName=Interesting Item",
745 "DiscoveryAttributes.GroupingAttributeType.tag.displayName=Tag",
746 "DiscoveryAttributes.GroupingAttributeType.object.displayName=Object Detected",
747 "DiscoveryAttributes.GroupingAttributeType.mostRecentDate.displayName=Most Recent Activity Date",
748 "DiscoveryAttributes.GroupingAttributeType.firstDate.displayName=First Activity Date",
749 "DiscoveryAttributes.GroupingAttributeType.numberOfVisits.displayName=Number of Visits",
750 "DiscoveryAttributes.GroupingAttributeType.none.displayName=None"})
753 FREQUENCY(
new FrequencyAttribute(), Bundle.DiscoveryAttributes_GroupingAttributeType_frequency_displayName()),
754 KEYWORD_LIST_NAME(
new KeywordListAttribute(), Bundle.DiscoveryAttributes_GroupingAttributeType_keywordList_displayName()),
755 DATA_SOURCE(
new DataSourceAttribute(), Bundle.DiscoveryAttributes_GroupingAttributeType_datasource_displayName()),
757 HASH_LIST_NAME(
new HashHitsAttribute(), Bundle.DiscoveryAttributes_GroupingAttributeType_hash_displayName()),
758 INTERESTING_ITEM_SET(
new InterestingItemAttribute(), Bundle.DiscoveryAttributes_GroupingAttributeType_interestingItem_displayName()),
759 FILE_TAG(
new FileTagAttribute(), Bundle.DiscoveryAttributes_GroupingAttributeType_tag_displayName()),
760 OBJECT_DETECTED(
new ObjectDetectedAttribute(), Bundle.DiscoveryAttributes_GroupingAttributeType_object_displayName()),
761 MOST_RECENT_DATE(
new MostRecentActivityDateAttribute(), Bundle.DiscoveryAttributes_GroupingAttributeType_mostRecentDate_displayName()),
762 FIRST_DATE(
new FirstActivityDateAttribute(), Bundle.DiscoveryAttributes_GroupingAttributeType_firstDate_displayName()),
763 NUMBER_OF_VISITS(
new NumberOfVisitsAttribute(), Bundle.DiscoveryAttributes_GroupingAttributeType_numberOfVisits_displayName()),
764 NO_GROUPING(
new NoGroupingAttribute(), Bundle.DiscoveryAttributes_GroupingAttributeType_none_displayName());
778 this.attributeType = attributeType;
779 this.displayName = displayName;
793 return attributeType;
802 return Arrays.asList(FILE_SIZE, FREQUENCY, PARENT_PATH, OBJECT_DETECTED, HASH_LIST_NAME, INTERESTING_ITEM_SET);
811 return Arrays.asList(FREQUENCY, MOST_RECENT_DATE, FIRST_DATE, NUMBER_OF_VISITS);
825 if (hashesToLookUp.isEmpty()) {
829 String hashes = String.join(
"','", hashesToLookUp);
830 hashes =
"'" + hashes +
"'";
835 String selectClause =
" value, COUNT(value) FROM "
836 +
"(SELECT DISTINCT case_id, value FROM " + tableName
837 +
" WHERE value IN ("
839 +
")) AS foo GROUP BY value";
845 logger.log(Level.WARNING,
"Error getting frequency counts from Central Repository", ex);
867 String objIdList =
"";
868 for (
Result result : results) {
873 if (!objIdList.isEmpty()) {
881 return "blackboard_artifacts.obj_id AS object_id, blackboard_attributes.value_text AS set_name "
882 +
"FROM blackboard_artifacts "
883 +
"INNER JOIN blackboard_attributes ON blackboard_artifacts.artifact_id=blackboard_attributes.artifact_id "
884 +
"WHERE blackboard_attributes.artifact_type_id=\'" + artifactTypeID +
"\' "
885 +
"AND blackboard_attributes.attribute_type_id=\'" + setNameAttrID +
"\' "
886 +
"AND blackboard_artifacts.obj_id IN (" + objIdList
static String createSetNameClause(List< Result > results, int artifactTypeID, int setNameAttrID)
AttributeType getAttributeType()
DiscoveryKeyUtils.GroupKey getGroupKey(Result file)
static List< GroupingAttributeType > getOptionsForGroupingForDomains()
DomainFrequencyCallback(Map< String, List< ResultDomain >> domainLookup)
void process(ResultSet rs)
static final Logger logger
static void computeFrequency(Set< String > hashesToLookUp, List< ResultFile > currentFiles, CentralRepository centralRepoDb)
void addTagName(String tagName)
static Frequency fromCount(long count)
abstract SearchData.Type getType()
FrequencyCallback(List< ResultFile > files)
GroupingAttributeType(AttributeType attributeType, String displayName)
static List< GroupingAttributeType > getOptionsForGroupingForFiles()
final void setFrequency(SearchData.Frequency frequency)
static String correlationTypeToInstanceTableName(CorrelationAttributeInstance.Type type)
static String normalize(CorrelationAttributeInstance.Type attributeType, String data)
AbstractFile getFirstInstance()
void process(ResultSet resultSet)
DiscoveryKeyUtils.GroupKey getGroupKey(Result result)
void addAttributeToResults(List< Result > results, SleuthkitCase caseDb, CentralRepository centralRepoDb)
static final int DOMAIN_TYPE_ID
void process(ResultSet rs)
abstract DiscoveryKeyUtils.GroupKey getGroupKey(Result result)
final List< ResultFile > files
final Map< String, List< ResultDomain > > domainLookup
void process(ResultSet rs)
void addKeywordListName(String keywordListName)
void process(ResultSet rs)
synchronized static Logger getLogger(String name)
CorrelationAttributeInstance.Type getCorrelationTypeById(int typeId)
void process(ResultSet resultSet)
void processSelectClause(String selectClause, InstanceTableCallback instanceTableCallback)
static void queryDomainFrequency(List< ResultDomain > domainsToQuery, CentralRepository centralRepository)
static final int FILES_TYPE_ID
final AttributeType attributeType