Autopsy  4.5.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  private final Map<String, Rule> rules = new HashMap<>();
48 
61  public FilesSet(String name, String description, boolean ignoreKnownFiles, boolean ignoreUnallocatedSpace, Map<String, Rule> rules) {
62  if ((name == null) || (name.isEmpty())) {
63  throw new IllegalArgumentException("Interesting files set name cannot be null or empty");
64  }
65  this.name = name;
66  this.description = (description != null ? description : "");
67  this.ignoreKnownFiles = ignoreKnownFiles;
68  this.ignoreUnallocatedSpace = ignoreUnallocatedSpace;
69  if (rules != null) {
70  this.rules.putAll(rules);
71  }
72  }
73 
79  public String getName() {
80  return this.name;
81  }
82 
88  public String getDescription() {
89  return this.description;
90  }
91 
101  boolean ignoresKnownFiles() {
102  return this.ignoreKnownFiles;
103  }
104 
111  public boolean ingoresUnallocatedSpace() {
112  return this.ignoreUnallocatedSpace;
113  }
114 
120  Map<String, Rule> getRules() {
121  return new HashMap<>(this.rules);
122  }
123 
132  public String fileIsMemberOf(AbstractFile file) {
133  if ((this.ignoreKnownFiles) && (file.getKnown() == TskData.FileKnown.KNOWN)) {
134  return null;
135  }
136 
137  if ((this.ignoreUnallocatedSpace)
138  && (file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS)
139  || file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.SLACK)
140  || file.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS))) {
141  return null;
142  }
143 
144  for (Rule rule : rules.values()) {
145  if (rule.isSatisfied(file)) {
146  return rule.getName();
147  }
148  }
149  return null;
150  }
151 
152  @Override
153  public String toString() {
154  // This override is designed to provide a display name for use with
155  // javax.swing.DefaultListModel<E>.
156  return this.name;
157  }
158 
163  static class Rule implements Serializable {
164 
165  private static final long serialVersionUID = 1L;
166  private final String uuid;
167  private final String ruleName;
168  private final FileNameCondition fileNameCondition;
169  private final MetaTypeCondition metaTypeCondition;
170  private final ParentPathCondition pathCondition;
171  private final MimeTypeCondition mimeTypeCondition;
172  private final FileSizeCondition fileSizeCondition;
173  private final DateCondition dateCondition;
174  private final List<FileAttributeCondition> conditions = new ArrayList<>();
175 
188  Rule(String ruleName, FileNameCondition fileNameCondition, MetaTypeCondition metaTypeCondition, ParentPathCondition pathCondition, MimeTypeCondition mimeTypeCondition, FileSizeCondition fileSizeCondition, DateCondition dateCondition) {
189  // since ruleName is optional, ruleUUID can be used to uniquely identify a rule.
190  this.uuid = UUID.randomUUID().toString();
191  if (metaTypeCondition == null) {
192  throw new IllegalArgumentException("Interesting files set rule meta-type condition cannot be null");
193  }
194 
195  this.ruleName = ruleName;
196 
197  /*
198  * The rules are evaluated in the order added. MetaType check is
199  * fastest, so do it first
200  */
201  this.metaTypeCondition = metaTypeCondition;
202  this.conditions.add(this.metaTypeCondition);
203 
204  this.fileSizeCondition = fileSizeCondition;
205  if (this.fileSizeCondition != null) {
206  this.conditions.add(this.fileSizeCondition);
207  }
208 
209  this.fileNameCondition = fileNameCondition;
210  if (this.fileNameCondition != null) {
211  this.conditions.add(fileNameCondition);
212  }
213 
214  this.mimeTypeCondition = mimeTypeCondition;
215  if (this.mimeTypeCondition != null) {
216  this.conditions.add(mimeTypeCondition);
217  }
218 
219  this.pathCondition = pathCondition;
220  if (this.pathCondition != null) {
221  this.conditions.add(this.pathCondition);
222  }
223  this.dateCondition = dateCondition;
224  if (this.dateCondition != null) {
225  this.conditions.add(this.dateCondition);
226  }
227  }
228 
234  String getName() {
235  return ruleName;
236  }
237 
243  FileNameCondition getFileNameCondition() {
244  return this.fileNameCondition;
245  }
246 
252  MetaTypeCondition getMetaTypeCondition() {
253  return this.metaTypeCondition;
254  }
255 
261  ParentPathCondition getPathCondition() {
262  return this.pathCondition;
263  }
264 
265  DateCondition getDateCondition() {
266  return this.dateCondition;
267  }
268 
276  boolean isSatisfied(AbstractFile file) {
277  for (FileAttributeCondition condition : conditions) {
278  if (!condition.passes(file)) {
279  return false;
280  }
281  }
282  return true;
283  }
284 
285  @NbBundle.Messages({
286  "# {0} - daysIncluded",
287  "FilesSet.rule.dateRule.toString=(modified within {0} day(s))"
288  })
289  @Override
290  public String toString() {
291  // This override is designed to provide a display name for use with
292  // javax.swing.DefaultListModel<E>.
293  if (fileNameCondition != null) {
294  return this.ruleName + " (" + fileNameCondition.getTextToMatch() + ")";
295  } else if (this.pathCondition != null) {
296  return this.ruleName + " (" + pathCondition.getTextToMatch() + ")";
297  } else if (this.mimeTypeCondition != null) {
298  return this.ruleName + " (" + mimeTypeCondition.getMimeType() + ")";
299  } else if (this.fileSizeCondition != null) {
300  return this.ruleName + " (" + fileSizeCondition.getComparator().getSymbol() + " " + fileSizeCondition.getSizeValue()
301  + " " + fileSizeCondition.getUnit().getName() + ")";
302  } else if (this.dateCondition != null) {
303  return this.ruleName + Bundle.FilesSet_rule_dateRule_toString(dateCondition.getDaysIncluded());
304  } else {
305  return this.ruleName + " ()";
306  }
307 
308  }
309 
313  public String getUuid() {
314  return this.uuid;
315  }
316 
320  MimeTypeCondition getMimeTypeCondition() {
321  return mimeTypeCondition;
322  }
323 
327  FileSizeCondition getFileSizeCondition() {
328  return fileSizeCondition;
329  }
330 
335  static interface FileAttributeCondition extends Serializable {
336 
344  boolean passes(AbstractFile file);
345  }
346 
350  static final class MimeTypeCondition implements FileAttributeCondition {
351 
352  private static final long serialVersionUID = 1L;
353  private final String mimeType;
354 
360  MimeTypeCondition(String mimeType) {
361  this.mimeType = mimeType;
362  }
363 
364  @Override
365  public boolean passes(AbstractFile file) {
366  return this.mimeType.equals(file.getMIMEType());
367  }
368 
374  String getMimeType() {
375  return this.mimeType;
376  }
377 
378  }
379 
384  static final class FileSizeCondition implements FileAttributeCondition {
385 
386  private static final long serialVersionUID = 1L;
387 
391  static enum COMPARATOR {
392 
393  LESS_THAN("<"),
394  LESS_THAN_EQUAL("≤"),
395  EQUAL("="),
396  GREATER_THAN(">"),
397  GREATER_THAN_EQUAL("≥");
398 
399  private String symbol;
400 
401  COMPARATOR(String symbol) {
402  this.symbol = symbol;
403  }
404 
405  public static COMPARATOR fromSymbol(String symbol) {
406  if (symbol.equals("<=") || symbol.equals("≤")) {
407  return LESS_THAN_EQUAL;
408  } else if (symbol.equals("<")) {
409  return LESS_THAN;
410  } else if (symbol.equals("==") || symbol.equals("=")) {
411  return EQUAL;
412  } else if (symbol.equals(">")) {
413  return GREATER_THAN;
414  } else if (symbol.equals(">=") || symbol.equals("≥")) {
415  return GREATER_THAN_EQUAL;
416  } else {
417  throw new IllegalArgumentException("Invalid symbol");
418  }
419  }
420 
424  public String getSymbol() {
425  return symbol;
426  }
427  }
428 
432  static enum SIZE_UNIT {
433 
434  BYTE(1, "Bytes"),
435  KILOBYTE(1024, "Kilobytes"),
436  MEGABYTE(1024 * 1024, "Megabytes"),
437  GIGABYTE(1024 * 1024 * 1024, "Gigabytes");
438  private long size;
439  private String name;
440 
441  private SIZE_UNIT(long size, String name) {
442  this.size = size;
443  this.name = name;
444  }
445 
446  public long getSize() {
447  return this.size;
448  }
449 
450  public static SIZE_UNIT fromName(String name) {
451  for (SIZE_UNIT unit : SIZE_UNIT.values()) {
452  if (unit.getName().equals(name)) {
453  return unit;
454  }
455  }
456  throw new IllegalArgumentException("Invalid name for size unit.");
457  }
458 
462  public String getName() {
463  return name;
464  }
465  }
466  private final COMPARATOR comparator;
467  private final SIZE_UNIT unit;
468  private final int sizeValue;
469 
470  FileSizeCondition(COMPARATOR comparator, SIZE_UNIT unit, int sizeValue) {
471  this.comparator = comparator;
472  this.unit = unit;
473  this.sizeValue = sizeValue;
474  }
475 
481  COMPARATOR getComparator() {
482  return comparator;
483  }
484 
490  SIZE_UNIT getUnit() {
491  return unit;
492  }
493 
499  int getSizeValue() {
500  return sizeValue;
501  }
502 
503  @Override
504  public boolean passes(AbstractFile file) {
505  long fileSize = file.getSize();
506  long conditionSize = this.getUnit().getSize() * this.getSizeValue();
507  switch (this.getComparator()) {
508  case GREATER_THAN:
509  return fileSize > conditionSize;
510  case GREATER_THAN_EQUAL:
511  return fileSize >= conditionSize;
512  case LESS_THAN_EQUAL:
513  return fileSize <= conditionSize;
514  case LESS_THAN:
515  return fileSize < conditionSize;
516  default:
517  return fileSize == conditionSize;
518 
519  }
520  }
521 
522  }
523 
529  static final class MetaTypeCondition implements FileAttributeCondition {
530 
531  private static final long serialVersionUID = 1L;
532 
533  enum Type {
534 
535  FILES,
536  DIRECTORIES,
537  FILES_AND_DIRECTORIES,
538  ALL
539  }
540 
541  private final Type type;
542 
548  MetaTypeCondition(Type type) {
549  this.type = type;
550  }
551 
552  @Override
553  public boolean passes(AbstractFile file) {
554  switch (this.type) {
555  case FILES:
556  return file.isFile();
557  case DIRECTORIES:
558  return file.getMetaType() == TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_DIR
559  || file.getMetaType() == TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_VIRT_DIR;
560  case FILES_AND_DIRECTORIES:
561  return file.getMetaType() == TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_REG
562  || file.getMetaType() == TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_DIR
563  || file.getMetaType() == TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_VIRT_DIR;
564  case ALL:
565  return true; //Effectively ignores the metatype condition when All is selected.
566  default:
567  return true;
568  }
569  }
570 
576  Type getMetaType() {
577  return this.type;
578  }
579  }
580 
584  static interface TextCondition extends FileAttributeCondition {
585 
591  String getTextToMatch();
592 
600  boolean isRegex();
601 
609  boolean textMatches(String textToMatch);
610 
611  }
612 
617  private static abstract class AbstractTextCondition implements TextCondition {
618 
619  private final TextMatcher textMatcher;
620 
626  AbstractTextCondition(String text, Boolean partialMatch) {
627  if (partialMatch) {
628  this.textMatcher = new FilesSet.Rule.CaseInsensitivePartialStringComparisionMatcher(text);
629  } else {
630  this.textMatcher = new FilesSet.Rule.CaseInsensitiveStringComparisionMatcher(text);
631  }
632  }
633 
639  AbstractTextCondition(Pattern regex) {
640  this.textMatcher = new FilesSet.Rule.RegexMatcher(regex);
641  }
642 
648  @Override
649  public String getTextToMatch() {
650  return this.textMatcher.getTextToMatch();
651  }
652 
660  @Override
661  public boolean isRegex() {
662  return this.textMatcher.isRegex();
663  }
664 
672  @Override
673  public boolean textMatches(String textToMatch) {
674  return this.textMatcher.textMatches(textToMatch);
675  }
676 
677  @Override
678  public abstract boolean passes(AbstractFile file);
679 
680  }
681 
687  static final class ParentPathCondition extends AbstractTextCondition {
688 
689  private static final long serialVersionUID = 1L;
690 
696  ParentPathCondition(String path) {
697  super(path, true);
698  }
699 
705  ParentPathCondition(Pattern path) {
706  super(path);
707  }
708 
709  @Override
710  public boolean passes(AbstractFile file) {
711  return this.textMatches(file.getParentPath() + "/");
712  }
713 
714  }
715 
721  static interface FileNameCondition extends TextCondition {
722  }
723 
729  static final class FullNameCondition extends AbstractTextCondition implements FileNameCondition {
730 
731  private static final long serialVersionUID = 1L;
732 
738  FullNameCondition(String name) {
739  super(name, false);
740  }
741 
747  FullNameCondition(Pattern name) {
748  super(name);
749  }
750 
751  @Override
752  public boolean passes(AbstractFile file) {
753  return this.textMatches(file.getName());
754  }
755 
756  }
757 
762  static final class DateCondition implements FileAttributeCondition {
763 
764  private final static long SECS_PER_DAY = 60 * 60 * 24;
765 
766  private int daysIncluded;
767 
774  DateCondition(int days) {
775  daysIncluded = days;
776  }
777 
783  int getDaysIncluded() {
784  return daysIncluded;
785  }
786 
787  @Override
788  public boolean passes(AbstractFile file) {
789  long dateThreshold = System.currentTimeMillis() / 1000 - daysIncluded * SECS_PER_DAY;
790  if (file.getCrtime() > dateThreshold || file.getMtime() > dateThreshold) {
791  return true;
792  }
793  return false;
794  }
795 
796  }
797 
803  static final class ExtensionCondition extends AbstractTextCondition implements FileNameCondition {
804 
805  private static final long serialVersionUID = 1L;
806 
812  ExtensionCondition(String extension) {
813  // If there is a leading ".", strip it since
814  // AbstractFile.getFileNameExtension() returns just the
815  // extension chars and not the dot.
816  super(extension.startsWith(".") ? extension.substring(1) : extension, false);
817  }
818 
825  ExtensionCondition(Pattern extension) {
826  super(extension);
827  }
828 
829  @Override
830  public boolean passes(AbstractFile file) {
831  return this.textMatches(file.getNameExtension());
832  }
833 
834  }
835 
840  private static interface TextMatcher extends Serializable {
841 
847  String getTextToMatch();
848 
856  boolean isRegex();
857 
865  boolean textMatches(String subject);
866 
867  }
868 
872  private static class CaseInsensitiveStringComparisionMatcher implements TextMatcher {
873 
874  private static final long serialVersionUID = 1L;
875  private final String textToMatch;
876 
883  CaseInsensitiveStringComparisionMatcher(String textToMatch) {
884  this.textToMatch = textToMatch;
885  }
886 
887  @Override
888  public String getTextToMatch() {
889  return this.textToMatch;
890  }
891 
892  @Override
893  public boolean isRegex() {
894  return false;
895  }
896 
897  @Override
898  public boolean textMatches(String subject) {
899  return subject.equalsIgnoreCase(textToMatch);
900  }
901 
902  }
903 
908 
909  private static final long serialVersionUID = 1L;
910  private final String textToMatch;
911  private final Pattern pattern;
912 
920  this.textToMatch = textToMatch;
921  this.pattern = Pattern.compile(Pattern.quote(textToMatch), Pattern.CASE_INSENSITIVE);
922  }
923 
924  @Override
925  public String getTextToMatch() {
926  return this.textToMatch;
927  }
928 
929  @Override
930  public boolean isRegex() {
931  return false;
932  }
933 
934  @Override
935  public boolean textMatches(String subject) {
936  return pattern.matcher(subject).find();
937  }
938  }
939 
943  private static class RegexMatcher implements TextMatcher {
944 
945  private static final long serialVersionUID = 1L;
946  private final Pattern regex;
947 
954  RegexMatcher(Pattern regex) {
955  this.regex = regex;
956  }
957 
958  @Override
959  public String getTextToMatch() {
960  return this.regex.pattern();
961  }
962 
963  @Override
964  public boolean isRegex() {
965  return true;
966  }
967 
968  @Override
969  public boolean textMatches(String subject) {
970  // A single match is sufficient.
971  return this.regex.matcher(subject).find();
972  }
973 
974  }
975 
976  }
977 
978 }
FilesSet(String name, String description, boolean ignoreKnownFiles, boolean ignoreUnallocatedSpace, Map< String, Rule > rules)
Definition: FilesSet.java:61

Copyright © 2012-2016 Basis Technology. Generated on: Tue Feb 20 2018
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.