Autopsy 4.22.1
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 */
19package org.sleuthkit.autopsy.modules.interestingitems;
20
21import java.io.Serializable;
22import java.util.ArrayList;
23import java.util.Collections;
24import java.util.HashMap;
25import java.util.List;
26import java.util.Map;
27import java.util.Map.Entry;
28import java.util.UUID;
29import java.util.regex.Pattern;
30import org.openide.util.NbBundle;
31import org.openide.util.NbBundle.Messages;
32import org.sleuthkit.datamodel.AbstractFile;
33import org.sleuthkit.datamodel.TskData;
34
43public final class FilesSet implements Serializable {
44
45 private static final long serialVersionUID = 1L;
46 private final String name;
47 private final String description;
48 private final boolean ignoreKnownFiles;
49 private final boolean ignoreUnallocatedSpace;
50
51 private final boolean standardSet;
52 private final int versionNumber;
53
54 private final Map<String, Rule> rules;
55
56 // NOTE: these fields are derived from 'rules' which may happen at runtime
57 // due to deserialization of older FilesSet objects before inclusive and
58 // exclusive rules existed.
59 private Map<String, Rule> inclusiveRules;
60 private Map<String, Rule> exclusiveRules;
61
74 public FilesSet(String name, String description, boolean ignoreKnownFiles, boolean ignoreUnallocatedSpace, Map<String, Rule> rules) {
76 }
77
95 public FilesSet(String name, String description, boolean ignoreKnownFiles, boolean ignoreUnallocatedSpace, Map<String, Rule> rules,
96 boolean standardSet, int versionNumber) {
97 if ((name == null) || (name.isEmpty())) {
98 throw new IllegalArgumentException("Interesting files set name cannot be null or empty");
99 }
100
101 if (versionNumber < 0) {
102 throw new IllegalArgumentException("version number must be >= 0");
103 }
104
105 this.standardSet = standardSet;
106 this.versionNumber = versionNumber;
107
108 this.name = name;
109 this.description = (description != null ? description : "");
110 this.ignoreKnownFiles = ignoreKnownFiles;
111 this.ignoreUnallocatedSpace = ignoreUnallocatedSpace;
112 this.rules = rules == null ? Collections.emptyMap() : new HashMap<>(rules);
113
115 }
116
121 Map<String, Rule> inclusiveRules = new HashMap<>();
122 Map<String, Rule> exclusiveRules = new HashMap<>();
123 if (this.rules != null) {
124 for (Entry<String, Rule> ruleEntry : this.rules.entrySet()) {
125 if (ruleEntry.getValue().isExclusive()) {
126 exclusiveRules.put(ruleEntry.getKey(), ruleEntry.getValue());
127 } else {
128 inclusiveRules.put(ruleEntry.getKey(), ruleEntry.getValue());
129 }
130 }
131 }
132 this.inclusiveRules = inclusiveRules;
133 this.exclusiveRules = exclusiveRules;
134 }
135
140 boolean isStandardSet() {
141 return standardSet;
142 }
143
148 int getVersionNumber() {
149 return versionNumber;
150 }
151
157 public String getName() {
158 return this.name;
159 }
160
166 public String getDescription() {
167 return this.description;
168 }
169
179 public boolean ignoresKnownFiles() {
180 return this.ignoreKnownFiles;
181 }
182
189 public boolean ingoresUnallocatedSpace() {
190 return this.ignoreUnallocatedSpace;
191 }
192
198 public Map<String, Rule> getRules() {
199 return new HashMap<>(this.rules);
200 }
201
202
211 @Messages({
212 "FileSet_fileIsMemberOf_noInclusiveRules_ruleName=Not Excluded"
213 })
214 public String fileIsMemberOf(AbstractFile file) {
215 if ((this.ignoreKnownFiles) && (file.getKnown() == TskData.FileKnown.KNOWN)) {
216 return null;
217 }
218
219 if ((this.ignoreUnallocatedSpace)
220 && (file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS)
221 || file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.SLACK)
222 || file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS))) {
223 return null;
224 }
225
226 if (inclusiveRules == null || exclusiveRules == null) {
228 }
229
230
231 String ruleName;
232 if (inclusiveRules.isEmpty()) {
233 // in the event there are no rules, return null for no match
234 if (exclusiveRules.isEmpty()) {
235 return null;
236 // in the event there are exclusion rules, rely on those
237 } else {
238 ruleName = Bundle.FileSet_fileIsMemberOf_noInclusiveRules_ruleName();
239 }
240
241 } else {
242 // if there are inclusive rules, at least one should be matched
243 ruleName = null;
244 for (Rule rule : inclusiveRules.values()) {
245 if (rule.isSatisfied(file)) {
246 ruleName = rule.getName();
247 break;
248 }
249 }
250 }
251
252 for (Rule rule : exclusiveRules.values()) {
253 if (rule.isSatisfied(file)) {
254 return null;
255 }
256 }
257
258 return ruleName;
259 }
260
261 @Override
262 public String toString() {
263 // This override is designed to provide a display name for use with
264 // javax.swing.DefaultListModel<E>.
265 return this.name;
266 }
267
272 public final static class Rule implements Serializable {
273
274 private static final long serialVersionUID = 1L;
275 private final String uuid;
276 private final String ruleName;
277 private final Boolean exclusive;
284 private final List<FileAttributeCondition> conditions = new ArrayList<>();
285
303 Boolean exclusive) {
304
305 // since ruleName is optional, ruleUUID can be used to uniquely identify a rule.
306 this.uuid = UUID.randomUUID().toString();
307 if (metaTypeCondition == null) {
308 throw new IllegalArgumentException("Interesting files set rule meta-type condition cannot be null");
309 }
310
311 this.ruleName = ruleName;
312
313 /*
314 * The rules are evaluated in the order added. MetaType check is
315 * fastest, so do it first
316 */
317 this.metaTypeCondition = metaTypeCondition;
318 this.conditions.add(this.metaTypeCondition);
319
320 this.fileSizeCondition = fileSizeCondition;
321 if (this.fileSizeCondition != null) {
322 this.conditions.add(this.fileSizeCondition);
323 }
324
325 this.fileNameCondition = fileNameCondition;
326 if (this.fileNameCondition != null) {
327 this.conditions.add(fileNameCondition);
328 }
329
330 this.mimeTypeCondition = mimeTypeCondition;
331 if (this.mimeTypeCondition != null) {
332 this.conditions.add(mimeTypeCondition);
333 }
334
335 this.pathCondition = pathCondition;
336 if (this.pathCondition != null) {
337 this.conditions.add(this.pathCondition);
338 }
339 this.dateCondition = dateCondition;
340 if (this.dateCondition != null) {
341 this.conditions.add(this.dateCondition);
342 }
343
344 this.exclusive = exclusive;
345 }
346
352 public String getName() {
353 return ruleName;
354 }
355
362 return this.fileNameCondition;
363 }
364
371 return this.metaTypeCondition;
372 }
373
380 return this.pathCondition;
381 }
382
384 return this.dateCondition;
385 }
386
392 public boolean isExclusive() {
393 return exclusive != null && exclusive == true;
394 }
395
403 public boolean isSatisfied(AbstractFile file) {
404 for (FileAttributeCondition condition : conditions) {
405 if (!condition.passes(file)) {
406 return false;
407 }
408 }
409 return true;
410 }
411
412 @NbBundle.Messages({
413 "# {0} - daysIncluded",
414 "FilesSet.rule.dateRule.toString=(modified within {0} day(s))"
415 })
416 @Override
417 public String toString() {
418 // This override is designed to provide a display name for use with
419 // javax.swing.DefaultListModel<E>.
420 if (fileNameCondition != null) {
421 return this.ruleName + " (" + fileNameCondition.getTextToMatch() + ")";
422 } else if (this.pathCondition != null) {
423 return this.ruleName + " (" + pathCondition.getTextToMatch() + ")";
424 } else if (this.mimeTypeCondition != null) {
425 return this.ruleName + " (" + mimeTypeCondition.getMimeType() + ")";
426 } else if (this.fileSizeCondition != null) {
427 return this.ruleName + " (" + fileSizeCondition.getComparator().getSymbol() + " " + fileSizeCondition.getSizeValue()
428 + " " + fileSizeCondition.getUnit().getName() + ")";
429 } else if (this.dateCondition != null) {
430 return this.ruleName + Bundle.FilesSet_rule_dateRule_toString(dateCondition.getDaysIncluded());
431 } else {
432 return this.ruleName + " ()";
433 }
434
435 }
436
440 public String getUuid() {
441 return this.uuid;
442 }
443
450
457
462 static interface FileAttributeCondition extends Serializable {
463
471 boolean passes(AbstractFile file);
472 }
473
477 public static final class MimeTypeCondition implements FileAttributeCondition {
478
479 private static final long serialVersionUID = 1L;
480 private final String mimeType;
481
488 this.mimeType = mimeType;
489 }
490
491 @Override
492 public boolean passes(AbstractFile file) {
493 return this.mimeType.equals(file.getMIMEType());
494 }
495
501 public String getMimeType() {
502 return this.mimeType;
503 }
504
505 }
506
511 public static final class FileSizeCondition implements FileAttributeCondition {
512
513 private static final long serialVersionUID = 1L;
514
518 public static enum COMPARATOR {
519
521 LESS_THAN_EQUAL("≤"),
522 EQUAL("="),
525
526 private String symbol;
527
528 private COMPARATOR(String symbol) {
529 this.symbol = symbol;
530 }
531
532 public static COMPARATOR fromSymbol(String symbol) {
533 switch (symbol) {
534 case "<=":
535 case "≤":
536 return LESS_THAN_EQUAL;
537 case "<":
538 return LESS_THAN;
539 case "==":
540 case "=":
541 return EQUAL;
542 case ">":
543 return GREATER_THAN;
544 case ">=":
545 case "≥":
546 return GREATER_THAN_EQUAL;
547 default:
548 throw new IllegalArgumentException("Invalid symbol");
549 }
550 }
551
555 public String getSymbol() {
556 return symbol;
557 }
558 }
559
563 public static enum SIZE_UNIT {
564
565 BYTE(1, "Bytes"),
566 KILOBYTE(1024, "Kilobytes"),
567 MEGABYTE(1024 * 1024, "Megabytes"),
568 GIGABYTE(1024 * 1024 * 1024, "Gigabytes");
569 private long size;
570 private String name;
571
572 private SIZE_UNIT(long size, String name) {
573 this.size = size;
574 this.name = name;
575 }
576
577 public long getSize() {
578 return this.size;
579 }
580
581 public static SIZE_UNIT fromName(String name) {
582 for (SIZE_UNIT unit : SIZE_UNIT.values()) {
583 if (unit.getName().equals(name)) {
584 return unit;
585 }
586 }
587 throw new IllegalArgumentException("Invalid name for size unit.");
588 }
589
593 public String getName() {
594 return name;
595 }
596 }
597 private final COMPARATOR comparator;
598 private final SIZE_UNIT unit;
599 private final int sizeValue;
600
602 this.comparator = comparator;
603 this.unit = unit;
604 this.sizeValue = sizeValue;
605 }
606
613 return comparator;
614 }
615
622 return unit;
623 }
624
630 public int getSizeValue() {
631 return sizeValue;
632 }
633
634 @Override
635 public boolean passes(AbstractFile file) {
636 long fileSize = file.getSize();
637 long conditionSize = this.getUnit().getSize() * this.getSizeValue();
638 switch (this.getComparator()) {
639 case GREATER_THAN:
640 return fileSize > conditionSize;
641 case GREATER_THAN_EQUAL:
642 return fileSize >= conditionSize;
643 case LESS_THAN_EQUAL:
644 return fileSize <= conditionSize;
645 case LESS_THAN:
646 return fileSize < conditionSize;
647 default:
648 return fileSize == conditionSize;
649
650 }
651 }
652
653 }
654
660 public static final class MetaTypeCondition implements FileAttributeCondition {
661
662 private static final long serialVersionUID = 1L;
663
671
672 private final Type type;
673
680 this.type = type;
681 }
682
683 @Override
684 public boolean passes(AbstractFile file) {
685 switch (this.type) {
686 case FILES:
687 return file.isFile();
688 case DIRECTORIES:
689 return file.getMetaType() == TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_DIR
690 || file.getMetaType() == TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_VIRT_DIR;
691 case FILES_AND_DIRECTORIES:
692 return file.getMetaType() == TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_REG
693 || file.getMetaType() == TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_DIR
694 || file.getMetaType() == TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_VIRT_DIR;
695 case ALL:
696 return true; //Effectively ignores the metatype condition when All is selected.
697 default:
698 return true;
699 }
700 }
701
707 public Type getMetaType() {
708 return this.type;
709 }
710 }
711
715 static interface TextCondition extends FileAttributeCondition {
716
723
731 boolean isRegex();
732
740 boolean textMatches(String textToMatch);
741
742 }
743
748 private static abstract class AbstractTextCondition implements TextCondition {
749
750 /*
751 * To ensure compatibility with existing serialized configuration
752 * settings, this class cannot have a 'serialVersionUID'.
753 */
755
761 AbstractTextCondition(String text, Boolean partialMatch) {
762 if (partialMatch) {
763 this.textMatcher = new FilesSet.Rule.CaseInsensitivePartialStringComparisionMatcher(text);
764 } else {
765 this.textMatcher = new FilesSet.Rule.CaseInsensitiveStringComparisionMatcher(text);
766 }
767 }
768
774 AbstractTextCondition(Pattern regex) {
775 this.textMatcher = new FilesSet.Rule.RegexMatcher(regex);
776 }
777
783 AbstractTextCondition(List<String> values) {
784 this.textMatcher = new FilesSet.Rule.CaseInsensitiveMultiValueStringComparisionMatcher(values);
785 }
786
792 @Override
793 public String getTextToMatch() {
794 return this.textMatcher.getTextToMatch();
795 }
796
804 @Override
805 public boolean isRegex() {
806 return this.textMatcher.isRegex();
807 }
808
816 @Override
817 public boolean textMatches(String textToMatch) {
818 return this.textMatcher.textMatches(textToMatch);
819 }
820
821 @Override
822 public abstract boolean passes(AbstractFile file);
823
824 }
825
831 public static final class ParentPathCondition extends AbstractTextCondition {
832
833 private static final long serialVersionUID = 1L;
834
840 public ParentPathCondition(String path) {
841 super(path, true);
842 }
843
849 public ParentPathCondition(Pattern path) {
850 super(path);
851 }
852
853 @Override
854 public boolean passes(AbstractFile file) {
855 return this.textMatches(file.getParentPath() + "/");
856 }
857
858 }
859
865 static interface FileNameCondition extends TextCondition {
866 }
867
873 public static final class FullNameCondition extends AbstractTextCondition implements FileNameCondition {
874
875 private static final long serialVersionUID = 1L;
876
882 public FullNameCondition(String name) {
883 super(name, false);
884 }
885
891 public FullNameCondition(Pattern name) {
892 super(name);
893 }
894
895 @Override
896 public boolean passes(AbstractFile file) {
897 return this.textMatches(file.getName());
898 }
899
900 }
901
906 public static final class DateCondition implements FileAttributeCondition {
907
908 /*
909 * To ensure compatibility with existing serialized configuration
910 * settings, this class cannot have a 'serialVersionUID'.
911 */
912 private final static long SECS_PER_DAY = 60 * 60 * 24;
913
914 private int daysIncluded;
915
922 public DateCondition(int days) {
923 daysIncluded = days;
924 }
925
931 public int getDaysIncluded() {
932 return daysIncluded;
933 }
934
935 @Override
936 public boolean passes(AbstractFile file) {
937 long dateThreshold = System.currentTimeMillis() / 1000 - daysIncluded * SECS_PER_DAY;
938 return file.getCrtime() > dateThreshold || file.getMtime() > dateThreshold;
939 }
940
941 }
942
948 public static final class ExtensionCondition extends AbstractTextCondition implements FileNameCondition {
949
950 private static final long serialVersionUID = 1L;
951
957 public ExtensionCondition(String extension) {
958 // If there is a leading ".", strip it since
959 // AbstractFile.getFileNameExtension() returns just the
960 // extension chars and not the dot.
961 super(normalize(extension), false);
962 }
963
969 public ExtensionCondition(List<String> extensions) {
970 // If there is a leading "." in any list value, strip it since
971 // AbstractFile.getFileNameExtension() returns just the
972 // extension chars and not the dot.
973 super(normalize(extensions));
974 }
975
982 public ExtensionCondition(Pattern extension) {
983 super(extension);
984 }
985
986 @Override
987 public boolean passes(AbstractFile file) {
988 return this.textMatches(file.getNameExtension());
989 }
990
998 private static List<String> normalize(List<String> extensions) {
999 List<String> values = new ArrayList<>(extensions);
1000
1001 for (int i = 0; i < values.size(); i++) {
1002 values.set(i, normalize(values.get(i)));
1003 }
1004
1005 return values;
1006 }
1007
1015 private static String normalize(String extension) {
1016 return extension.startsWith(".") ? extension.substring(1) : extension;
1017 }
1018
1019 }
1020
1025 private static interface TextMatcher extends Serializable {
1026
1033
1041 boolean isRegex();
1042
1050 boolean textMatches(String subject);
1051
1052 }
1053
1057 private static class CaseInsensitiveStringComparisionMatcher implements TextMatcher {
1058
1059 private static final long serialVersionUID = 1L;
1060 private final String textToMatch;
1061
1068 CaseInsensitiveStringComparisionMatcher(String textToMatch) {
1069 this.textToMatch = textToMatch;
1070 }
1071
1072 @Override
1073 public String getTextToMatch() {
1074 return this.textToMatch;
1075 }
1076
1077 @Override
1078 public boolean isRegex() {
1079 return false;
1080 }
1081
1082 @Override
1083 public boolean textMatches(String subject) {
1084 return subject.equalsIgnoreCase(textToMatch);
1085 }
1086
1087 }
1088
1092 private static class CaseInsensitivePartialStringComparisionMatcher implements TextMatcher {
1093
1094 private static final long serialVersionUID = 1L;
1095 private final String textToMatch;
1096 private final Pattern pattern;
1097
1104 CaseInsensitivePartialStringComparisionMatcher(String textToMatch) {
1105 this.textToMatch = textToMatch;
1106 this.pattern = Pattern.compile(Pattern.quote(textToMatch), Pattern.CASE_INSENSITIVE);
1107 }
1108
1109 @Override
1110 public String getTextToMatch() {
1111 return this.textToMatch;
1112 }
1113
1114 @Override
1115 public boolean isRegex() {
1116 return false;
1117 }
1118
1119 @Override
1120 public boolean textMatches(String subject) {
1121 return pattern.matcher(subject).find();
1122 }
1123 }
1124
1129 private static class CaseInsensitiveMultiValueStringComparisionMatcher implements TextMatcher {
1130
1131 private static final long serialVersionUID = 1L;
1132 private final List<String> valuesToMatch;
1133
1141 CaseInsensitiveMultiValueStringComparisionMatcher(List<String> valuesToMatch) {
1142 this.valuesToMatch = valuesToMatch;
1143 }
1144
1145 @Override
1146 public String getTextToMatch() {
1147 return String.join(",", this.valuesToMatch);
1148 }
1149
1150 @Override
1151 public boolean isRegex() {
1152 return false;
1153 }
1154
1155 @Override
1156 public boolean textMatches(String subject) {
1157 for (String value : valuesToMatch) {
1158 if (value.equalsIgnoreCase(subject)) {
1159 return true;
1160 }
1161 }
1162 return false;
1163 }
1164
1165 }
1166
1170 private static class RegexMatcher implements TextMatcher {
1171
1172 private static final long serialVersionUID = 1L;
1173 private final Pattern regex;
1174
1181 RegexMatcher(Pattern regex) {
1182 this.regex = regex;
1183 }
1184
1185 @Override
1186 public String getTextToMatch() {
1187 return this.regex.pattern();
1188 }
1189
1190 @Override
1191 public boolean isRegex() {
1192 return true;
1193 }
1194
1195 @Override
1196 public boolean textMatches(String subject) {
1197 // A single match is sufficient.
1198 return this.regex.matcher(subject).find();
1199 }
1200
1201 }
1202
1203 }
1204
1205}
FileSizeCondition(COMPARATOR comparator, SIZE_UNIT unit, int sizeValue)
Rule(String ruleName, FileNameCondition fileNameCondition, MetaTypeCondition metaTypeCondition, ParentPathCondition pathCondition, MimeTypeCondition mimeTypeCondition, FileSizeCondition fileSizeCondition, DateCondition dateCondition, Boolean exclusive)
FilesSet(String name, String description, boolean ignoreKnownFiles, boolean ignoreUnallocatedSpace, Map< String, Rule > rules, boolean standardSet, int versionNumber)
Definition FilesSet.java:95
FilesSet(String name, String description, boolean ignoreKnownFiles, boolean ignoreUnallocatedSpace, Map< String, Rule > rules)
Definition FilesSet.java:74

Copyright © 2012-2024 Sleuth Kit Labs. Generated on:
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.