Autopsy  3.1
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 - 2014 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.io.File;
23 import java.io.IOException;
24 import java.util.ArrayList;
25 import java.util.HashSet;
26 import java.util.List;
27 import java.util.Set;
28 import javax.swing.JFileChooser;
29 import javax.swing.filechooser.FileNameExtensionFilter;
30 import javax.xml.parsers.DocumentBuilder;
31 import javax.xml.parsers.DocumentBuilderFactory;
32 import javax.xml.parsers.ParserConfigurationException;
33 import org.openide.util.NbBundle;
36 import org.w3c.dom.Document;
37 import org.w3c.dom.Element;
38 import org.w3c.dom.NodeList;
39 import java.beans.PropertyChangeListener;
40 import java.beans.PropertyChangeSupport;
41 import java.util.concurrent.ExecutionException;
42 import java.util.logging.Level;
43 import javax.swing.JOptionPane;
44 import javax.swing.SwingWorker;
45 import org.apache.commons.io.FilenameUtils;
46 import org.apache.commons.io.FileUtils;
47 import org.netbeans.api.progress.ProgressHandle;
48 import org.netbeans.api.progress.ProgressHandleFactory;
57 
59 
64 public class HashDbManager implements PropertyChangeListener {
65 
66  private static final String ROOT_ELEMENT = "hash_sets"; //NON-NLS
67  private static final String SET_ELEMENT = "hash_set"; //NON-NLS
68  private static final String SET_NAME_ATTRIBUTE = "name"; //NON-NLS
69  private static final String SET_TYPE_ATTRIBUTE = "type"; //NON-NLS
70  private static final String SEARCH_DURING_INGEST_ATTRIBUTE = "use_for_ingest"; //NON-NLS
71  private static final String SEND_INGEST_MESSAGES_ATTRIBUTE = "show_inbox_messages"; //NON-NLS
72  private static final String PATH_ELEMENT = "hash_set_path"; //NON-NLS
73  private static final String LEGACY_PATH_NUMBER_ATTRIBUTE = "number"; //NON-NLS
74  private static final String CONFIG_FILE_NAME = "hashsets.xml"; //NON-NLS
75  private static final String XSD_FILE_NAME = "HashsetsSchema.xsd"; //NON-NLS
76  private static final String ENCODING = "UTF-8"; //NON-NLS
77  private static final String HASH_DATABASE_FILE_EXTENSON = "kdb"; //NON-NLS
78  private static HashDbManager instance = null;
79  private final String configFilePath = PlatformUtil.getUserConfigDirectory() + File.separator + CONFIG_FILE_NAME;
80  private List<HashDb> knownHashSets = new ArrayList<>();
81  private List<HashDb> knownBadHashSets = new ArrayList<>();
82  private Set<String> hashSetNames = new HashSet<>();
83  private Set<String> hashSetPaths = new HashSet<>();
84  PropertyChangeSupport changeSupport = new PropertyChangeSupport(HashDbManager.class);
85  private static final Logger logger = Logger.getLogger(HashDbManager.class.getName());
86 
92  public enum SetEvt {
93 
94  DB_ADDED, DB_DELETED, DB_INDEXED
95  };
96 
100  public static synchronized HashDbManager getInstance() {
101  if (instance == null) {
102  instance = new HashDbManager();
103  }
104  return instance;
105  }
106 
107  public synchronized void addPropertyChangeListener(PropertyChangeListener listener) {
108  changeSupport.addPropertyChangeListener(listener);
109  }
110 
111  private HashDbManager() {
114  }
115  }
116 
122  static String getHashDatabaseFileExtension() {
124  }
125 
126  public class HashDbManagerException extends Exception {
127 
128  private HashDbManagerException(String message) {
129  super(message);
130  }
131  }
132 
150  public HashDb addExistingHashDatabase(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType) throws HashDbManagerException {
151  HashDb hashDb = null;
152  try {
153  addExistingHashDatabaseInternal(hashSetName, path, searchDuringIngest, sendIngestMessages, knownFilesType);
154  } catch (TskCoreException ex) {
155  throw new HashDbManagerException(ex.getMessage());
156  }
157 
158  // Save the configuration
159  if (!save()) {
160  throw new HashDbManagerException(NbBundle.getMessage(this.getClass(), "HashDbManager.saveErrorExceptionMsg"));
161  }
162 
163  return hashDb;
164  }
165 
185  synchronized HashDb addExistingHashDatabaseInternal(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType) throws HashDbManagerException, TskCoreException {
186  if (!new File(path).exists()) {
187  throw new HashDbManagerException(NbBundle.getMessage(HashDbManager.class, "HashDbManager.hashDbDoesNotExistExceptionMsg", path));
188  }
189 
190  if (hashSetPaths.contains(path)) {
191  throw new HashDbManagerException(NbBundle.getMessage(HashDbManager.class, "HashDbManager.hashDbAlreadyAddedExceptionMsg", path));
192  }
193 
194  if (hashSetNames.contains(hashSetName)) {
195  throw new HashDbManagerException(NbBundle.getMessage(HashDbManager.class, "HashDbManager.duplicateHashSetNameExceptionMsg", hashSetName));
196  }
197 
198  return addHashDatabase(SleuthkitJNI.openHashDatabase(path), hashSetName, searchDuringIngest, sendIngestMessages, knownFilesType);
199  }
200 
217  public HashDb addNewHashDatabase(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages,
218  HashDb.KnownFilesType knownFilesType) throws HashDbManagerException {
219 
220  HashDb hashDb = null;
221  try {
222  hashDb = addNewHashDatabaseInternal(hashSetName, path, searchDuringIngest, sendIngestMessages, knownFilesType);
223  } catch (TskCoreException ex) {
224  throw new HashDbManagerException(ex.getMessage());
225  }
226 
227  // Save the configuration
228  if (!save()) {
229  throw new HashDbManagerException(NbBundle.getMessage(this.getClass(), "HashDbManager.saveErrorExceptionMsg"));
230  }
231 
232  return hashDb;
233  }
234 
253  synchronized HashDb addNewHashDatabaseInternal(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType) throws HashDbManagerException, TskCoreException {
254  File file = new File(path);
255  if (file.exists()) {
256  throw new HashDbManagerException(NbBundle.getMessage(HashDbManager.class, "HashDbManager.hashDbFileExistsExceptionMsg", path));
257  }
258  if (!FilenameUtils.getExtension(file.getName()).equalsIgnoreCase(HASH_DATABASE_FILE_EXTENSON)) {
259  throw new HashDbManagerException(NbBundle.getMessage(HashDbManager.class, "HashDbManager.illegalHashDbFileNameExtensionMsg",
260  getHashDatabaseFileExtension()));
261  }
262 
263  if (hashSetPaths.contains(path)) {
264  throw new HashDbManagerException(NbBundle.getMessage(HashDbManager.class, "HashDbManager.hashDbAlreadyAddedExceptionMsg", path));
265  }
266 
267  if (hashSetNames.contains(hashSetName)) {
268  throw new HashDbManagerException(NbBundle.getMessage(HashDbManager.class, "HashDbManager.duplicateHashSetNameExceptionMsg", hashSetName));
269  }
270 
271  return addHashDatabase(SleuthkitJNI.createHashDatabase(path), hashSetName, searchDuringIngest, sendIngestMessages, knownFilesType);
272  }
273 
274  private HashDb addHashDatabase(int handle, String hashSetName, boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType) throws TskCoreException {
275  // Wrap an object around the handle.
276  HashDb hashDb = new HashDb(handle, hashSetName, searchDuringIngest, sendIngestMessages, knownFilesType);
277 
278  // Get the indentity data before updating the collections since the
279  // accessor methods may throw.
280  String databasePath = hashDb.getDatabasePath();
281  String indexPath = hashDb.getIndexPath();
282 
283  // Update the collections used to ensure that hash set names are unique
284  // and the same database is not added to the configuration more than once.
285  hashSetNames.add(hashDb.getHashSetName());
286  if (!databasePath.equals("None")) { //NON-NLS
287  hashSetPaths.add(databasePath);
288  }
289  if (!indexPath.equals("None")) { //NON-NLS
290  hashSetPaths.add(indexPath);
291  }
292 
293  // Add the hash database to the appropriate collection for its type.
294  if (hashDb.getKnownFilesType() == HashDb.KnownFilesType.KNOWN) {
295  knownHashSets.add(hashDb);
296  } else {
297  knownBadHashSets.add(hashDb);
298  }
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  synchronized void indexHashDatabase(HashDb hashDb) {
314  hashDb.addPropertyChangeListener(this);
315  HashDbIndexer creator = new HashDbIndexer(hashDb);
316  creator.execute();
317  }
318 
319  @Override
320  public void propertyChange(PropertyChangeEvent event) {
321  if (event.getPropertyName().equals(HashDb.Event.INDEXING_DONE.name())) {
322  HashDb hashDb = (HashDb) event.getNewValue();
323  if (null != hashDb) {
324  try {
325  String indexPath = hashDb.getIndexPath();
326  if (!indexPath.equals("None")) { //NON-NLS
327  hashSetPaths.add(indexPath);
328  }
329  } catch (TskCoreException ex) {
330  Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error getting index path of " + hashDb.getHashSetName() + " hash database after indexing", ex); //NON-NLS
331  }
332  }
333  }
334  }
335 
343  public synchronized void removeHashDatabase(HashDb hashDb) throws HashDbManagerException {
344  // Don't remove a database if ingest is running
345  boolean ingestIsRunning = IngestManager.getInstance().isIngestRunning();
346  if (ingestIsRunning) {
347  throw new HashDbManagerException(NbBundle.getMessage(this.getClass(), "HashDbManager.ingestRunningExceptionMsg"));
348  }
349  removeHashDatabaseInternal(hashDb);
350  if (!save()) {
351  throw new HashDbManagerException(NbBundle.getMessage(this.getClass(), "HashDbManager.saveErrorExceptionMsg"));
352  }
353  }
354 
363  synchronized void removeHashDatabaseInternal(HashDb hashDb) {
364  // Remove the database from whichever hash set list it occupies,
365  // and remove its hash set name from the hash set used to ensure unique
366  // hash set names are used, before undertaking These operations will succeed and constitute
367  // a mostly effective removal, even if the subsequent operations fail.
368  String hashSetName = hashDb.getHashSetName();
369  knownHashSets.remove(hashDb);
370  knownBadHashSets.remove(hashDb);
371  hashSetNames.remove(hashSetName);
372 
373  // Now undertake the operations that could throw.
374  try {
375  hashSetPaths.remove(hashDb.getIndexPath());
376  } catch (TskCoreException ex) {
377  Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error getting index path of " + hashDb.getHashSetName() + " hash database when removing the database", ex); //NON-NLS
378  }
379  try {
380  if (!hashDb.hasIndexOnly()) {
381  hashSetPaths.remove(hashDb.getDatabasePath());
382  }
383  } catch (TskCoreException ex) {
384  Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error getting database path of " + hashDb.getHashSetName() + " hash database when removing the database", ex); //NON-NLS
385  }
386  try {
387  hashDb.close();
388  } catch (TskCoreException ex) {
389  Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error closing " + hashDb.getHashSetName() + " hash database when removing the database", ex); //NON-NLS
390  }
391 
392  // Let any external listeners know that a set has been deleted
393 
394  try {
395  changeSupport.firePropertyChange(SetEvt.DB_DELETED.toString(), null, hashSetName);
396  } catch (Exception e) {
397  logger.log(Level.SEVERE, "HashDbManager listener threw exception", e); //NON-NLS
398  MessageNotifyUtil.Notify.show(
399  NbBundle.getMessage(this.getClass(), "HashDbManager.moduleErr"),
400  NbBundle.getMessage(this.getClass(), "HashDbManager.moduleErrorListeningToUpdatesMsg"),
401  MessageNotifyUtil.MessageType.ERROR);
402  }
403  }
404 
411  public synchronized List<HashDb> getAllHashSets() {
412  List<HashDb> hashDbs = new ArrayList<>();
413  hashDbs.addAll(knownHashSets);
414  hashDbs.addAll(knownBadHashSets);
415  return hashDbs;
416  }
417 
423  public synchronized List<HashDb> getKnownFileHashSets() {
424  List<HashDb> hashDbs = new ArrayList<>();
425  hashDbs.addAll(knownHashSets);
426  return hashDbs;
427  }
428 
434  public synchronized List<HashDb> getKnownBadFileHashSets() {
435  List<HashDb> hashDbs = new ArrayList<>();
436  hashDbs.addAll(knownBadHashSets);
437  return hashDbs;
438  }
439 
445  public synchronized List<HashDb> getUpdateableHashSets() {
446  List<HashDb> updateableDbs = getUpdateableHashSets(knownHashSets);
447  updateableDbs.addAll(getUpdateableHashSets(knownBadHashSets));
448  return updateableDbs;
449  }
450 
451  private List<HashDb> getUpdateableHashSets(List<HashDb> hashDbs) {
452  ArrayList<HashDb> updateableDbs = new ArrayList<>();
453  for (HashDb db : hashDbs) {
454  try {
455  if (db.isUpdateable()) {
456  updateableDbs.add(db);
457  }
458  } catch (TskCoreException ex) {
459  Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error checking updateable status of " + db.getHashSetName() + " hash database", ex); //NON-NLS
460  }
461  }
462  return updateableDbs;
463  }
464 
471  synchronized boolean save() {
473  }
474 
479  public synchronized void loadLastSavedConfiguration() {
480  closeHashDatabases(knownHashSets);
481  closeHashDatabases(knownBadHashSets);
482  hashSetNames.clear();
483  hashSetPaths.clear();
484 
487  }
488  }
489 
490  private void closeHashDatabases(List<HashDb> hashDatabases) {
491  for (HashDb database : hashDatabases) {
492  try {
493  database.close();
494  } catch (TskCoreException ex) {
495  Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error closing " + database.getHashSetName() + " hash database", ex); //NON-NLS
496  }
497  }
498  hashDatabases.clear();
499  }
500 
502  boolean success = false;
503  DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance();
504  try {
505  DocumentBuilder docBuilder = dbfac.newDocumentBuilder();
506  Document doc = docBuilder.newDocument();
507  Element rootEl = doc.createElement(ROOT_ELEMENT);
508  doc.appendChild(rootEl);
509 
510  writeHashDbsToDisk(doc, rootEl, knownHashSets);
511  writeHashDbsToDisk(doc, rootEl, knownBadHashSets);
512 
513  success = XMLUtil.saveDoc(HashDbManager.class, configFilePath, ENCODING, doc);
514  } catch (ParserConfigurationException ex) {
515  Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error saving hash databases", ex); //NON-NLS
516  }
517  return success;
518  }
519 
520  private static void writeHashDbsToDisk(Document doc, Element rootEl, List<HashDb> hashDbs) {
521  for (HashDb db : hashDbs) {
522  // Get the path for the hash database before writing anything, in
523  // case an exception is thrown.
524  String path;
525  try {
526  if (db.hasIndexOnly()) {
527  path = db.getIndexPath();
528  } else {
529  path = db.getDatabasePath();
530  }
531  } catch (TskCoreException ex) {
532  Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error getting path of hash database " + db.getHashSetName() + ", discarding from hash database configuration", ex); //NON-NLS
533  continue;
534  }
535 
536  Element setElement = doc.createElement(SET_ELEMENT);
537  setElement.setAttribute(SET_NAME_ATTRIBUTE, db.getHashSetName());
538  setElement.setAttribute(SET_TYPE_ATTRIBUTE, db.getKnownFilesType().toString());
539  setElement.setAttribute(SEARCH_DURING_INGEST_ATTRIBUTE, Boolean.toString(db.getSearchDuringIngest()));
540  setElement.setAttribute(SEND_INGEST_MESSAGES_ATTRIBUTE, Boolean.toString(db.getSendIngestMessages()));
541  Element pathElement = doc.createElement(PATH_ELEMENT);
542  pathElement.setTextContent(path);
543  setElement.appendChild(pathElement);
544  rootEl.appendChild(setElement);
545  }
546  }
547 
549  File f = new File(configFilePath);
550  return f.exists() && f.canRead() && f.canWrite();
551  }
552 
554  boolean updatedSchema = false;
555 
556  // Open the XML document that implements the configuration file.
557  final Document doc = XMLUtil.loadDoc(HashDbManager.class, configFilePath);
558  if (doc == null) {
559  return false;
560  }
561 
562  // Get the root element.
563  Element root = doc.getDocumentElement();
564  if (root == null) {
565  Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error loading hash sets: invalid file format."); //NON-NLS
566  return false;
567  }
568 
569  // Get the hash set elements.
570  NodeList setsNList = root.getElementsByTagName(SET_ELEMENT);
571  int numSets = setsNList.getLength();
572  if (numSets == 0) {
573  Logger.getLogger(HashDbManager.class.getName()).log(Level.WARNING, "No element hash_set exists."); //NON-NLS
574  }
575 
576  // Create HashDb objects for each hash set element. Skip to the next hash database if the definition of
577  // a particular hash database is not well-formed.
578  String attributeErrorMessage = " attribute was not set for hash_set at index {0}, cannot make instance of HashDb class"; //NON-NLS
579  String elementErrorMessage = " element was not set for hash_set at index {0}, cannot make instance of HashDb class"; //NON-NLS
580  for (int i = 0; i < numSets; ++i) {
581  Element setEl = (Element) setsNList.item(i);
582 
583  String hashSetName = setEl.getAttribute(SET_NAME_ATTRIBUTE);
584  if (hashSetName.isEmpty()) {
585  Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, SET_NAME_ATTRIBUTE + attributeErrorMessage, i);
586  continue;
587  }
588 
589  // Handle configurations saved before duplicate hash set names were not permitted.
590  if (hashSetNames.contains(hashSetName)) {
591  int suffix = 0;
592  String newHashSetName;
593  do {
594  ++suffix;
595  newHashSetName = hashSetName + suffix;
596  } while (hashSetNames.contains(newHashSetName));
597  JOptionPane.showMessageDialog(null,
598  NbBundle.getMessage(this.getClass(),
599  "HashDbManager.replacingDuplicateHashsetNameMsg",
600  hashSetName, newHashSetName),
601  NbBundle.getMessage(this.getClass(), "HashDbManager.openHashDbErr"),
602  JOptionPane.ERROR_MESSAGE);
603  hashSetName = newHashSetName;
604  }
605 
606  String knownFilesType = setEl.getAttribute(SET_TYPE_ATTRIBUTE);
607  if (knownFilesType.isEmpty()) {
608  Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, SET_TYPE_ATTRIBUTE + attributeErrorMessage, i);
609  continue;
610  }
611 
612  // Handle legacy known files types.
613  if (knownFilesType.equals("NSRL")) { //NON-NLS
614  knownFilesType = HashDb.KnownFilesType.KNOWN.toString();
615  updatedSchema = true;
616  }
617 
618  final String searchDuringIngest = setEl.getAttribute(SEARCH_DURING_INGEST_ATTRIBUTE);
619  if (searchDuringIngest.isEmpty()) {
620  Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, SEARCH_DURING_INGEST_ATTRIBUTE + attributeErrorMessage, i);
621  continue;
622  }
623  Boolean seearchDuringIngestFlag = Boolean.parseBoolean(searchDuringIngest);
624 
625  final String sendIngestMessages = setEl.getAttribute(SEND_INGEST_MESSAGES_ATTRIBUTE);
626  if (searchDuringIngest.isEmpty()) {
627  Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, SEND_INGEST_MESSAGES_ATTRIBUTE + attributeErrorMessage, i);
628  continue;
629  }
630  Boolean sendIngestMessagesFlag = Boolean.parseBoolean(sendIngestMessages);
631 
632  String dbPath;
633  NodeList pathsNList = setEl.getElementsByTagName(PATH_ELEMENT);
634  if (pathsNList.getLength() > 0) {
635  Element pathEl = (Element) pathsNList.item(0); // Shouldn't be more than one.
636 
637  // Check for legacy path number attribute.
638  String legacyPathNumber = pathEl.getAttribute(LEGACY_PATH_NUMBER_ATTRIBUTE);
639  if (null != legacyPathNumber && !legacyPathNumber.isEmpty()) {
640  updatedSchema = true;
641  }
642 
643  dbPath = pathEl.getTextContent();
644  if (dbPath.isEmpty()) {
645  Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, PATH_ELEMENT + elementErrorMessage, i);
646  continue;
647  }
648  } else {
649  Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, PATH_ELEMENT + elementErrorMessage, i);
650  continue;
651  }
652  dbPath = getValidFilePath(hashSetName, dbPath);
653 
654  if (null != dbPath) {
655  try {
656  addExistingHashDatabaseInternal(hashSetName, dbPath, seearchDuringIngestFlag, sendIngestMessagesFlag, HashDb.KnownFilesType.valueOf(knownFilesType));
657  } catch (HashDbManagerException | TskCoreException ex) {
658  Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error opening hash database", ex); //NON-NLS
659  JOptionPane.showMessageDialog(null,
660  NbBundle.getMessage(this.getClass(),
661  "HashDbManager.unableToOpenHashDbMsg", dbPath),
662  NbBundle.getMessage(this.getClass(), "HashDbManager.openHashDbErr"),
663  JOptionPane.ERROR_MESSAGE);
664  }
665  } else {
666  Logger.getLogger(HashDbManager.class.getName()).log(Level.WARNING, "No valid path for hash_set at index {0}, cannot make instance of HashDb class", i); //NON-NLS
667  }
668  }
669 
670  if (updatedSchema) {
671  String backupFilePath = configFilePath + ".v1_backup"; //NON-NLS
672  String messageBoxTitle = NbBundle.getMessage(this.getClass(),
673  "HashDbManager.msgBoxTitle.confFileFmtChanged");
674  String baseMessage = NbBundle.getMessage(this.getClass(),
675  "HashDbManager.baseMessage.updatedFormatHashDbConfig");
676  try {
677  FileUtils.copyFile(new File(configFilePath), new File(backupFilePath));
678  JOptionPane.showMessageDialog(null,
679  NbBundle.getMessage(this.getClass(),
680  "HashDbManager.savedBackupOfOldConfigMsg",
681  baseMessage, backupFilePath),
682  messageBoxTitle,
683  JOptionPane.INFORMATION_MESSAGE);
684  } catch (IOException ex) {
685  Logger.getLogger(HashDbManager.class.getName()).log(Level.WARNING, "Failed to save backup of old format configuration file to " + backupFilePath, ex); //NON-NLS
686  JOptionPane.showMessageDialog(null, baseMessage, messageBoxTitle, JOptionPane.INFORMATION_MESSAGE);
687  }
688 
690  }
691 
692  return true;
693  }
694 
695  private String getValidFilePath(String hashSetName, String configuredPath) {
696  // Check the configured path.
697  File database = new File(configuredPath);
698  if (database.exists()) {
699  return configuredPath;
700  }
701 
702  // Give the user an opportunity to find the desired file.
703  String newPath = null;
704  if (JOptionPane.showConfirmDialog(null,
705  NbBundle.getMessage(this.getClass(), "HashDbManager.dlgMsg.dbNotFoundAtLoc",
706  hashSetName, configuredPath),
707  NbBundle.getMessage(this.getClass(), "HashDbManager.dlgTitle.MissingDb"),
708  JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
709  newPath = searchForFile();
710  if (null != newPath && !newPath.isEmpty()) {
711  database = new File(newPath);
712  if (!database.exists()) {
713  newPath = null;
714  }
715  }
716  }
717  return newPath;
718  }
719 
720  private String searchForFile() {
721  String filePath = null;
722  JFileChooser fc = new JFileChooser();
723  fc.setDragEnabled(false);
724  fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
725  String[] EXTENSION = new String[]{"txt", "idx", "hash", "Hash", "kdb"}; //NON-NLS
726  FileNameExtensionFilter filter = new FileNameExtensionFilter(
727  NbBundle.getMessage(this.getClass(), "HashDbManager.fileNameExtensionFilter.title"), EXTENSION);
728  fc.setFileFilter(filter);
729  fc.setMultiSelectionEnabled(false);
730  if (fc.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
731  File f = fc.getSelectedFile();
732  try {
733  filePath = f.getCanonicalPath();
734  } catch (IOException ex) {
735  Logger.getLogger(HashDbManager.class.getName()).log(Level.WARNING, "Couldn't get selected file path", ex); //NON-NLS
736  }
737  }
738  return filePath;
739  }
740 
745  public static class HashDb {
746 
751  public enum KnownFilesType {
752 
753  KNOWN(NbBundle.getMessage(HashDbManager.class, "HashDbManager.known.text")),
754  KNOWN_BAD(NbBundle.getMessage(HashDbManager.class, "HashDbManager.knownBad.text"));
755  private String displayName;
756 
757  private KnownFilesType(String displayName) {
758  this.displayName = displayName;
759  }
760 
761  public String getDisplayName() {
762  return this.displayName;
763  }
764  }
765 
769  public enum Event {
770 
771  INDEXING_DONE
772  }
773  private int handle;
774  private String hashSetName;
775  private boolean searchDuringIngest;
776  private boolean sendIngestMessages;
778  private boolean indexing;
779  private final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
780 
781  private HashDb(int handle, String hashSetName, boolean useForIngest, boolean sendHitMessages, KnownFilesType knownFilesType) {
782  this.handle = handle;
783  this.hashSetName = hashSetName;
784  this.searchDuringIngest = useForIngest;
785  this.sendIngestMessages = sendHitMessages;
786  this.knownFilesType = knownFilesType;
787  this.indexing = false;
788  }
789 
793  public void addPropertyChangeListener(PropertyChangeListener pcl) {
794  propertyChangeSupport.addPropertyChangeListener(pcl);
795  }
796 
800  public void removePropertyChangeListener(PropertyChangeListener pcl) {
801  propertyChangeSupport.removePropertyChangeListener(pcl);
802  }
803 
804  public String getHashSetName() {
805  return hashSetName;
806  }
807 
808  public String getDatabasePath() throws TskCoreException {
809  return SleuthkitJNI.getHashDatabasePath(handle);
810  }
811 
812  public String getIndexPath() throws TskCoreException {
813  return SleuthkitJNI.getHashDatabaseIndexPath(handle);
814  }
815 
817  return knownFilesType;
818  }
819 
820  public boolean getSearchDuringIngest() {
821  return searchDuringIngest;
822  }
823 
824  void setSearchDuringIngest(boolean useForIngest) {
825  this.searchDuringIngest = useForIngest;
826  }
827 
828  public boolean getSendIngestMessages() {
829  return sendIngestMessages;
830  }
831 
832  void setSendIngestMessages(boolean showInboxMessages) {
833  this.sendIngestMessages = showInboxMessages;
834  }
835 
841  public boolean isUpdateable() throws TskCoreException {
842  return SleuthkitJNI.isUpdateableHashDatabase(this.handle);
843  }
844 
852  public void addHashes(Content content) throws TskCoreException {
853  addHashes(content, null);
854  }
855 
865  public void addHashes(Content content, String comment) throws TskCoreException {
866  // This only works for AbstractFiles and MD5 hashes at present.
867  assert content instanceof AbstractFile;
868  if (content instanceof AbstractFile) {
869  AbstractFile file = (AbstractFile) content;
870  if (null != file.getMd5Hash()) {
871  SleuthkitJNI.addToHashDatabase(null, file.getMd5Hash(), null, null, comment, handle);
872  }
873  }
874  }
875 
882  public void addHashes(List<HashEntry> hashes) throws TskCoreException {
883  SleuthkitJNI.addToHashDatabase(hashes, handle);
884  }
885 
892  public boolean lookupMD5Quick(Content content) throws TskCoreException {
893  boolean result = false;
894  assert content instanceof AbstractFile;
895  if (content instanceof AbstractFile) {
896  AbstractFile file = (AbstractFile) content;
897  if (null != file.getMd5Hash()) {
899  }
900  }
901  return result;
902  }
903 
910  public HashHitInfo lookupMD5(Content content) throws TskCoreException {
911  HashHitInfo result = null;
912  // This only works for AbstractFiles and MD5 hashes at present.
913  assert content instanceof AbstractFile;
914  if (content instanceof AbstractFile) {
915  AbstractFile file = (AbstractFile) content;
916  if (null != file.getMd5Hash()) {
918  }
919  }
920  return result;
921  }
922 
923 
924  boolean hasIndex() throws TskCoreException {
926  }
927 
928  boolean hasIndexOnly() throws TskCoreException {
929  return SleuthkitJNI.hashDatabaseIsIndexOnly(handle);
930  }
931 
932  boolean canBeReIndexed() throws TskCoreException {
933  return SleuthkitJNI.hashDatabaseCanBeReindexed(handle);
934  }
935 
936  boolean isIndexing() {
937  return indexing;
938  }
939 
940  private void close() throws TskCoreException {
942  }
943  }
944 
948  private class HashDbIndexer extends SwingWorker<Object, Void> {
949 
950  private ProgressHandle progress = null;
951  private HashDb hashDb = null;
952 
953  HashDbIndexer(HashDb hashDb) {
954  this.hashDb = hashDb;
955  }
956 
957  ;
958 
959  @Override
960  protected Object doInBackground() {
961  hashDb.indexing = true;
962  progress = ProgressHandleFactory.createHandle(
963  NbBundle.getMessage(this.getClass(), "HashDbManager.progress.indexingHashSet", hashDb.hashSetName));
964  progress.start();
965  progress.switchToIndeterminate();
966  try {
968  } catch (TskCoreException ex) {
969  Logger.getLogger(HashDb.class.getName()).log(Level.SEVERE, "Error indexing hash database", ex); //NON-NLS
970  JOptionPane.showMessageDialog(null,
971  NbBundle.getMessage(this.getClass(),
972  "HashDbManager.dlgMsg.errorIndexingHashSet",
973  hashDb.getHashSetName()),
974  NbBundle.getMessage(this.getClass(), "HashDbManager.hashDbIndexingErr"),
975  JOptionPane.ERROR_MESSAGE);
976  }
977  return null;
978  }
979 
980  @Override
981  protected void done() {
982  hashDb.indexing = false;
983  progress.finish();
984 
985  // see if we got any errors
986  try {
987  get();
988  } catch (InterruptedException | ExecutionException ex) {
989  logger.log(Level.SEVERE, "Error creating index", ex); //NON-NLS
991  NbBundle.getMessage(this.getClass(), "HashDbManager.errCreatingIndex.title"),
992  NbBundle.getMessage(this.getClass(), "HashDbManager.errCreatingIndex.msg", ex.getMessage()),
994  }
995  // catch and ignore if we were cancelled
996  catch (java.util.concurrent.CancellationException ex ) { }
997 
998  try {
999  hashDb.propertyChangeSupport.firePropertyChange(HashDb.Event.INDEXING_DONE.toString(), null, hashDb);
1000  hashDb.propertyChangeSupport.firePropertyChange(HashDbManager.SetEvt.DB_INDEXED.toString(), null, hashDb.getHashSetName());
1001  } catch (Exception e) {
1002  logger.log(Level.SEVERE, "HashDbManager listener threw exception", e); //NON-NLS
1004  NbBundle.getMessage(this.getClass(), "HashDbManager.moduleErr"),
1005  NbBundle.getMessage(this.getClass(), "HashDbManager.moduleErrorListeningToUpdatesMsg"),
1007  }
1008  }
1009  }
1010 }
static String getHashDatabaseIndexPath(int dbHandle)
static void createLookupIndexForHashDatabase(int dbHandle)
static void addToHashDatabase(String filename, String md5, String sha1, String sha256, String comment, int dbHandle)
static synchronized IngestManager getInstance()
static< T > Document loadDoc(Class< T > clazz, String xmlPath)
Definition: XMLUtil.java:221
synchronized void addPropertyChangeListener(PropertyChangeListener listener)
HashDb addExistingHashDatabase(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType)
HashDb addHashDatabase(int handle, String hashSetName, boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType)
static HashHitInfo lookupInHashDatabaseVerbose(String hash, int dbHandle)
static void writeHashDbsToDisk(Document doc, Element rootEl, List< HashDb > hashDbs)
List< HashDb > getUpdateableHashSets(List< HashDb > hashDbs)
static boolean hashDatabaseIsIndexOnly(int dbHandle)
HashDb addNewHashDatabase(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType)
String getValidFilePath(String hashSetName, String configuredPath)
static boolean lookupInHashDatabase(String hash, int dbHandle)
static boolean hashDatabaseHasLookupIndex(int dbHandle)
static void show(String title, String message, MessageType type, ActionListener actionListener)
static boolean isUpdateableHashDatabase(int dbHandle)
HashDb(int handle, String hashSetName, boolean useForIngest, boolean sendHitMessages, KnownFilesType knownFilesType)
static String getHashDatabasePath(int dbHandle)
static Logger getLogger(String name)
Definition: Logger.java:131
static void closeHashDatabase(int dbHandle)
static< T > boolean saveDoc(Class< T > clazz, String xmlPath, String encoding, final Document doc)
Definition: XMLUtil.java:263

Copyright © 2012-2015 Basis Technology. Generated on: Mon Oct 19 2015
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.