Autopsy  4.19.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
FilesSet.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2011-2018 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.modules.interestingitems;
20 
21 import java.io.Serializable;
22 import java.util.ArrayList;
23 import java.util.HashMap;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.UUID;
27 import java.util.regex.Pattern;
28 import org.openide.util.NbBundle;
29 import org.sleuthkit.datamodel.AbstractFile;
30 import org.sleuthkit.datamodel.TskData;
31 
40 public final class FilesSet implements Serializable {
41 
42  private static final long serialVersionUID = 1L;
43  private final String name;
44  private final String description;
45  private final boolean ignoreKnownFiles;
46  private final boolean ignoreUnallocatedSpace;
47 
48  private final boolean standardSet;
49  private final int versionNumber;
50 
51  private final Map<String, Rule> rules = new HashMap<>();
52 
65  public FilesSet(String name, String description, boolean ignoreKnownFiles, boolean ignoreUnallocatedSpace, Map<String, Rule> rules) {
67  }
68 
86  public FilesSet(String name, String description, boolean ignoreKnownFiles, boolean ignoreUnallocatedSpace, Map<String, Rule> rules,
87  boolean standardSet, int versionNumber) {
88  if ((name == null) || (name.isEmpty())) {
89  throw new IllegalArgumentException("Interesting files set name cannot be null or empty");
90  }
91 
92  if (versionNumber < 0) {
93  throw new IllegalArgumentException("version number must be >= 0");
94  }
95 
96  this.standardSet = standardSet;
97  this.versionNumber = versionNumber;
98 
99  this.name = name;
100  this.description = (description != null ? description : "");
101  this.ignoreKnownFiles = ignoreKnownFiles;
102  this.ignoreUnallocatedSpace = ignoreUnallocatedSpace;
103  if (rules != null) {
104  this.rules.putAll(rules);
105  }
106  }
107 
112  boolean isStandardSet() {
113  return standardSet;
114  }
115 
120  int getVersionNumber() {
121  return versionNumber;
122  }
123 
129  public String getName() {
130  return this.name;
131  }
132 
138  public String getDescription() {
139  return this.description;
140  }
141 
151  public boolean ignoresKnownFiles() {
152  return this.ignoreKnownFiles;
153  }
154 
161  public boolean ingoresUnallocatedSpace() {
162  return this.ignoreUnallocatedSpace;
163  }
164 
170  public Map<String, Rule> getRules() {
171  return new HashMap<>(this.rules);
172  }
173 
182  public String fileIsMemberOf(AbstractFile file) {
183  if ((this.ignoreKnownFiles) && (file.getKnown() == TskData.FileKnown.KNOWN)) {
184  return null;
185  }
186 
187  if ((this.ignoreUnallocatedSpace)
188  && (file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS)
189  || file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.SLACK)
190  || file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS))) {
191  return null;
192  }
193 
194  for (Rule rule : rules.values()) {
195  if (rule.isSatisfied(file)) {
196  return rule.getName();
197  }
198  }
199  return null;
200  }
201 
202  @Override
203  public String toString() {
204  // This override is designed to provide a display name for use with
205  // javax.swing.DefaultListModel<E>.
206  return this.name;
207  }
208 
213  public final static class Rule implements Serializable {
214 
215  private static final long serialVersionUID = 1L;
216  private final String uuid;
217  private final String ruleName;
218  private final FileNameCondition fileNameCondition;
224  private final List<FileAttributeCondition> conditions = new ArrayList<>();
225 
238  public Rule(String ruleName, FileNameCondition fileNameCondition, MetaTypeCondition metaTypeCondition, ParentPathCondition pathCondition, MimeTypeCondition mimeTypeCondition, FileSizeCondition fileSizeCondition, DateCondition dateCondition) {
239  // since ruleName is optional, ruleUUID can be used to uniquely identify a rule.
240  this.uuid = UUID.randomUUID().toString();
241  if (metaTypeCondition == null) {
242  throw new IllegalArgumentException("Interesting files set rule meta-type condition cannot be null");
243  }
244 
245  this.ruleName = ruleName;
246 
247  /*
248  * The rules are evaluated in the order added. MetaType check is
249  * fastest, so do it first
250  */
251  this.metaTypeCondition = metaTypeCondition;
252  this.conditions.add(this.metaTypeCondition);
253 
254  this.fileSizeCondition = fileSizeCondition;
255  if (this.fileSizeCondition != null) {
256  this.conditions.add(this.fileSizeCondition);
257  }
258 
259  this.fileNameCondition = fileNameCondition;
260  if (this.fileNameCondition != null) {
261  this.conditions.add(fileNameCondition);
262  }
263 
264  this.mimeTypeCondition = mimeTypeCondition;
265  if (this.mimeTypeCondition != null) {
266  this.conditions.add(mimeTypeCondition);
267  }
268 
269  this.pathCondition = pathCondition;
270  if (this.pathCondition != null) {
271  this.conditions.add(this.pathCondition);
272  }
273  this.dateCondition = dateCondition;
274  if (this.dateCondition != null) {
275  this.conditions.add(this.dateCondition);
276  }
277  }
278 
284  public String getName() {
285  return ruleName;
286  }
287 
293  public FileNameCondition getFileNameCondition() {
294  return this.fileNameCondition;
295  }
296 
303  return this.metaTypeCondition;
304  }
305 
312  return this.pathCondition;
313  }
314 
316  return this.dateCondition;
317  }
318 
326  public boolean isSatisfied(AbstractFile file) {
327  for (FileAttributeCondition condition : conditions) {
328  if (!condition.passes(file)) {
329  return false;
330  }
331  }
332  return true;
333  }
334 
335  @NbBundle.Messages({
336  "# {0} - daysIncluded",
337  "FilesSet.rule.dateRule.toString=(modified within {0} day(s))"
338  })
339  @Override
340  public String toString() {
341  // This override is designed to provide a display name for use with
342  // javax.swing.DefaultListModel<E>.
343  if (fileNameCondition != null) {
344  return this.ruleName + " (" + fileNameCondition.getTextToMatch() + ")";
345  } else if (this.pathCondition != null) {
346  return this.ruleName + " (" + pathCondition.getTextToMatch() + ")";
347  } else if (this.mimeTypeCondition != null) {
348  return this.ruleName + " (" + mimeTypeCondition.getMimeType() + ")";
349  } else if (this.fileSizeCondition != null) {
350  return this.ruleName + " (" + fileSizeCondition.getComparator().getSymbol() + " " + fileSizeCondition.getSizeValue()
351  + " " + fileSizeCondition.getUnit().getName() + ")";
352  } else if (this.dateCondition != null) {
353  return this.ruleName + Bundle.FilesSet_rule_dateRule_toString(dateCondition.getDaysIncluded());
354  } else {
355  return this.ruleName + " ()";
356  }
357 
358  }
359 
363  public String getUuid() {
364  return this.uuid;
365  }
366 
371  return mimeTypeCondition;
372  }
373 
378  return fileSizeCondition;
379  }
380 
385  static interface FileAttributeCondition extends Serializable {
386 
394  boolean passes(AbstractFile file);
395  }
396 
400  public static final class MimeTypeCondition implements FileAttributeCondition {
401 
402  private static final long serialVersionUID = 1L;
403  private final String mimeType;
404 
410  public MimeTypeCondition(String mimeType) {
411  this.mimeType = mimeType;
412  }
413 
414  @Override
415  public boolean passes(AbstractFile file) {
416  return this.mimeType.equals(file.getMIMEType());
417  }
418 
424  public String getMimeType() {
425  return this.mimeType;
426  }
427 
428  }
429 
434  public static final class FileSizeCondition implements FileAttributeCondition {
435 
436  private static final long serialVersionUID = 1L;
437 
441  public static enum COMPARATOR {
442 
443  LESS_THAN("<"),
444  LESS_THAN_EQUAL("≤"),
445  EQUAL("="),
447  GREATER_THAN_EQUAL("≥");
448 
449  private String symbol;
450 
451  private COMPARATOR(String symbol) {
452  this.symbol = symbol;
453  }
454 
455  public static COMPARATOR fromSymbol(String symbol) {
456  switch (symbol) {
457  case "<=":
458  case "≤":
459  return LESS_THAN_EQUAL;
460  case "<":
461  return LESS_THAN;
462  case "==":
463  case "=":
464  return EQUAL;
465  case ">":
466  return GREATER_THAN;
467  case ">=":
468  case "≥":
469  return GREATER_THAN_EQUAL;
470  default:
471  throw new IllegalArgumentException("Invalid symbol");
472  }
473  }
474 
478  public String getSymbol() {
479  return symbol;
480  }
481  }
482 
486  public static enum SIZE_UNIT {
487 
488  BYTE(1, "Bytes"),
489  KILOBYTE(1024, "Kilobytes"),
490  MEGABYTE(1024 * 1024, "Megabytes"),
491  GIGABYTE(1024 * 1024 * 1024, "Gigabytes");
492  private long size;
493  private String name;
494 
495  private SIZE_UNIT(long size, String name) {
496  this.size = size;
497  this.name = name;
498  }
499 
500  public long getSize() {
501  return this.size;
502  }
503 
504  public static SIZE_UNIT fromName(String name) {
505  for (SIZE_UNIT unit : SIZE_UNIT.values()) {
506  if (unit.getName().equals(name)) {
507  return unit;
508  }
509  }
510  throw new IllegalArgumentException("Invalid name for size unit.");
511  }
512 
516  public String getName() {
517  return name;
518  }
519  }
520  private final COMPARATOR comparator;
521  private final SIZE_UNIT unit;
522  private final int sizeValue;
523 
524  public FileSizeCondition(COMPARATOR comparator, SIZE_UNIT unit, int sizeValue) {
525  this.comparator = comparator;
526  this.unit = unit;
527  this.sizeValue = sizeValue;
528  }
529 
536  return comparator;
537  }
538 
544  public SIZE_UNIT getUnit() {
545  return unit;
546  }
547 
553  public int getSizeValue() {
554  return sizeValue;
555  }
556 
557  @Override
558  public boolean passes(AbstractFile file) {
559  long fileSize = file.getSize();
560  long conditionSize = this.getUnit().getSize() * this.getSizeValue();
561  switch (this.getComparator()) {
562  case GREATER_THAN:
563  return fileSize > conditionSize;
564  case GREATER_THAN_EQUAL:
565  return fileSize >= conditionSize;
566  case LESS_THAN_EQUAL:
567  return fileSize <= conditionSize;
568  case LESS_THAN:
569  return fileSize < conditionSize;
570  default:
571  return fileSize == conditionSize;
572 
573  }
574  }
575 
576  }
577 
583  public static final class MetaTypeCondition implements FileAttributeCondition {
584 
585  private static final long serialVersionUID = 1L;
586 
587  public enum Type {
588 
592  ALL
593  }
594 
595  private final Type type;
596 
602  public MetaTypeCondition(Type type) {
603  this.type = type;
604  }
605 
606  @Override
607  public boolean passes(AbstractFile file) {
608  switch (this.type) {
609  case FILES:
610  return file.isFile();
611  case DIRECTORIES:
612  return file.getMetaType() == TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_DIR
613  || file.getMetaType() == TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_VIRT_DIR;
614  case FILES_AND_DIRECTORIES:
615  return file.getMetaType() == TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_REG
616  || file.getMetaType() == TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_DIR
617  || file.getMetaType() == TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_VIRT_DIR;
618  case ALL:
619  return true; //Effectively ignores the metatype condition when All is selected.
620  default:
621  return true;
622  }
623  }
624 
630  public Type getMetaType() {
631  return this.type;
632  }
633  }
634 
638  static interface TextCondition extends FileAttributeCondition {
639 
645  String getTextToMatch();
646 
654  boolean isRegex();
655 
663  boolean textMatches(String textToMatch);
664 
665  }
666 
671  private static abstract class AbstractTextCondition implements TextCondition {
672 
673  /*
674  * To ensure compatibility with existing serialized configuration
675  * settings, this class cannot have a 'serialVersionUID'.
676  */
677  private final TextMatcher textMatcher;
678 
684  AbstractTextCondition(String text, Boolean partialMatch) {
685  if (partialMatch) {
686  this.textMatcher = new FilesSet.Rule.CaseInsensitivePartialStringComparisionMatcher(text);
687  } else {
688  this.textMatcher = new FilesSet.Rule.CaseInsensitiveStringComparisionMatcher(text);
689  }
690  }
691 
697  AbstractTextCondition(Pattern regex) {
698  this.textMatcher = new FilesSet.Rule.RegexMatcher(regex);
699  }
700 
706  AbstractTextCondition(List<String> values) {
707  this.textMatcher = new FilesSet.Rule.CaseInsensitiveMultiValueStringComparisionMatcher(values);
708  }
709 
715  @Override
716  public String getTextToMatch() {
717  return this.textMatcher.getTextToMatch();
718  }
719 
727  @Override
728  public boolean isRegex() {
729  return this.textMatcher.isRegex();
730  }
731 
739  @Override
740  public boolean textMatches(String textToMatch) {
741  return this.textMatcher.textMatches(textToMatch);
742  }
743 
744  @Override
745  public abstract boolean passes(AbstractFile file);
746 
747  }
748 
754  public static final class ParentPathCondition extends AbstractTextCondition {
755 
756  private static final long serialVersionUID = 1L;
757 
763  public ParentPathCondition(String path) {
764  super(path, true);
765  }
766 
772  public ParentPathCondition(Pattern path) {
773  super(path);
774  }
775 
776  @Override
777  public boolean passes(AbstractFile file) {
778  return this.textMatches(file.getParentPath() + "/");
779  }
780 
781  }
782 
788  static interface FileNameCondition extends TextCondition {
789  }
790 
796  public static final class FullNameCondition extends AbstractTextCondition implements FileNameCondition {
797 
798  private static final long serialVersionUID = 1L;
799 
805  public FullNameCondition(String name) {
806  super(name, false);
807  }
808 
814  public FullNameCondition(Pattern name) {
815  super(name);
816  }
817 
818  @Override
819  public boolean passes(AbstractFile file) {
820  return this.textMatches(file.getName());
821  }
822 
823  }
824 
829  public static final class DateCondition implements FileAttributeCondition {
830 
831  /*
832  * To ensure compatibility with existing serialized configuration
833  * settings, this class cannot have a 'serialVersionUID'.
834  */
835  private final static long SECS_PER_DAY = 60 * 60 * 24;
836 
837  private int daysIncluded;
838 
845  public DateCondition(int days) {
846  daysIncluded = days;
847  }
848 
854  public int getDaysIncluded() {
855  return daysIncluded;
856  }
857 
858  @Override
859  public boolean passes(AbstractFile file) {
860  long dateThreshold = System.currentTimeMillis() / 1000 - daysIncluded * SECS_PER_DAY;
861  return file.getCrtime() > dateThreshold || file.getMtime() > dateThreshold;
862  }
863 
864  }
865 
871  public static final class ExtensionCondition extends AbstractTextCondition implements FileNameCondition {
872 
873  private static final long serialVersionUID = 1L;
874 
880  public ExtensionCondition(String extension) {
881  // If there is a leading ".", strip it since
882  // AbstractFile.getFileNameExtension() returns just the
883  // extension chars and not the dot.
884  super(normalize(extension), false);
885  }
886 
892  public ExtensionCondition(List<String> extensions) {
893  // If there is a leading "." in any list value, strip it since
894  // AbstractFile.getFileNameExtension() returns just the
895  // extension chars and not the dot.
896  super(normalize(extensions));
897  }
898 
905  public ExtensionCondition(Pattern extension) {
906  super(extension);
907  }
908 
909  @Override
910  public boolean passes(AbstractFile file) {
911  return this.textMatches(file.getNameExtension());
912  }
913 
921  private static List<String> normalize(List<String> extensions) {
922  List<String> values = new ArrayList<>(extensions);
923 
924  for (int i = 0; i < values.size(); i++) {
925  values.set(i, normalize(values.get(i)));
926  }
927 
928  return values;
929  }
930 
938  private static String normalize(String extension) {
939  return extension.startsWith(".") ? extension.substring(1) : extension;
940  }
941 
942  }
943 
948  private static interface TextMatcher extends Serializable {
949 
955  String getTextToMatch();
956 
964  boolean isRegex();
965 
973  boolean textMatches(String subject);
974 
975  }
976 
980  private static class CaseInsensitiveStringComparisionMatcher implements TextMatcher {
981 
982  private static final long serialVersionUID = 1L;
983  private final String textToMatch;
984 
991  CaseInsensitiveStringComparisionMatcher(String textToMatch) {
992  this.textToMatch = textToMatch;
993  }
994 
995  @Override
996  public String getTextToMatch() {
997  return this.textToMatch;
998  }
999 
1000  @Override
1001  public boolean isRegex() {
1002  return false;
1003  }
1004 
1005  @Override
1006  public boolean textMatches(String subject) {
1007  return subject.equalsIgnoreCase(textToMatch);
1008  }
1009 
1010  }
1011 
1016 
1017  private static final long serialVersionUID = 1L;
1018  private final String textToMatch;
1019  private final Pattern pattern;
1020 
1028  this.textToMatch = textToMatch;
1029  this.pattern = Pattern.compile(Pattern.quote(textToMatch), Pattern.CASE_INSENSITIVE);
1030  }
1031 
1032  @Override
1033  public String getTextToMatch() {
1034  return this.textToMatch;
1035  }
1036 
1037  @Override
1038  public boolean isRegex() {
1039  return false;
1040  }
1041 
1042  @Override
1043  public boolean textMatches(String subject) {
1044  return pattern.matcher(subject).find();
1045  }
1046  }
1047 
1053 
1054  private static final long serialVersionUID = 1L;
1055  private final List<String> valuesToMatch;
1056 
1064  CaseInsensitiveMultiValueStringComparisionMatcher(List<String> valuesToMatch) {
1065  this.valuesToMatch = valuesToMatch;
1066  }
1067 
1068  @Override
1069  public String getTextToMatch() {
1070  return String.join(",", this.valuesToMatch);
1071  }
1072 
1073  @Override
1074  public boolean isRegex() {
1075  return false;
1076  }
1077 
1078  @Override
1079  public boolean textMatches(String subject) {
1080  for (String value : valuesToMatch) {
1081  if (value.equalsIgnoreCase(subject)) {
1082  return true;
1083  }
1084  }
1085  return false;
1086  }
1087 
1088  }
1089 
1093  private static class RegexMatcher implements TextMatcher {
1094 
1095  private static final long serialVersionUID = 1L;
1096  private final Pattern regex;
1097 
1104  RegexMatcher(Pattern regex) {
1105  this.regex = regex;
1106  }
1107 
1108  @Override
1109  public String getTextToMatch() {
1110  return this.regex.pattern();
1111  }
1112 
1113  @Override
1114  public boolean isRegex() {
1115  return true;
1116  }
1117 
1118  @Override
1119  public boolean textMatches(String subject) {
1120  // A single match is sufficient.
1121  return this.regex.matcher(subject).find();
1122  }
1123 
1124  }
1125 
1126  }
1127 
1128 }
FileSizeCondition(COMPARATOR comparator, SIZE_UNIT unit, int sizeValue)
Definition: FilesSet.java:524
FilesSet(String name, String description, boolean ignoreKnownFiles, boolean ignoreUnallocatedSpace, Map< String, Rule > rules)
Definition: FilesSet.java:65
FilesSet(String name, String description, boolean ignoreKnownFiles, boolean ignoreUnallocatedSpace, Map< String, Rule > rules, boolean standardSet, int versionNumber)
Definition: FilesSet.java:86
Rule(String ruleName, FileNameCondition fileNameCondition, MetaTypeCondition metaTypeCondition, ParentPathCondition pathCondition, MimeTypeCondition mimeTypeCondition, FileSizeCondition fileSizeCondition, DateCondition dateCondition)
Definition: FilesSet.java:238
final List< FileAttributeCondition > conditions
Definition: FilesSet.java:224

Copyright © 2012-2021 Basis Technology. Generated on: Fri Aug 6 2021
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.