Autopsy  4.16.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
DiscoveryAttributes.java
Go to the documentation of this file.
1 /*
2  * Autopsy
3  *
4  * Copyright 2020 Basis Technology Corp.
5  * Contact: carrier <at> sleuthkit <dot> org
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 package org.sleuthkit.autopsy.discovery.search;
20 
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;
29 import java.util.Map;
30 import java.util.Set;
31 import java.util.logging.Level;
32 import org.openide.util.NbBundle;
40 import org.sleuthkit.datamodel.BlackboardArtifact;
41 import org.sleuthkit.datamodel.BlackboardAttribute;
42 import org.sleuthkit.datamodel.CaseDbAccessManager;
43 import org.sleuthkit.datamodel.ContentTag;
44 import org.sleuthkit.datamodel.SleuthkitCase;
45 import org.sleuthkit.datamodel.TskCoreException;
46 import org.sleuthkit.datamodel.TskData;
47 import java.util.StringJoiner;
49 
54 public class DiscoveryAttributes {
55 
56  private final static Logger logger = Logger.getLogger(DiscoveryAttributes.class.getName());
57 
61  public abstract static class AttributeType {
62 
71  public abstract DiscoveryKeyUtils.GroupKey getGroupKey(Result result);
72 
83  public void addAttributeToResults(List<Result> results, SleuthkitCase caseDb, CentralRepository centralRepoDb) throws DiscoveryException {
84  // Default is to do nothing
85  }
86  }
87 
91  public static class FileSizeAttribute extends AttributeType {
92 
93  @Override
95  return new DiscoveryKeyUtils.FileSizeGroupKey(result);
96  }
97  }
98 
102  public static class ParentPathAttribute extends AttributeType {
103 
104  @Override
107  }
108  }
109 
113  static class NoGroupingAttribute extends AttributeType {
114 
115  @Override
116  public DiscoveryKeyUtils.GroupKey getGroupKey(Result result) {
118  }
119  }
120 
124  static class DataSourceAttribute extends AttributeType {
125 
126  @Override
127  public DiscoveryKeyUtils.GroupKey getGroupKey(Result result) {
128  return new DiscoveryKeyUtils.DataSourceGroupKey(result);
129  }
130  }
131 
135  static class FileTypeAttribute extends AttributeType {
136 
137  @Override
138  public DiscoveryKeyUtils.GroupKey getGroupKey(Result file) {
139  return new DiscoveryKeyUtils.FileTypeGroupKey(file);
140  }
141  }
142 
146  static class KeywordListAttribute extends AttributeType {
147 
148  @Override
149  public DiscoveryKeyUtils.GroupKey getGroupKey(Result file) {
150  return new DiscoveryKeyUtils.KeywordListGroupKey((ResultFile) file);
151  }
152 
153  @Override
154  public void addAttributeToResults(List<Result> results, SleuthkitCase caseDb,
155  CentralRepository centralRepoDb) throws DiscoveryException {
156 
157  // Get pairs of (object ID, keyword list name) for all files in the list of files that have
158  // keyword list hits.
159  String selectQuery = createSetNameClause(results, BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID(),
160  BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID());
161 
162  SetKeywordListNamesCallback callback = new SetKeywordListNamesCallback(results);
163  try {
164  caseDb.getCaseDbAccessManager().select(selectQuery, callback);
165  } catch (TskCoreException ex) {
166  throw new DiscoveryException("Error looking up keyword list attributes", ex); // NON-NLS
167  }
168  }
169 
175  private static class SetKeywordListNamesCallback implements CaseDbAccessManager.CaseDbAccessQueryCallback {
176 
177  List<Result> resultFiles;
178 
184  SetKeywordListNamesCallback(List<Result> resultFiles) {
185  this.resultFiles = resultFiles;
186  }
187 
188  @Override
189  public void process(ResultSet rs) {
190  try {
191  // Create a temporary map of object ID to ResultFile
192  Map<Long, ResultFile> tempMap = new HashMap<>();
193  for (Result result : resultFiles) {
194  if (result.getType() == SearchData.Type.DOMAIN) {
195  break;
196  }
197  ResultFile file = (ResultFile) result;
198  tempMap.put(file.getFirstInstance().getId(), file);
199  }
200 
201  while (rs.next()) {
202  try {
203  Long objId = rs.getLong("object_id"); // NON-NLS
204  String keywordListName = rs.getString("set_name"); // NON-NLS
205 
206  tempMap.get(objId).addKeywordListName(keywordListName);
207 
208  } catch (SQLException ex) {
209  logger.log(Level.SEVERE, "Unable to get object_id or set_name from result set", ex); // NON-NLS
210  }
211  }
212  } catch (SQLException ex) {
213  logger.log(Level.SEVERE, "Failed to get keyword list names", ex); // NON-NLS
214  }
215  }
216  }
217  }
218 
222  static class FrequencyAttribute extends AttributeType {
223 
224  static final int BATCH_SIZE = 50; // Number of hashes to look up at one time
225 
226  static final int DOMAIN_BATCH_SIZE = 500; // Number of domains to look up at one time
227 
228  @Override
229  public DiscoveryKeyUtils.GroupKey getGroupKey(Result file) {
230  return new DiscoveryKeyUtils.FrequencyGroupKey(file);
231  }
232 
233  @Override
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);
240  }
241  }
242  } else {
243  processResultFilesForCR(results, centralRepoDb);
244  }
245  }
246 
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);
263  }
264 
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);
272  }
273 
274  if (hashesToLookUp.size() >= BATCH_SIZE) {
275  computeFrequency(hashesToLookUp, currentFiles, centralRepoDb);
276 
277  hashesToLookUp.clear();
278  currentFiles.clear();
279  }
280  } else {
281  ResultDomain domainInstance = (ResultDomain) result;
282  if (domainInstance.getFrequency() != SearchData.Frequency.UNKNOWN) {
283  // Frequency already calculated, skipping...
284  continue;
285  }
286  domainsToQuery.add(domainInstance);
287 
288  if (domainsToQuery.size() == DOMAIN_BATCH_SIZE) {
289  queryDomainFrequency(domainsToQuery, centralRepoDb);
290 
291  domainsToQuery.clear();
292  }
293  }
294  }
295 
296  queryDomainFrequency(domainsToQuery, centralRepoDb);
297  computeFrequency(hashesToLookUp, currentFiles, centralRepoDb);
298  }
299  }
300 
309  private static void queryDomainFrequency(List<ResultDomain> domainsToQuery, CentralRepository centralRepository) throws DiscoveryException {
310  if (domainsToQuery.isEmpty()) {
311  return;
312  }
313  try {
314  final Map<String, List<ResultDomain>> resultDomainTable = new HashMap<>();
315  final StringJoiner joiner = new StringJoiner(", ");
316 
317  final CorrelationAttributeInstance.Type attributeType = centralRepository.getCorrelationTypeById(CorrelationAttributeInstance.DOMAIN_TYPE_ID);
318  for (ResultDomain domainInstance : domainsToQuery) {
319  try {
320  final String domainValue = domainInstance.getDomain();
321  final String normalizedDomain = CorrelationAttributeNormalizer.normalize(attributeType, domainValue);
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()));
328  }
329  }
330 
331  final String tableName = CentralRepoDbUtil.correlationTypeToInstanceTableName(attributeType);
332  final String domainFrequencyQuery = " value AS domain_name, COUNT(*) AS frequency "
333  + "FROM " + tableName + " "
334  + "WHERE value IN (" + joiner + ") "
335  + "GROUP BY value";
336 
337  final DomainFrequencyCallback frequencyCallback = new DomainFrequencyCallback(resultDomainTable);
338  centralRepository.processSelectClause(domainFrequencyQuery, frequencyCallback);
339 
340  if (frequencyCallback.getCause() != null) {
341  throw frequencyCallback.getCause();
342  }
343  } catch (CentralRepoException | SQLException ex) {
344  throw new DiscoveryException("Fatal exception encountered querying the CR.", ex);
345  }
346  }
347 
351  private static class DomainFrequencyCallback implements InstanceTableCallback {
352 
353  private final Map<String, List<ResultDomain>> domainLookup;
354  private SQLException sqlCause;
355 
361  private DomainFrequencyCallback(Map<String, List<ResultDomain>> domainLookup) {
362  this.domainLookup = domainLookup;
363  }
364 
365  @Override
366  public void process(ResultSet resultSet) {
367  try {
368  while (resultSet.next()) {
369  String domain = resultSet.getString("domain_name");
370  Long frequency = resultSet.getLong("frequency");
371 
372  List<ResultDomain> domainInstances = domainLookup.get(domain);
373  for (ResultDomain domainInstance : domainInstances) {
374  domainInstance.setFrequency(SearchData.Frequency.fromCount(frequency));
375  }
376  }
377  } catch (SQLException ex) {
378  this.sqlCause = ex;
379  }
380  }
381 
387  SQLException getCause() {
388  return this.sqlCause;
389  }
390  }
391 
396  private static class FrequencyCallback implements InstanceTableCallback {
397 
398  private final List<ResultFile> files;
399 
405  private FrequencyCallback(List<ResultFile> files) {
406  this.files = new ArrayList<>(files);
407  }
408 
409  @Override
410  public void process(ResultSet resultSet) {
411  try {
412 
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();) {
417  ResultFile file = iterator.next();
418  if (file.getFirstInstance().getMd5Hash().equalsIgnoreCase(hash)) {
420  iterator.remove();
421  }
422  }
423  }
424 
425  // The files left had no matching entries in the CR, so mark them as unique
426  for (ResultFile file : files) {
427  file.setFrequency(SearchData.Frequency.UNIQUE);
428  }
429  } catch (SQLException ex) {
430  logger.log(Level.WARNING, "Error getting frequency counts from Central Repository", ex); // NON-NLS
431  }
432  }
433  }
434 
438  static class HashHitsAttribute extends AttributeType {
439 
440  @Override
441  public DiscoveryKeyUtils.GroupKey getGroupKey(Result result) {
442  if (result.getType() == SearchData.Type.DOMAIN) {
443  return null;
444  }
445  return new DiscoveryKeyUtils.HashHitsGroupKey((ResultFile) result);
446  }
447 
448  @Override
449  public void addAttributeToResults(List<Result> results, SleuthkitCase caseDb,
450  CentralRepository centralRepoDb) throws DiscoveryException {
451 
452  // Get pairs of (object ID, hash set name) for all files in the list of files that have
453  // hash set hits.
454  String selectQuery = createSetNameClause(results, BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID(),
455  BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID());
456 
457  HashSetNamesCallback callback = new HashSetNamesCallback(results);
458  try {
459  caseDb.getCaseDbAccessManager().select(selectQuery, callback);
460  } catch (TskCoreException ex) {
461  throw new DiscoveryException("Error looking up hash set attributes", ex); // NON-NLS
462  }
463  }
464 
469  private static class HashSetNamesCallback implements CaseDbAccessManager.CaseDbAccessQueryCallback {
470 
471  List<Result> results;
472 
478  HashSetNamesCallback(List<Result> results) {
479  this.results = results;
480  }
481 
482  @Override
483  public void process(ResultSet rs) {
484  try {
485  // Create a temporary map of object ID to ResultFile
486  Map<Long, ResultFile> tempMap = new HashMap<>();
487  for (Result result : results) {
488  if (result.getType() == SearchData.Type.DOMAIN) {
489  return;
490  }
491  ResultFile file = (ResultFile) result;
492  tempMap.put(file.getFirstInstance().getId(), file);
493  }
494 
495  while (rs.next()) {
496  try {
497  Long objId = rs.getLong("object_id"); // NON-NLS
498  String hashSetName = rs.getString("set_name"); // NON-NLS
499 
500  tempMap.get(objId).addHashSetName(hashSetName);
501 
502  } catch (SQLException ex) {
503  logger.log(Level.SEVERE, "Unable to get object_id or set_name from result set", ex); // NON-NLS
504  }
505  }
506  } catch (SQLException ex) {
507  logger.log(Level.SEVERE, "Failed to get hash set names", ex); // NON-NLS
508  }
509  }
510  }
511  }
512 
516  static class InterestingItemAttribute extends AttributeType {
517 
518  @Override
519  public DiscoveryKeyUtils.GroupKey getGroupKey(Result file) {
521  }
522 
523  @Override
524  public void addAttributeToResults(List<Result> results, SleuthkitCase caseDb,
525  CentralRepository centralRepoDb) throws DiscoveryException {
526 
527  // Get pairs of (object ID, interesting item set name) for all files in the list of files that have
528  // interesting file set hits.
529  String selectQuery = createSetNameClause(results, BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID(),
530  BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID());
531 
532  InterestingFileSetNamesCallback callback = new InterestingFileSetNamesCallback(results);
533  try {
534  caseDb.getCaseDbAccessManager().select(selectQuery, callback);
535  } catch (TskCoreException ex) {
536  throw new DiscoveryException("Error looking up interesting file set attributes", ex); // NON-NLS
537  }
538  }
539 
545  private static class InterestingFileSetNamesCallback implements CaseDbAccessManager.CaseDbAccessQueryCallback {
546 
547  List<Result> results;
548 
555  InterestingFileSetNamesCallback(List<Result> results) {
556  this.results = results;
557  }
558 
559  @Override
560  public void process(ResultSet rs) {
561  try {
562  // Create a temporary map of object ID to ResultFile
563  Map<Long, ResultFile> tempMap = new HashMap<>();
564  for (Result result : results) {
565  if (result.getType() == SearchData.Type.DOMAIN) {
566  return;
567  }
568  ResultFile file = (ResultFile) result;
569  tempMap.put(file.getFirstInstance().getId(), file);
570  }
571 
572  while (rs.next()) {
573  try {
574  Long objId = rs.getLong("object_id"); // NON-NLS
575  String setName = rs.getString("set_name"); // NON-NLS
576 
577  tempMap.get(objId).addInterestingSetName(setName);
578 
579  } catch (SQLException ex) {
580  logger.log(Level.SEVERE, "Unable to get object_id or set_name from result set", ex); // NON-NLS
581  }
582  }
583  } catch (SQLException ex) {
584  logger.log(Level.SEVERE, "Failed to get interesting file set names", ex); // NON-NLS
585  }
586  }
587  }
588  }
589 
593  static class MostRecentActivityDateAttribute extends AttributeType {
594 
595  @Override
596  public DiscoveryKeyUtils.GroupKey getGroupKey(Result result) {
598  }
599 
600  }
601 
605  static class FirstActivityDateAttribute extends AttributeType {
606 
607  @Override
608  public DiscoveryKeyUtils.GroupKey getGroupKey(Result result) {
609  return new DiscoveryKeyUtils.FirstActivityDateGroupKey(result);
610  }
611 
612  }
613 
617  static class NumberOfVisitsAttribute extends AttributeType {
618 
619  @Override
620  public DiscoveryKeyUtils.GroupKey getGroupKey(Result result) {
621  return new DiscoveryKeyUtils.NumberOfVisitsGroupKey(result);
622  }
623  }
624 
628  static class ObjectDetectedAttribute extends AttributeType {
629 
630  @Override
631  public DiscoveryKeyUtils.GroupKey getGroupKey(Result file) {
632  return new DiscoveryKeyUtils.ObjectDetectedGroupKey((ResultFile) file);
633  }
634 
635  @Override
636  public void addAttributeToResults(List<Result> results, SleuthkitCase caseDb,
637  CentralRepository centralRepoDb) throws DiscoveryException {
638 
639  // Get pairs of (object ID, object type name) for all files in the list of files that have
640  // objects detected
641  String selectQuery = createSetNameClause(results, BlackboardArtifact.ARTIFACT_TYPE.TSK_OBJECT_DETECTED.getTypeID(),
642  BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DESCRIPTION.getTypeID());
643 
644  ObjectDetectedNamesCallback callback = new ObjectDetectedNamesCallback(results);
645  try {
646  caseDb.getCaseDbAccessManager().select(selectQuery, callback);
647  } catch (TskCoreException ex) {
648  throw new DiscoveryException("Error looking up object detected attributes", ex); // NON-NLS
649  }
650  }
651 
657  private static class ObjectDetectedNamesCallback implements CaseDbAccessManager.CaseDbAccessQueryCallback {
658 
659  List<Result> results;
660 
666  ObjectDetectedNamesCallback(List<Result> results) {
667  this.results = results;
668  }
669 
670  @Override
671  public void process(ResultSet rs) {
672  try {
673  // Create a temporary map of object ID to ResultFile
674  Map<Long, ResultFile> tempMap = new HashMap<>();
675  for (Result result : results) {
676  if (result.getType() == SearchData.Type.DOMAIN) {
677  return;
678  }
679  ResultFile file = (ResultFile) result;
680  tempMap.put(file.getFirstInstance().getId(), file);
681  }
682 
683  while (rs.next()) {
684  try {
685  Long objId = rs.getLong("object_id"); // NON-NLS
686  String setName = rs.getString("set_name"); // NON-NLS
687 
688  tempMap.get(objId).addObjectDetectedName(setName);
689 
690  } catch (SQLException ex) {
691  logger.log(Level.SEVERE, "Unable to get object_id or set_name from result set", ex); // NON-NLS
692  }
693  }
694  } catch (SQLException ex) {
695  logger.log(Level.SEVERE, "Failed to get object detected names", ex); // NON-NLS
696  }
697  }
698  }
699  }
700 
704  static class FileTagAttribute extends AttributeType {
705 
706  @Override
707  public DiscoveryKeyUtils.GroupKey getGroupKey(Result file) {
708  return new DiscoveryKeyUtils.FileTagGroupKey((ResultFile) file);
709  }
710 
711  @Override
712  public void addAttributeToResults(List<Result> results, SleuthkitCase caseDb,
713  CentralRepository centralRepoDb) throws DiscoveryException {
714 
715  try {
716  for (Result result : results) {
717  if (result.getType() == SearchData.Type.DOMAIN) {
718  return;
719  }
720  ResultFile file = (ResultFile) result;
721  List<ContentTag> contentTags = caseDb.getContentTagsByContent(file.getFirstInstance());
722 
723  for (ContentTag tag : contentTags) {
724  result.addTagName(tag.getName().getDisplayName());
725  }
726  }
727  } catch (TskCoreException ex) {
728  throw new DiscoveryException("Error looking up file tag attributes", ex); // NON-NLS
729  }
730  }
731  }
732 
736  @NbBundle.Messages({
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"})
751  public enum GroupingAttributeType {
752  FILE_SIZE(new FileSizeAttribute(), Bundle.DiscoveryAttributes_GroupingAttributeType_size_displayName()),
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()),
756  PARENT_PATH(new ParentPathAttribute(), Bundle.DiscoveryAttributes_GroupingAttributeType_parent_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());
765 
767  private final String displayName;
768 
777  GroupingAttributeType(AttributeType attributeType, String displayName) {
778  this.attributeType = attributeType;
779  this.displayName = displayName;
780  }
781 
782  @Override
783  public String toString() {
784  return displayName;
785  }
786 
793  return attributeType;
794  }
795 
801  public static List<GroupingAttributeType> getOptionsForGroupingForFiles() {
802  return Arrays.asList(FILE_SIZE, FREQUENCY, PARENT_PATH, OBJECT_DETECTED, HASH_LIST_NAME, INTERESTING_ITEM_SET);
803  }
804 
810  public static List<GroupingAttributeType> getOptionsForGroupingForDomains() {
811  return Arrays.asList(FREQUENCY, MOST_RECENT_DATE, FIRST_DATE, NUMBER_OF_VISITS);
812  }
813  }
814 
823  private static void computeFrequency(Set<String> hashesToLookUp, List<ResultFile> currentFiles, CentralRepository centralRepoDb) {
824 
825  if (hashesToLookUp.isEmpty()) {
826  return;
827  }
828 
829  String hashes = String.join("','", hashesToLookUp);
830  hashes = "'" + hashes + "'";
831  try {
833  String tableName = CentralRepoDbUtil.correlationTypeToInstanceTableName(attributeType);
834 
835  String selectClause = " value, COUNT(value) FROM "
836  + "(SELECT DISTINCT case_id, value FROM " + tableName
837  + " WHERE value IN ("
838  + hashes
839  + ")) AS foo GROUP BY value";
840 
841  FrequencyCallback callback = new FrequencyCallback(currentFiles);
842  centralRepoDb.processSelectClause(selectClause, callback);
843 
844  } catch (CentralRepoException ex) {
845  logger.log(Level.WARNING, "Error getting frequency counts from Central Repository", ex); // NON-NLS
846  }
847 
848  }
849 
863  private static String createSetNameClause(List<Result> results,
864  int artifactTypeID, int setNameAttrID) throws DiscoveryException {
865 
866  // Concatenate the object IDs in the list of files
867  String objIdList = ""; // NON-NLS
868  for (Result result : results) {
869  if (result.getType() == SearchData.Type.DOMAIN) {
870  break;
871  }
872  ResultFile file = (ResultFile) result;
873  if (!objIdList.isEmpty()) {
874  objIdList += ","; // NON-NLS
875  }
876  objIdList += "\'" + file.getFirstInstance().getId() + "\'"; // NON-NLS
877  }
878 
879  // Get pairs of (object ID, set name) for all files in the list of files that have
880  // the given artifact type.
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
887  + ") "; // NON-NLS
888  }
889 
894  // Class should not be instantiated
895  }
896 }
static String createSetNameClause(List< Result > results, int artifactTypeID, int setNameAttrID)
static void computeFrequency(Set< String > hashesToLookUp, List< ResultFile > currentFiles, CentralRepository centralRepoDb)
final void setFrequency(SearchData.Frequency frequency)
Definition: Result.java:64
static String correlationTypeToInstanceTableName(CorrelationAttributeInstance.Type type)
static String normalize(CorrelationAttributeInstance.Type attributeType, String data)
void addAttributeToResults(List< Result > results, SleuthkitCase caseDb, CentralRepository centralRepoDb)
abstract DiscoveryKeyUtils.GroupKey getGroupKey(Result result)
void addKeywordListName(String keywordListName)
synchronized static Logger getLogger(String name)
Definition: Logger.java:124
CorrelationAttributeInstance.Type getCorrelationTypeById(int typeId)
void processSelectClause(String selectClause, InstanceTableCallback instanceTableCallback)
static void queryDomainFrequency(List< ResultDomain > domainsToQuery, CentralRepository centralRepository)

Copyright © 2012-2020 Basis Technology. Generated on: Tue Sep 22 2020
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.