Autopsy  4.16.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
HashDbManager.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.hashdatabase;
20 
21 import java.beans.PropertyChangeEvent;
22 import java.beans.PropertyChangeListener;
23 import java.beans.PropertyChangeSupport;
24 import java.io.File;
25 import java.io.FilenameFilter;
26 import java.io.IOException;
27 import java.util.ArrayList;
28 import java.util.HashSet;
29 import java.util.List;
30 import java.util.MissingResourceException;
31 import java.util.Objects;
32 import java.util.Set;
33 import java.util.concurrent.ExecutionException;
34 import java.util.logging.Level;
35 import java.util.regex.Matcher;
36 import java.util.regex.Pattern;
37 import java.util.stream.Collectors;
38 import java.util.stream.Stream;
39 import javax.swing.JFileChooser;
40 import javax.swing.JOptionPane;
41 import javax.swing.SwingWorker;
42 import javax.swing.filechooser.FileNameExtensionFilter;
43 import org.apache.commons.io.FilenameUtils;
44 import org.apache.commons.lang.StringUtils;
45 import org.netbeans.api.progress.ProgressHandle;
46 import org.openide.modules.InstalledFileLocator;
47 import org.openide.util.NbBundle;
48 import org.openide.util.NbBundle.Messages;
49 import org.openide.windows.WindowManager;
60 import org.sleuthkit.datamodel.AbstractFile;
61 import org.sleuthkit.datamodel.Content;
62 import org.sleuthkit.datamodel.HashEntry;
63 import org.sleuthkit.datamodel.HashHitInfo;
64 import org.sleuthkit.datamodel.SleuthkitJNI;
65 import org.sleuthkit.datamodel.TskCoreException;
66 import org.sleuthkit.datamodel.TskData;
69 
74 public class HashDbManager implements PropertyChangeListener {
75 
76  private static final String HASH_DATABASE_FILE_EXTENSON = "kdb"; //NON-NLS
77  private static HashDbManager instance = null;
78  private List<HashDb> hashSets = new ArrayList<>();
79  private Set<String> hashSetNames = new HashSet<>();
80  private Set<String> hashSetPaths = new HashSet<>();
81 
82  private List<HashDb> officialHashSets = new ArrayList<>();
83  private Set<String> officialHashSetNames = new HashSet<>();
84  private Set<String> officialHashSetPaths = new HashSet<>();
85 
86  PropertyChangeSupport changeSupport = new PropertyChangeSupport(HashDbManager.class);
87  private static final Logger logger = Logger.getLogger(HashDbManager.class.getName());
88  private boolean allDatabasesLoadedCorrectly = false;
89 
90  private static final String OFFICIAL_HASH_SETS_FOLDER = "OfficialHashSets";
91  private static final String KDB_EXT = "kdb";
92 
93  private static final String DB_NAME_PARAM = "dbName";
94  private static final String KNOWN_STATUS_PARAM = "knownStatus";
95  private static final Pattern OFFICIAL_FILENAME = Pattern.compile("(?<" + DB_NAME_PARAM + ">.+?)\\.(?<" + KNOWN_STATUS_PARAM + ">.+?)\\." + KDB_EXT);
96 
97  private static final FilenameFilter DEFAULT_KDB_FILTER = new FilenameFilter() {
98  @Override
99  public boolean accept(File dir, String name) {
100  return name.endsWith("." + KDB_EXT);
101  }
102  };
103 
109  public enum SetEvt {
110 
111  DB_ADDED, DB_DELETED, DB_INDEXED
112  };
113 
119  public static synchronized HashDbManager getInstance() {
120  if (instance == null) {
121  instance = new HashDbManager();
122  }
123  return instance;
124  }
125 
126  public synchronized void addPropertyChangeListener(PropertyChangeListener listener) {
127  changeSupport.addPropertyChangeListener(listener);
128  }
129 
130  public synchronized void removePropertyChangeListener(PropertyChangeListener listener) {
131  changeSupport.removePropertyChangeListener(listener);
132  }
133 
134  synchronized boolean verifyAllDatabasesLoadedCorrectly() {
136  }
137 
138  private HashDbManager() {
140  }
141 
147  static String getHashDatabaseFileExtension() {
149  }
150 
151  public class HashDbManagerException extends Exception {
152 
153  private static final long serialVersionUID = 1L;
154 
155  private HashDbManagerException(String message) {
156  super(message);
157  }
158 
159  private HashDbManagerException(String message, Throwable exception) {
160  super(message, exception);
161  }
162  }
163 
183  public synchronized HashDb addExistingHashDatabase(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType) throws HashDbManagerException {
184  HashDb hashDb = null;
185  hashDb = this.addExistingHashDatabaseNoSave(hashSetName, path, searchDuringIngest, sendIngestMessages, knownFilesType);
186  this.save();
187  return hashDb;
188  }
189 
190  synchronized HashDb addExistingHashDatabaseNoSave(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType) throws HashDbManagerException {
191  HashDb hashDb = null;
192  try {
193  if (!new File(path).exists()) {
194  throw new HashDbManagerException(NbBundle.getMessage(HashDbManager.class, "HashDbManager.hashDbDoesNotExistExceptionMsg", path));
195  }
196 
197  checkDbCollision(path, hashSetName);
198 
199  hashDb = addHashDatabase(SleuthkitJNI.openHashDatabase(path), hashSetName, searchDuringIngest, sendIngestMessages, knownFilesType);
200  } catch (TskCoreException ex) {
201  throw new HashDbManagerException(ex.getMessage());
202  }
203  return hashDb;
204  }
205 
224  public synchronized HashDb addNewHashDatabase(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages,
225  HashDb.KnownFilesType knownFilesType) throws HashDbManagerException {
226 
227  HashDb hashDb = null;
228  hashDb = this.addNewHashDatabaseNoSave(hashSetName, path, searchDuringIngest, sendIngestMessages, knownFilesType);
229 
230  this.save();
231 
232  return hashDb;
233  }
234 
235  public synchronized HashDb addNewHashDatabaseNoSave(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages,
236  HashDb.KnownFilesType knownFilesType) throws HashDbManagerException {
237  HashDb hashDb = null;
238  try {
239  File file = new File(path);
240  if (file.exists()) {
241  throw new HashDbManagerException(NbBundle.getMessage(HashDbManager.class, "HashDbManager.hashDbFileExistsExceptionMsg", path));
242  }
243  if (!FilenameUtils.getExtension(file.getName()).equalsIgnoreCase(HASH_DATABASE_FILE_EXTENSON)) {
244  throw new HashDbManagerException(NbBundle.getMessage(HashDbManager.class, "HashDbManager.illegalHashDbFileNameExtensionMsg",
245  getHashDatabaseFileExtension()));
246  }
247 
248  checkDbCollision(path, hashSetName);
249 
250  hashDb = addHashDatabase(SleuthkitJNI.createHashDatabase(path), hashSetName, searchDuringIngest, sendIngestMessages, knownFilesType);
251  } catch (TskCoreException ex) {
252  throw new HashDbManagerException(ex.getMessage());
253  }
254  return hashDb;
255  }
256 
268  private void checkDbCollision(String path, String hashSetName) throws HashDbManagerException, MissingResourceException {
269  if (hashSetPaths.contains(path) || officialHashSetPaths.contains(path)) {
270  throw new HashDbManagerException(NbBundle.getMessage(HashDbManager.class, "HashDbManager.hashDbAlreadyAddedExceptionMsg", path));
271  }
272 
273  if (hashSetNames.contains(hashSetName) || officialHashSetNames.contains(hashSetName)) {
274  throw new HashDbManagerException(NbBundle.getMessage(HashDbManager.class, "HashDbManager.duplicateHashSetNameExceptionMsg", hashSetName));
275  }
276  }
277 
278  private SleuthkitHashSet addHashDatabase(int handle, String hashSetName, boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType) throws TskCoreException {
279  // Wrap an object around the handle.
280  SleuthkitHashSet hashDb = new SleuthkitHashSet(handle, hashSetName, searchDuringIngest, sendIngestMessages, knownFilesType);
281 
282  // Get the indentity data before updating the collections since the
283  // accessor methods may throw.
284  String databasePath = hashDb.getDatabasePath();
285  String indexPath = hashDb.getIndexPath();
286 
287  // Update the collections used to ensure that hash set names are unique
288  // and the same database is not added to the configuration more than once.
289  hashSetNames.add(hashDb.getHashSetName());
290  if (!databasePath.equals("None")) { //NON-NLS
291  hashSetPaths.add(databasePath);
292  }
293  if (!indexPath.equals("None")) { //NON-NLS
294  hashSetPaths.add(indexPath);
295  }
296 
297  // Add the hash database to the collection
298  hashSets.add(hashDb);
299 
300  // Let any external listeners know that there's a new set
301  try {
302  changeSupport.firePropertyChange(SetEvt.DB_ADDED.toString(), null, hashSetName);
303  } catch (Exception e) {
304  logger.log(Level.SEVERE, "HashDbManager listener threw exception", e); //NON-NLS
306  NbBundle.getMessage(this.getClass(), "HashDbManager.moduleErr"),
307  NbBundle.getMessage(this.getClass(), "HashDbManager.moduleErrorListeningToUpdatesMsg"),
309  }
310  return hashDb;
311  }
312 
313  CentralRepoHashSet addExistingCentralRepoHashSet(String hashSetName, String version, int referenceSetID,
314  boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType,
315  boolean readOnly) throws TskCoreException {
316 
317  if (!CentralRepository.isEnabled()) {
318  throw new TskCoreException("Could not load central repository hash set " + hashSetName + " - central repository is not enabled");
319  }
320 
321  CentralRepoHashSet db = new CentralRepoHashSet(hashSetName, version, referenceSetID, searchDuringIngest,
322  sendIngestMessages, knownFilesType, readOnly);
323 
324  if (!db.isValid()) {
325  throw new TskCoreException("Error finding hash set " + hashSetName + " in central repository");
326  }
327 
328  // Add the hash database to the collection
329  if(!hashSets.contains(db)) {
330  hashSets.add(db);
331 
332  // Let any external listeners know that there's a new set
333  try {
334  changeSupport.firePropertyChange(SetEvt.DB_ADDED.toString(), null, hashSetName);
335  } catch (Exception e) {
336  logger.log(Level.SEVERE, "HashDbManager listener threw exception", e); //NON-NLS
337  MessageNotifyUtil.Notify.show(
338  NbBundle.getMessage(this.getClass(), "HashDbManager.moduleErr"),
339  NbBundle.getMessage(this.getClass(), "HashDbManager.moduleErrorListeningToUpdatesMsg"),
340  MessageNotifyUtil.MessageType.ERROR);
341  }
342  }
343  return db;
344 
345  }
346 
347  synchronized void indexHashDatabase(SleuthkitHashSet hashDb) {
348  hashDb.addPropertyChangeListener(this);
349  HashDbIndexer creator = new HashDbIndexer(hashDb);
350  creator.execute();
351  }
352 
353  @Override
354  public void propertyChange(PropertyChangeEvent event) {
355  if (event.getPropertyName().equals(SleuthkitHashSet.Event.INDEXING_DONE.name())) {
356  SleuthkitHashSet hashDb = (SleuthkitHashSet) event.getNewValue();
357  if (null != hashDb) {
358  try {
359  String indexPath = hashDb.getIndexPath();
360  if (!indexPath.equals("None")) { //NON-NLS
361  hashSetPaths.add(indexPath);
362  }
363  } catch (TskCoreException ex) {
364  Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error getting index path of " + hashDb.getHashSetName() + " hash set after indexing", ex); //NON-NLS
365  }
366  }
367  }
368  }
369 
378  public synchronized void removeHashDatabase(HashDb hashDb) throws HashDbManagerException {
379  this.removeHashDatabaseNoSave(hashDb);
380  this.save();
381  }
382 
383  public synchronized void removeHashDatabaseNoSave(HashDb hashDb) throws HashDbManagerException {
384  // Don't remove a database if ingest is running
385  boolean ingestIsRunning = IngestManager.getInstance().isIngestRunning();
386  if (ingestIsRunning) {
387  throw new HashDbManagerException(NbBundle.getMessage(this.getClass(), "HashDbManager.ingestRunningExceptionMsg"));
388  }
389  // Remove the database from whichever hash set list it occupies,
390  // and remove its hash set name from the hash set used to ensure unique
391  // hash set names are used, before undertaking These operations will succeed and constitute
392  // a mostly effective removal, even if the subsequent operations fail.
393  String hashSetName = hashDb.getHashSetName();
394  hashSetNames.remove(hashSetName);
395  hashSets.remove(hashDb);
396 
397  // Now undertake the operations that could throw.
398  // Indexing is only relevanet for sleuthkit hashsets
399  if (hashDb instanceof SleuthkitHashSet) {
400  SleuthkitHashSet hashDatabase = (SleuthkitHashSet) hashDb;
401  try {
402  if (hashDatabase.hasIndex()) {
403  hashSetPaths.remove(hashDatabase.getIndexPath());
404  }
405  } catch (TskCoreException ex) {
406  Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error getting index path of " + hashDatabase.getHashSetName() + " hash set when removing the hash set", ex); //NON-NLS
407  }
408 
409  try {
410  if (!hashDatabase.hasIndexOnly()) {
411  hashSetPaths.remove(hashDatabase.getDatabasePath());
412  }
413  } catch (TskCoreException ex) {
414  Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error getting hash set path of " + hashDatabase.getHashSetName() + " hash set when removing the hash set", ex); //NON-NLS
415  }
416 
417  try {
418  hashDatabase.close();
419  } catch (TskCoreException ex) {
420  Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error closing " + hashDb.getHashSetName() + " hash set when removing the hash set", ex); //NON-NLS
421  }
422  }
423 
424  // Let any external listeners know that a set has been deleted
425  try {
426  changeSupport.firePropertyChange(SetEvt.DB_DELETED.toString(), null, hashSetName);
427  } catch (Exception e) {
428  logger.log(Level.SEVERE, "HashDbManager listener threw exception", e); //NON-NLS
430  NbBundle.getMessage(this.getClass(), "HashDbManager.moduleErr"),
431  NbBundle.getMessage(this.getClass(), "HashDbManager.moduleErrorListeningToUpdatesMsg"),
433  }
434  }
435 
436  void save() throws HashDbManagerException {
437  try {
438  if (!HashLookupSettings.writeSettings(new HashLookupSettings(HashLookupSettings.convertHashSetList(this.hashSets)))) {
439  throw new HashDbManagerException(NbBundle.getMessage(this.getClass(), "HashDbManager.saveErrorExceptionMsg"));
440  }
441  } catch (HashLookupSettings.HashLookupSettingsException ex) {
442  throw new HashDbManagerException(NbBundle.getMessage(this.getClass(), "HashDbManager.saveErrorExceptionMsg"));
443  }
444  }
445 
453  public synchronized List<HashDb> getAllHashSets() {
454  try {
456  } catch (TskCoreException ex) {
457  Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error loading central repository hash sets", ex); //NON-NLS
458  }
459 
460  return Stream.concat(this.officialHashSets.stream(), this.hashSets.stream())
461  .collect(Collectors.toList());
462  }
463 
469  public synchronized List<HashDb> getKnownFileHashSets() {
470  return getAllHashSets()
471  .stream()
472  .filter((db) -> (db.getKnownFilesType() == HashDb.KnownFilesType.KNOWN))
473  .collect(Collectors.toList());
474  }
475 
481  public synchronized List<HashDb> getKnownBadFileHashSets() {
482  return getAllHashSets()
483  .stream()
484  .filter((db) -> (db.getKnownFilesType() == HashDb.KnownFilesType.KNOWN_BAD))
485  .collect(Collectors.toList());
486  }
487 
493  public synchronized List<HashDb> getUpdateableHashSets() {
495  }
496 
497  private List<HashDb> getUpdateableHashSets(List<HashDb> hashDbs) {
498  return hashDbs
499  .stream()
500  .filter((HashDb db) -> {
501  try {
502  return db.isUpdateable();
503  } catch (TskCoreException ex) {
504  Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error checking updateable status of " + db.getHashSetName() + " hash set", ex); //NON-NLS
505  return false;
506  }
507  })
508  .collect(Collectors.toList());
509  }
510 
511  private List<HashDbInfo> getCentralRepoHashSetsFromDatabase() {
512  List<HashDbInfo> crHashSets = new ArrayList<>();
514  try {
516  for (CentralRepoFileSet globalSet : crSets) {
517 
518  // Defaults for fields not stored in the central repository:
519  // searchDuringIngest: false
520  // sendIngestMessages: true if the hash set is notable
521  boolean sendIngestMessages = KnownFilesType.fromFileKnown(globalSet.getFileKnownStatus()).equals(HashDb.KnownFilesType.KNOWN_BAD);
522  crHashSets.add(new HashDbInfo(globalSet.getSetName(), globalSet.getVersion(),
523  globalSet.getGlobalSetID(), KnownFilesType.fromFileKnown(globalSet.getFileKnownStatus()), globalSet.isReadOnly(), false, sendIngestMessages));
524  }
525  } catch (CentralRepoException ex) {
526  Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error loading central repository hash sets", ex); //NON-NLS
527  }
528  }
529  return crHashSets;
530  }
531 
536  public synchronized void loadLastSavedConfiguration() {
537  closeHashDatabases(this.hashSets);
538  hashSetNames.clear();
539  hashSetPaths.clear();
540 
542  }
543 
544  private void closeHashDatabases(List<HashDb> hashDatabases) {
545  for (HashDb database : hashDatabases) {
546  if (database instanceof SleuthkitHashSet) {
547  try {
548  ((SleuthkitHashSet) database).close();
549  } catch (TskCoreException ex) {
550  Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error closing " + database.getHashSetName() + " hash set", ex); //NON-NLS
551  }
552  }
553  }
554  hashDatabases.clear();
555  }
556 
557  private void loadHashsetsConfiguration() {
559 
560  try {
561  HashLookupSettings settings = HashLookupSettings.readSettings();
562  this.configureSettings(settings, officialHashSetNames);
563  } catch (HashLookupSettings.HashLookupSettingsException ex) {
564  Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Could not read Hash lookup settings from disk.", ex);
565  }
566  }
567 
572  private void loadOfficialHashSets() {
573  officialHashSetPaths = new HashSet<>();
574  officialHashSetNames = new HashSet<>();
575 
576  try {
577  officialHashSets = loadOfficialHashSetsFromFolder(OFFICIAL_HASH_SETS_FOLDER);
578  officialHashSets.forEach(db -> {
579  officialHashSetNames.add(db.getHashSetName());
580  try {
581  String databasePath = db.getDatabasePath();
582  String indexPath = db.getIndexPath();
583 
584  if (StringUtils.isNotBlank(databasePath) && !databasePath.equals("None")) { //NON-NLS
585  officialHashSetPaths.add(databasePath);
586  }
587  if (StringUtils.isNotBlank(indexPath) && !indexPath.equals("None")) { //NON-NLS
588  officialHashSetPaths.add(indexPath);
589  }
590  } catch (TskCoreException ex) {
591  logger.log(Level.SEVERE, "There was an error loading the official hash set name.", ex);
592  }
593  });
594  } catch (HashDbManagerException ex) {
595  logger.log(Level.WARNING, "There was an error loading the official hash sets.", ex);
596  officialHashSets = new ArrayList<HashDb>();
597  }
598  }
599 
611  @Messages({
612  "# {0} - hashSetName",
613  "HashDbManager_handleNameConflict_conflictSuffix={0} (Custom)"
614  })
615  private List<HashDbInfo> handleNameConflict(List<HashDbInfo> curHashsets, Set<String> officialNames) {
616  Set<String> curNames = new HashSet<String>(officialNames);
617  boolean change = false;
618  List<HashDbInfo> newItems = new ArrayList<>();
619  for (HashDbInfo hashset : curHashsets) {
620  String thisName = hashset.getHashSetName();
621  if (curNames.contains(thisName)) {
622  while (curNames.contains(thisName)) {
623  thisName = Bundle.HashDbManager_handleNameConflict_conflictSuffix(thisName);
624  }
625 
626  newItems.add(new HashDbInfo(
627  thisName,
628  hashset.getKnownFilesType(),
629  hashset.getSearchDuringIngest(),
630  hashset.getSendIngestMessages(),
631  hashset.getPath(),
632  hashset.getReferenceSetID(),
633  hashset.getVersion(),
634  hashset.isReadOnly(),
635  hashset.isCentralRepoDatabaseType()
636  ));
637  change = true;
638  } else {
639  newItems.add(hashset);
640  }
641 
642  curNames.add(thisName);
643  }
644 
645  if (!change) {
646  return curHashsets;
647  } else {
648  try {
649  HashLookupSettings.writeSettings(new HashLookupSettings(newItems));
650  HashLookupSettings toRet = HashLookupSettings.readSettings();
651  return toRet.getHashDbInfo();
652  } catch (HashLookupSettings.HashLookupSettingsException ex) {
653  logger.log(Level.SEVERE, "There was an error while trying to resave after name conflict.", ex);
654  return newItems;
655  }
656  }
657  }
658 
668  private List<HashDb> loadOfficialHashSetsFromFolder(String folder) throws HashDbManagerException {
669  File configFolder = InstalledFileLocator.getDefault().locate(
670  folder, HashDbManager.class.getPackage().getName(), false);
671 
672  if (configFolder == null || !configFolder.exists() || !configFolder.isDirectory()) {
673  throw new HashDbManagerException("Folder provided: " + folder + " does not exist.");
674  }
675 
676  return Stream.of(configFolder.listFiles(DEFAULT_KDB_FILTER))
677  .map((f) -> {
678  try {
679  return getOfficialHashDbFromFile(f);
680  } catch (HashDbManagerException | TskCoreException ex) {
681  logger.log(Level.WARNING, String.format("Hashset: %s could not be properly read.", f.getAbsolutePath()), ex);
682  return null;
683  }
684  })
685  .filter((hashdb) -> hashdb != null)
686  .collect(Collectors.toList());
687  }
688 
701  private HashDb getOfficialHashDbFromFile(File file) throws HashDbManagerException, TskCoreException {
702  if (file == null || !file.exists()) {
703  throw new HashDbManagerException(String.format("No file found for: %s", file == null ? "<null>" : file.getAbsolutePath()));
704  }
705  String filename = file.getName();
706  Matcher match = OFFICIAL_FILENAME.matcher(filename);
707  if (!match.find()) {
708  throw new HashDbManagerException(String.format("File with name: %s does not match regex of: %s", filename, OFFICIAL_FILENAME.toString()));
709  }
710 
711  String hashdbName = match.group(DB_NAME_PARAM);
712  final String knownStatus = match.group(KNOWN_STATUS_PARAM);
713 
714  KnownFilesType knownFilesType = Stream.of(HashDb.KnownFilesType.values())
715  .filter(k -> k.getIdentifier().toUpperCase().equals(knownStatus.toUpperCase()))
716  .findFirst()
717  .orElseThrow(() -> new HashDbManagerException(String.format("No KnownFilesType matches %s for file: %s", knownStatus, filename)));
718 
719  return new SleuthkitHashSet(
720  SleuthkitJNI.openHashDatabase(file.getAbsolutePath()),
721  hashdbName,
722  true, //searchDuringIngest
723  false, //sendIngestMessages
724  knownFilesType,
725  true); // official set
726  }
727 
736  @Messages({"# {0} - hash set name", "HashDbManager.noDbPath.message=Couldn't get valid hash set path for: {0}",
737  "HashDbManager.centralRepoLoadError.message=Error loading central repository hash sets"})
738  private void configureSettings(HashLookupSettings settings, Set<String> officialSetNames) {
739  allDatabasesLoadedCorrectly = true;
740  List<HashDbInfo> hashDbInfoList = settings.getHashDbInfo();
741  hashDbInfoList = handleNameConflict(hashDbInfoList, officialSetNames);
742 
743  for (HashDbInfo hashDbInfo : hashDbInfoList) {
744  configureLocalDb(hashDbInfo);
745  }
746 
748  configureCrDbs();
749  }
750 
751  /*
752  * NOTE: When RuntimeProperties.coreComponentsAreActive() is "false", I
753  * don't think we should overwrite hash db settings file because we were
754  * unable to load a database. The user should have to fix the issue or
755  * remove the database from settings. Overwiting the settings
756  * effectively removes the database from HashLookupSettings and the user
757  * may not know about this because the dialogs are not being displayed.
758  * The next time user starts Autopsy, HashDB will load without errors
759  * and the user may think that the problem was solved.
760  */
761  if (!allDatabasesLoadedCorrectly && RuntimeProperties.runningWithGUI()) {
762  try {
763  HashLookupSettings.writeSettings(new HashLookupSettings(HashLookupSettings.convertHashSetList(this.hashSets)));
764  allDatabasesLoadedCorrectly = true;
765  } catch (HashLookupSettings.HashLookupSettingsException ex) {
766  allDatabasesLoadedCorrectly = false;
767  logger.log(Level.SEVERE, "Could not overwrite hash set settings.", ex);
768  }
769  }
770  }
771 
775  private void configureCrDbs() {
776  try {
778  } catch (TskCoreException ex) {
779  Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error opening hash set", ex); //NON-NLS
780 
781  JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(),
782  Bundle.HashDbManager_centralRepoLoadError_message(),
783  NbBundle.getMessage(this.getClass(), "HashDbManager.openHashDbErr"),
784  JOptionPane.ERROR_MESSAGE);
785  allDatabasesLoadedCorrectly = false;
786  }
787  }
788 
793  private void configureLocalDb(HashDbInfo hashDbInfo) {
794  try {
795  if (hashDbInfo.isFileDatabaseType()) {
796  String dbPath = this.getValidFilePath(hashDbInfo.getHashSetName(), hashDbInfo.getPath());
797  if (dbPath != null) {
798  addHashDatabase(SleuthkitJNI.openHashDatabase(dbPath), hashDbInfo.getHashSetName(), hashDbInfo.getSearchDuringIngest(), hashDbInfo.getSendIngestMessages(), hashDbInfo.getKnownFilesType());
799  } else {
800  logger.log(Level.WARNING, Bundle.HashDbManager_noDbPath_message(hashDbInfo.getHashSetName()));
801  allDatabasesLoadedCorrectly = false;
802  }
803  } else {
805  addExistingCentralRepoHashSet(hashDbInfo.getHashSetName(), hashDbInfo.getVersion(),
806  hashDbInfo.getReferenceSetID(),
807  hashDbInfo.getSearchDuringIngest(), hashDbInfo.getSendIngestMessages(),
808  hashDbInfo.getKnownFilesType(), hashDbInfo.isReadOnly());
809  }
810  }
811  } catch (TskCoreException ex) {
812  Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error opening hash set", ex); //NON-NLS
813  JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(),
814  NbBundle.getMessage(this.getClass(),
815  "HashDbManager.unableToOpenHashDbMsg", hashDbInfo.getHashSetName()),
816  NbBundle.getMessage(this.getClass(), "HashDbManager.openHashDbErr"),
817  JOptionPane.ERROR_MESSAGE);
818  allDatabasesLoadedCorrectly = false;
819  }
820  }
821 
822  private void updateHashSetsFromCentralRepository() throws TskCoreException {
824  List<HashDbInfo> crHashDbInfoList = getCentralRepoHashSetsFromDatabase();
825  for (HashDbInfo hashDbInfo : crHashDbInfoList) {
826  if (hashDbInfoIsNew(hashDbInfo)) {
827  addExistingCentralRepoHashSet(hashDbInfo.getHashSetName(), hashDbInfo.getVersion(),
828  hashDbInfo.getReferenceSetID(),
829  hashDbInfo.getSearchDuringIngest(), hashDbInfo.getSendIngestMessages(), hashDbInfo.getKnownFilesType(),
830  hashDbInfo.isReadOnly());
831  }
832  }
833  }
834  }
835 
836  private boolean hashDbInfoIsNew(HashDbInfo dbInfo) {
837  for (HashDb db : this.hashSets) {
838  if (dbInfo.matches(db)) {
839  return false;
840  }
841  }
842  return true;
843  }
844 
845  private String getValidFilePath(String hashSetName, String configuredPath) {
846  // Check the configured path.
847  File database = new File(configuredPath);
848  if (database.exists()) {
849  return configuredPath;
850  }
851 
852  // Give the user an opportunity to find the desired file.
853  String newPath = null;
855  && JOptionPane.showConfirmDialog(WindowManager.getDefault().getMainWindow(),
856  NbBundle.getMessage(this.getClass(), "HashDbManager.dlgMsg.dbNotFoundAtLoc",
857  hashSetName, configuredPath),
858  NbBundle.getMessage(this.getClass(), "HashDbManager.dlgTitle.MissingDb"),
859  JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
860  newPath = searchForFile();
861  if (null != newPath && !newPath.isEmpty()) {
862  database = new File(newPath);
863  if (!database.exists()) {
864  newPath = null;
865  }
866  }
867  }
868  return newPath;
869  }
870 
871  private String searchForFile() {
872  String filePath = null;
873  JFileChooser fc = new JFileChooser();
874  fc.setDragEnabled(false);
875  fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
876  String[] EXTENSION = new String[]{"txt", "idx", "hash", "Hash", "kdb"}; //NON-NLS
877  FileNameExtensionFilter filter = new FileNameExtensionFilter(
878  NbBundle.getMessage(this.getClass(), "HashDbManager.fileNameExtensionFilter.title"), EXTENSION);
879  fc.setFileFilter(filter);
880  fc.setMultiSelectionEnabled(false);
881  if (fc.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
882  File f = fc.getSelectedFile();
883  try {
884  filePath = f.getCanonicalPath();
885  } catch (IOException ex) {
886  Logger.getLogger(HashDbManager.class.getName()).log(Level.WARNING, "Couldn't get selected file path", ex); //NON-NLS
887  }
888  }
889  return filePath;
890  }
891 
892  public static abstract class HashDb {
893 
898  @Messages({
899  "HashDbManager.noChange.text=No Change",
900  "HashDbManager.known.text=Known",
901  "HashDbManager.knownBad.text=Notable"
902  })
903  public enum KnownFilesType {
904 
905  KNOWN(Bundle.HashDbManager_known_text(), "Known", TskData.FileKnown.KNOWN, false, false),
906  KNOWN_BAD(Bundle.HashDbManager_knownBad_text(), "Notable", TskData.FileKnown.BAD, true, true),
907  NO_CHANGE(Bundle.HashDbManager_noChange_text(), "NoChange", TskData.FileKnown.UNKNOWN, true, false);
908 
909  private final String displayName;
910  private final String identifier;
911  private final TskData.FileKnown fileKnown;
912  private final boolean allowSendInboxMessages;
913  private final boolean defaultSendInboxMessages;
914 
915  KnownFilesType(String displayName, String identifier, TskData.FileKnown fileKnown,
916  boolean allowSendInboxMessages, boolean defaultSendInboxMessages) {
917 
918  this.displayName = displayName;
919  this.identifier = identifier;
920  this.fileKnown = fileKnown;
921  this.allowSendInboxMessages = allowSendInboxMessages;
922  this.defaultSendInboxMessages = defaultSendInboxMessages;
923  }
924 
933  return allowSendInboxMessages;
934  }
935 
944  return defaultSendInboxMessages;
945  }
946 
953  String getIdentifier() {
954  return identifier;
955  }
956 
957  public String getDisplayName() {
958  return this.displayName;
959  }
960 
967  TskData.FileKnown getFileKnown() {
968  return this.fileKnown;
969  }
970 
978  static KnownFilesType fromFileKnown(TskData.FileKnown fileKnown) {
979  if (fileKnown == null) {
980  return null;
981  }
982 
983  return Stream.of(KnownFilesType.values())
984  .filter((type) -> type.getFileKnown() == fileKnown)
985  .findFirst()
986  .orElseThrow(() -> new IllegalArgumentException("Unknown TskData.FileKnown type: " + fileKnown));
987  }
988  }
989 
993  public enum Event {
994 
995  INDEXING_DONE
996  }
997 
998  public abstract String getHashSetName();
999 
1000  abstract String getDisplayName();
1001 
1002  public abstract String getDatabasePath() throws TskCoreException;
1003 
1004  public abstract HashDb.KnownFilesType getKnownFilesType();
1005 
1006  public abstract boolean getSearchDuringIngest();
1007 
1008  abstract void setSearchDuringIngest(boolean useForIngest);
1009 
1010  public abstract boolean getSendIngestMessages();
1011 
1012  abstract void setSendIngestMessages(boolean showInboxMessages);
1013 
1021  public abstract boolean isUpdateable() throws TskCoreException;
1022 
1031  public abstract void addHashes(Content content) throws TskCoreException;
1032 
1033  public abstract void addHashes(Content content, String comment) throws TskCoreException;
1034 
1035  public abstract void addHashes(List<HashEntry> hashes) throws TskCoreException;
1036 
1037  public abstract boolean lookupMD5Quick(Content content) throws TskCoreException;
1038 
1039  public abstract HashHitInfo lookupMD5(Content content) throws TskCoreException;
1040 
1049  abstract boolean isValid() throws TskCoreException;
1050 
1051  public abstract String getIndexPath() throws TskCoreException;
1052 
1053  public abstract boolean hasIndexOnly() throws TskCoreException;
1054 
1055  public abstract void firePropertyChange(String propertyName, Object oldValue, Object newValue);
1056 
1057  public abstract void addPropertyChangeListener(PropertyChangeListener pcl);
1058 
1059  public abstract void removePropertyChangeListener(PropertyChangeListener pcl);
1060 
1061  @Override
1062  public abstract String toString();
1063 
1064  }
1065 
1070  class SleuthkitHashSet extends HashDb {
1071 
1072  private static final long serialVersionUID = 1L;
1073  private final int handle;
1074  private final String hashSetName;
1075  private boolean searchDuringIngest;
1076  private boolean sendIngestMessages;
1077  private final HashDb.KnownFilesType knownFilesType;
1078  private boolean indexing;
1079  private final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
1080  private final boolean officialSet;
1081 
1082  private SleuthkitHashSet(int handle, String hashSetName, boolean useForIngest, boolean sendHitMessages, KnownFilesType knownFilesType) {
1083  this(handle, hashSetName, useForIngest, sendHitMessages, knownFilesType, false);
1084  }
1085 
1086  private SleuthkitHashSet(int handle, String hashSetName, boolean useForIngest, boolean sendHitMessages, KnownFilesType knownFilesType, boolean officialSet) {
1087  this.handle = handle;
1088  this.hashSetName = hashSetName;
1089  this.searchDuringIngest = useForIngest;
1090  this.sendIngestMessages = sendHitMessages;
1091  this.knownFilesType = knownFilesType;
1092  this.indexing = false;
1093  this.officialSet = officialSet;
1094  }
1095 
1102  @Override
1103  public void addPropertyChangeListener(PropertyChangeListener pcl) {
1104  propertyChangeSupport.addPropertyChangeListener(pcl);
1105  }
1106 
1112  @Override
1113  public void removePropertyChangeListener(PropertyChangeListener pcl) {
1114  propertyChangeSupport.removePropertyChangeListener(pcl);
1115  }
1116 
1117  int getHandle() {
1118  return handle;
1119  }
1120 
1121  @Override
1122  public String getHashSetName() {
1123  return hashSetName;
1124  }
1125 
1126  @Override
1127  String getDisplayName() {
1128  return getHashSetName();
1129  }
1130 
1131  @Override
1132  public String getDatabasePath() throws TskCoreException {
1133  return SleuthkitJNI.getHashDatabasePath(handle);
1134  }
1135 
1136  public void setIndexing(boolean indexing) {
1137  this.indexing = indexing;
1138  }
1139 
1140  @Override
1141  public String getIndexPath() throws TskCoreException {
1142  return SleuthkitJNI.getHashDatabaseIndexPath(handle);
1143  }
1144 
1145  @Override
1146  public KnownFilesType getKnownFilesType() {
1147  return knownFilesType;
1148  }
1149 
1150  @Override
1151  public boolean getSearchDuringIngest() {
1152  return searchDuringIngest;
1153  }
1154 
1155  @Override
1156  void setSearchDuringIngest(boolean useForIngest) {
1157  this.searchDuringIngest = useForIngest;
1158  }
1159 
1160  @Override
1161  public boolean getSendIngestMessages() {
1162  return sendIngestMessages;
1163  }
1164 
1165  @Override
1166  void setSendIngestMessages(boolean showInboxMessages) {
1167  this.sendIngestMessages = showInboxMessages;
1168  }
1169 
1177  @Override
1178  public boolean isUpdateable() throws TskCoreException {
1179  if (isOfficialSet()) {
1180  return false;
1181  }
1182 
1183  return SleuthkitJNI.isUpdateableHashDatabase(this.handle);
1184  }
1185 
1194  @Override
1195  public void addHashes(Content content) throws TskCoreException {
1196  addHashes(content, null);
1197  }
1198 
1209  @Override
1210  public void addHashes(Content content, String comment) throws TskCoreException {
1211  // This only works for AbstractFiles and MD5 hashes at present.
1212  assert content instanceof AbstractFile;
1213  officialSetCheck();
1214  if (content instanceof AbstractFile) {
1215  AbstractFile file = (AbstractFile) content;
1216  if (null != file.getMd5Hash()) {
1217  SleuthkitJNI.addToHashDatabase(null, file.getMd5Hash(), null, null, comment, handle);
1218  }
1219  }
1220  }
1221 
1227  private void officialSetCheck() throws TskCoreException {
1228  if (isOfficialSet()) {
1229  throw new TskCoreException("Hashes cannot be added to an official set");
1230  }
1231  }
1232 
1240  @Override
1241  public void addHashes(List<HashEntry> hashes) throws TskCoreException {
1242  officialSetCheck();
1243  SleuthkitJNI.addToHashDatabase(hashes, handle);
1244  }
1245 
1255  @Override
1256  public boolean lookupMD5Quick(Content content) throws TskCoreException {
1257  boolean result = false;
1258  assert content instanceof AbstractFile;
1259  if (content instanceof AbstractFile) {
1260  AbstractFile file = (AbstractFile) content;
1261  if (null != file.getMd5Hash()) {
1262  result = SleuthkitJNI.lookupInHashDatabase(file.getMd5Hash(), handle);
1263  }
1264  }
1265  return result;
1266  }
1267 
1277  @Override
1278  public HashHitInfo lookupMD5(Content content) throws TskCoreException {
1279  HashHitInfo result = null;
1280  // This only works for AbstractFiles and MD5 hashes at present.
1281  assert content instanceof AbstractFile;
1282  if (content instanceof AbstractFile) {
1283  AbstractFile file = (AbstractFile) content;
1284  if (null != file.getMd5Hash()) {
1285  result = SleuthkitJNI.lookupInHashDatabaseVerbose(file.getMd5Hash(), handle);
1286  }
1287  }
1288  return result;
1289  }
1290 
1299  @Override
1300  boolean isValid() throws TskCoreException {
1301  return hasIndex();
1302  }
1303 
1304  boolean hasIndex() throws TskCoreException {
1305  return SleuthkitJNI.hashDatabaseHasLookupIndex(handle);
1306  }
1307 
1308  @Override
1309  public boolean hasIndexOnly() throws TskCoreException {
1310  return SleuthkitJNI.hashDatabaseIsIndexOnly(handle);
1311  }
1312 
1313  boolean canBeReIndexed() throws TskCoreException {
1314  return SleuthkitJNI.hashDatabaseCanBeReindexed(handle);
1315  }
1316 
1317  boolean isIndexing() {
1318  return indexing;
1319  }
1320 
1321  @Override
1322  public void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
1323  this.propertyChangeSupport.firePropertyChange(propertyName, oldValue, newValue);
1324  }
1325 
1326  private void close() throws TskCoreException {
1327  SleuthkitJNI.closeHashDatabase(handle);
1328  }
1329 
1330  @Override
1331  public String toString() {
1332  return getHashSetName();
1333  }
1334 
1335  @Override
1336  public int hashCode() {
1337  int code = 23;
1338  code = 47 * code + Integer.hashCode(handle);
1339  code = 47 * code + Objects.hashCode(this.hashSetName);
1340  code = 47 * code + Objects.hashCode(this.propertyChangeSupport);
1341  code = 47 * code + Objects.hashCode(this.knownFilesType);
1342  return code;
1343  }
1344 
1345  @Override
1346  public boolean equals(Object obj) {
1347  if (obj == null) {
1348  return false;
1349  }
1350  if (getClass() != obj.getClass()) {
1351  return false;
1352  }
1353  final SleuthkitHashSet other = (SleuthkitHashSet) obj;
1354  if (!Objects.equals(this.hashSetName, other.hashSetName)) {
1355  return false;
1356  }
1357  if (this.knownFilesType != other.knownFilesType) {
1358  return false;
1359  }
1360  return true;
1361  }
1362 
1369  boolean isOfficialSet() {
1370  return officialSet;
1371  }
1372  }
1373 
1378  class CentralRepoHashSet extends HashDb {
1379 
1380  private static final long serialVersionUID = 1L;
1381  private final String hashSetName;
1382  private boolean searchDuringIngest;
1383  private boolean sendIngestMessages;
1384  private final HashDb.KnownFilesType knownFilesType;
1385  private final int referenceSetID;
1386  private final String version;
1387  private String orgName;
1388  private final boolean readOnly;
1389  private final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
1390 
1391  @Messages({"HashDbManager.CentralRepoHashDb.orgError=Error loading organization"})
1392  private CentralRepoHashSet(String hashSetName, String version, int referenceSetID,
1393  boolean useForIngest, boolean sendHitMessages, HashDb.KnownFilesType knownFilesType,
1394  boolean readOnly)
1395  throws TskCoreException {
1396  this.hashSetName = hashSetName;
1397  this.version = version;
1398  this.referenceSetID = referenceSetID;
1399  this.searchDuringIngest = useForIngest;
1400  this.sendIngestMessages = sendHitMessages;
1401  this.knownFilesType = knownFilesType;
1402  this.readOnly = readOnly;
1403 
1404  try {
1405  orgName = CentralRepository.getInstance().getReferenceSetOrganization(referenceSetID).getName();
1406  } catch (CentralRepoException ex) {
1407  Logger.getLogger(SleuthkitHashSet.class.getName()).log(Level.SEVERE, "Error looking up central repository organization for reference set " + referenceSetID, ex); //NON-NLS
1408  orgName = Bundle.HashDbManager_CentralRepoHashDb_orgError();
1409  }
1410  }
1411 
1418  @Override
1419  public void addPropertyChangeListener(PropertyChangeListener pcl) {
1420  propertyChangeSupport.addPropertyChangeListener(pcl);
1421  }
1422 
1428  @Override
1429  public void removePropertyChangeListener(PropertyChangeListener pcl) {
1430  propertyChangeSupport.removePropertyChangeListener(pcl);
1431  }
1432 
1433  @Override
1434  public boolean hasIndexOnly() throws TskCoreException {
1435  return true;
1436  }
1437 
1438  @Override
1439  public String getHashSetName() {
1440  return hashSetName;
1441  }
1442 
1443  @Override
1444  public String getDisplayName() {
1445  if (!getVersion().isEmpty()) {
1446  return getHashSetName() + " " + getVersion() + " (remote)";
1447  } else {
1448  return getHashSetName() + " (remote)";
1449  }
1450  }
1451 
1452  String getVersion() {
1453  return version;
1454  }
1455 
1456  String getOrgName() {
1457  return orgName;
1458  }
1459 
1460  int getReferenceSetID() {
1461  return referenceSetID;
1462  }
1463 
1464  @Override
1465  public String getDatabasePath() throws TskCoreException {
1466  return "";
1467  }
1468 
1469  @Override
1470  public String getIndexPath() throws TskCoreException {
1471  return "";
1472  }
1473 
1474  @Override
1475  public HashDb.KnownFilesType getKnownFilesType() {
1476  return knownFilesType;
1477  }
1478 
1479  @Override
1480  public boolean getSearchDuringIngest() {
1481  return searchDuringIngest;
1482  }
1483 
1484  @Override
1485  void setSearchDuringIngest(boolean useForIngest) {
1486  this.searchDuringIngest = useForIngest;
1487  }
1488 
1489  @Override
1490  public boolean getSendIngestMessages() {
1491  return sendIngestMessages;
1492  }
1493 
1494  @Override
1495  void setSendIngestMessages(boolean showInboxMessages) {
1496  this.sendIngestMessages = showInboxMessages;
1497  }
1498 
1506  @Override
1507  public boolean isUpdateable() throws TskCoreException {
1508  return (!readOnly);
1509  }
1510 
1519  @Override
1520  public void addHashes(Content content) throws TskCoreException {
1521  addHashes(content, null);
1522  }
1523 
1534  @Override
1535  public void addHashes(Content content, String comment) throws TskCoreException {
1536  // This only works for AbstractFiles and MD5 hashes at present.
1537  assert content instanceof AbstractFile;
1538  if (content instanceof AbstractFile) {
1539  AbstractFile file = (AbstractFile) content;
1540  if (null != file.getMd5Hash()) {
1541  TskData.FileKnown type = knownFilesType.getFileKnown();
1542 
1543  try {
1544  CentralRepoFileInstance fileInstance = new CentralRepoFileInstance(referenceSetID, file.getMd5Hash(),
1545  type, comment);
1546  CentralRepository.getInstance().addReferenceInstance(fileInstance, CentralRepository.getInstance().getCorrelationTypeById(CorrelationAttributeInstance.FILES_TYPE_ID));
1547  } catch (CentralRepoException | CorrelationAttributeNormalizationException ex) {
1548  throw new TskCoreException("Error adding hashes to " + getDisplayName(), ex); //NON-NLS
1549  }
1550  }
1551  }
1552  }
1553 
1561  @Override
1562  public void addHashes(List<HashEntry> hashes) throws TskCoreException {
1563  Set<CentralRepoFileInstance> globalFileInstances = new HashSet<>();
1564  for (HashEntry hashEntry : hashes) {
1565  TskData.FileKnown type = knownFilesType.getFileKnown();
1566 
1567  try {
1568  globalFileInstances.add(new CentralRepoFileInstance(referenceSetID, hashEntry.getMd5Hash(), type, hashEntry.getComment()));
1569  } catch (CentralRepoException | CorrelationAttributeNormalizationException ex) {
1570  throw new TskCoreException("Error adding hashes to " + getDisplayName(), ex);
1571  }
1572  }
1573 
1574  try {
1575  CentralRepository.getInstance().bulkInsertReferenceTypeEntries(globalFileInstances,
1576  CentralRepository.getInstance().getCorrelationTypeById(CorrelationAttributeInstance.FILES_TYPE_ID));
1577  } catch (CentralRepoException ex) {
1578  throw new TskCoreException("Error adding hashes to " + getDisplayName(), ex);
1579  }
1580  }
1581 
1591  @Override
1592  public boolean lookupMD5Quick(Content content) throws TskCoreException {
1593  // This only works for AbstractFiles and MD5 hashes
1594  assert content instanceof AbstractFile;
1595  if (content instanceof AbstractFile) {
1596  AbstractFile file = (AbstractFile) content;
1597  if (null != file.getMd5Hash()) {
1598  try {
1599  return CentralRepository.getInstance().isFileHashInReferenceSet(file.getMd5Hash(), this.referenceSetID);
1600  } catch (CentralRepoException | CorrelationAttributeNormalizationException ex) {
1601  Logger.getLogger(SleuthkitHashSet.class.getName()).log(Level.SEVERE, "Error performing central reposiotry hash lookup for hash "
1602  + file.getMd5Hash() + " in reference set " + referenceSetID, ex); //NON-NLS
1603  throw new TskCoreException("Error performing central reposiotry hash lookup", ex);
1604  }
1605  }
1606  }
1607  return false;
1608  }
1609 
1619  @Override
1620  public HashHitInfo lookupMD5(Content content) throws TskCoreException {
1621  HashHitInfo result = null;
1622  // This only works for AbstractFiles and MD5 hashes
1623  assert content instanceof AbstractFile;
1624  if (content instanceof AbstractFile) {
1625  AbstractFile file = (AbstractFile) content;
1626  if (null != file.getMd5Hash()) {
1627  try {
1628  return CentralRepository.getInstance().lookupHash(file.getMd5Hash(), referenceSetID);
1629  } catch (CentralRepoException | CorrelationAttributeNormalizationException ex) {
1630  Logger.getLogger(SleuthkitHashSet.class.getName()).log(Level.SEVERE, "Error performing central reposiotry hash lookup for hash "
1631  + file.getMd5Hash() + " in reference set " + referenceSetID, ex); //NON-NLS
1632  throw new TskCoreException("Error performing central reposiotry hash lookup", ex);
1633  }
1634  }
1635  }
1636  return result;
1637  }
1638 
1644  @Override
1645  boolean isValid() {
1646  if (!CentralRepository.isEnabled()) {
1647  return false;
1648  }
1649  try {
1650  return CentralRepository.getInstance().referenceSetIsValid(this.referenceSetID, this.hashSetName, this.version);
1651  } catch (CentralRepoException ex) {
1652  Logger.getLogger(CentralRepoHashSet.class.getName()).log(Level.SEVERE, "Error validating hash set " + hashSetName, ex); //NON-NLS
1653  return false;
1654  }
1655  }
1656 
1657  @Override
1658  public void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
1659  this.propertyChangeSupport.firePropertyChange(propertyName, oldValue, newValue);
1660  }
1661 
1662  @Override
1663  public String toString() {
1664  return getDisplayName();
1665  }
1666 
1667  @Override
1668  public int hashCode() {
1669  int code = 23;
1670  code = 47 * code + Objects.hashCode(this.hashSetName);
1671  code = 47 * code + Objects.hashCode(this.version);
1672  code = 47 * code + Integer.hashCode(this.referenceSetID);
1673  code = 47 * code + Objects.hashCode(this.knownFilesType);
1674  return code;
1675  }
1676 
1677  @Override
1678  public boolean equals(Object obj) {
1679  if (obj == null) {
1680  return false;
1681  }
1682  if (getClass() != obj.getClass()) {
1683  return false;
1684  }
1685  final CentralRepoHashSet other = (CentralRepoHashSet) obj;
1686  if (!Objects.equals(this.hashSetName, other.hashSetName)) {
1687  return false;
1688  }
1689  if (!Objects.equals(this.version, other.version)) {
1690  return false;
1691  }
1692  if (this.knownFilesType != other.knownFilesType) {
1693  return false;
1694  }
1695  return true;
1696  }
1697  }
1698 
1702  private class HashDbIndexer extends SwingWorker<Object, Void> {
1703 
1704  private ProgressHandle progress = null;
1705  private SleuthkitHashSet hashDb = null;
1706 
1707  HashDbIndexer(SleuthkitHashSet hashDb) {
1708  this.hashDb = hashDb;
1709  }
1710 
1711  @Override
1712  protected Object doInBackground() {
1713  hashDb.setIndexing(true);
1714  progress = ProgressHandle.createHandle(
1715  NbBundle.getMessage(this.getClass(), "HashDbManager.progress.indexingHashSet", hashDb.getHashSetName()));
1716  progress.start();
1717  progress.switchToIndeterminate();
1718  try {
1719  SleuthkitJNI.createLookupIndexForHashDatabase(hashDb.getHandle());
1720  } catch (TskCoreException ex) {
1721  Logger.getLogger(HashDbIndexer.class.getName()).log(Level.SEVERE, "Error indexing hash set " + hashDb.getHashSetName(), ex); //NON-NLS
1722  JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(),
1723  NbBundle.getMessage(this.getClass(),
1724  "HashDbManager.dlgMsg.errorIndexingHashSet",
1725  hashDb.getHashSetName()),
1726  NbBundle.getMessage(this.getClass(), "HashDbManager.hashDbIndexingErr"),
1727  JOptionPane.ERROR_MESSAGE);
1728  }
1729  return null;
1730  }
1731 
1732  @Override
1733  protected void done() {
1734  hashDb.setIndexing(false);
1735  progress.finish();
1736 
1737  // see if we got any errors
1738  try {
1739  get();
1740  } catch (InterruptedException | ExecutionException ex) {
1741  logger.log(Level.SEVERE, "Error creating index", ex); //NON-NLS
1743  NbBundle.getMessage(this.getClass(), "HashDbManager.errCreatingIndex.title"),
1744  NbBundle.getMessage(this.getClass(), "HashDbManager.errCreatingIndex.msg", ex.getMessage()),
1746  } // catch and ignore if we were cancelled
1747  catch (java.util.concurrent.CancellationException ex) {
1748  }
1749 
1750  try {
1751  hashDb.firePropertyChange(SleuthkitHashSet.Event.INDEXING_DONE.toString(), null, hashDb);
1752  hashDb.firePropertyChange(HashDbManager.SetEvt.DB_INDEXED.toString(), null, hashDb.getHashSetName());
1753  } catch (Exception e) {
1754  logger.log(Level.SEVERE, "HashDbManager listener threw exception", e); //NON-NLS
1756  NbBundle.getMessage(this.getClass(), "HashDbManager.moduleErr"),
1757  NbBundle.getMessage(this.getClass(), "HashDbManager.moduleErrorListeningToUpdatesMsg"),
1759  }
1760  }
1761  }
1762 }
static synchronized IngestManager getInstance()
synchronized void addPropertyChangeListener(PropertyChangeListener listener)
void checkDbCollision(String path, String hashSetName)
List< CentralRepoFileSet > getAllReferenceSets(CorrelationAttributeInstance.Type correlationType)
static KnownFilesType fromFileKnown(TskData.FileKnown fileKnown)
List< HashDb > getUpdateableHashSets(List< HashDb > hashDbs)
synchronized HashDb addNewHashDatabaseNoSave(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType)
void configureSettings(HashLookupSettings settings, Set< String > officialSetNames)
abstract void firePropertyChange(String propertyName, Object oldValue, Object newValue)
synchronized void removeHashDatabaseNoSave(HashDb hashDb)
String getValidFilePath(String hashSetName, String configuredPath)
synchronized HashDb addNewHashDatabase(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType)
synchronized void removePropertyChangeListener(PropertyChangeListener listener)
void closeHashDatabases(List< HashDb > hashDatabases)
abstract void addPropertyChangeListener(PropertyChangeListener pcl)
synchronized static Logger getLogger(String name)
Definition: Logger.java:124
static void show(String title, String message, MessageType type, ActionListener actionListener)
CorrelationAttributeInstance.Type getCorrelationTypeById(int typeId)
KnownFilesType(String displayName, String identifier, TskData.FileKnown fileKnown, boolean allowSendInboxMessages, boolean defaultSendInboxMessages)
SleuthkitHashSet addHashDatabase(int handle, String hashSetName, boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType)
synchronized HashDb addExistingHashDatabase(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType)
abstract void removePropertyChangeListener(PropertyChangeListener pcl)
List< HashDbInfo > handleNameConflict(List< HashDbInfo > curHashsets, Set< String > officialNames)

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.