Autopsy 4.22.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-2021 Basis Technology Corp.
5 * Contact: carrier <at> sleuthkit <dot> org
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19package org.sleuthkit.autopsy.modules.hashdatabase;
20
21import java.beans.PropertyChangeEvent;
22import java.beans.PropertyChangeListener;
23import java.beans.PropertyChangeSupport;
24import java.io.File;
25import java.io.FilenameFilter;
26import java.io.IOException;
27import java.util.ArrayList;
28import java.util.HashSet;
29import java.util.List;
30import java.util.MissingResourceException;
31import java.util.Objects;
32import java.util.Set;
33import java.util.concurrent.ExecutionException;
34import java.util.logging.Level;
35import java.util.regex.Matcher;
36import java.util.regex.Pattern;
37import java.util.stream.Collectors;
38import java.util.stream.Stream;
39import javax.swing.JFileChooser;
40import javax.swing.JOptionPane;
41import javax.swing.SwingWorker;
42import javax.swing.filechooser.FileNameExtensionFilter;
43import org.apache.commons.io.FilenameUtils;
44import org.apache.commons.lang.StringUtils;
45import org.netbeans.api.progress.ProgressHandle;
46import org.openide.modules.InstalledFileLocator;
47import org.openide.util.NbBundle;
48import org.openide.util.NbBundle.Messages;
49import org.openide.windows.WindowManager;
50import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeNormalizationException;
51import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance;
52import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoException;
53import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoFileInstance;
54import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoFileSet;
55import org.sleuthkit.autopsy.core.RuntimeProperties;
56import org.sleuthkit.autopsy.coreutils.Logger;
57import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
58import org.sleuthkit.autopsy.ingest.IngestManager;
59import org.sleuthkit.autopsy.modules.hashdatabase.HashLookupSettings.HashDbInfo;
60import org.sleuthkit.datamodel.AbstractFile;
61import org.sleuthkit.datamodel.Content;
62import org.sleuthkit.datamodel.HashEntry;
63import org.sleuthkit.datamodel.HashHitInfo;
64import org.sleuthkit.datamodel.SleuthkitJNI;
65import org.sleuthkit.datamodel.TskCoreException;
66import org.sleuthkit.datamodel.TskData;
67import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
68import org.sleuthkit.autopsy.guiutils.JFileChooserFactory;
69import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb.KnownFilesType;
70
75public class HashDbManager implements PropertyChangeListener {
76
77 private static final String HASH_DATABASE_FILE_EXTENSON = "kdb"; //NON-NLS
78 private static HashDbManager instance = null;
79 private List<HashDb> hashSets = new ArrayList<>();
80 private Set<String> hashSetNames = new HashSet<>();
81 private Set<String> hashSetPaths = new HashSet<>();
82
83 private List<HashDb> officialHashSets = new ArrayList<>();
84 private Set<String> officialHashSetNames = new HashSet<>();
85 private Set<String> officialHashSetPaths = new HashSet<>();
86
87 PropertyChangeSupport changeSupport = new PropertyChangeSupport(HashDbManager.class);
88 private static final Logger logger = Logger.getLogger(HashDbManager.class.getName());
89 private boolean allDatabasesLoadedCorrectly = false;
90
91 private static final String OFFICIAL_HASH_SETS_FOLDER = "OfficialHashSets";
92 private static final String KDB_EXT = "kdb";
93
94 private static final String DB_NAME_PARAM = "dbName";
95 private static final String KNOWN_STATUS_PARAM = "knownStatus";
96 private static final Pattern OFFICIAL_FILENAME = Pattern.compile("(?<" + DB_NAME_PARAM + ">.+?)\\.(?<" + KNOWN_STATUS_PARAM + ">.+?)\\." + KDB_EXT);
97
99
100 private static final FilenameFilter DEFAULT_KDB_FILTER = new FilenameFilter() {
101 @Override
102 public boolean accept(File dir, String name) {
103 return name.endsWith("." + KDB_EXT);
104 }
105 };
106
112 public enum SetEvt {
113
115 };
116
122 public static synchronized HashDbManager getInstance() {
123 if (instance == null) {
124 instance = new HashDbManager();
125 }
126 return instance;
127 }
128
129 public synchronized void addPropertyChangeListener(PropertyChangeListener listener) {
130 changeSupport.addPropertyChangeListener(listener);
131 }
132
133 public synchronized void removePropertyChangeListener(PropertyChangeListener listener) {
134 changeSupport.removePropertyChangeListener(listener);
135 }
136
137 synchronized boolean verifyAllDatabasesLoadedCorrectly() {
139 }
140
145
151 static String getHashDatabaseFileExtension() {
153 }
154
155 public class HashDbManagerException extends Exception {
156
157 private static final long serialVersionUID = 1L;
158
159 private HashDbManagerException(String message) {
160 super(message);
161 }
162
163 private HashDbManagerException(String message, Throwable exception) {
164 super(message, exception);
165 }
166 }
167
187 public synchronized HashDb addExistingHashDatabase(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType) throws HashDbManagerException {
188 HashDb hashDb = null;
189 hashDb = this.addExistingHashDatabaseNoSave(hashSetName, path, searchDuringIngest, sendIngestMessages, knownFilesType);
190 this.save();
191 return hashDb;
192 }
193
194 synchronized HashDb addExistingHashDatabaseNoSave(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType) throws HashDbManagerException {
195 HashDb hashDb = null;
196 try {
197 if (!new File(path).exists()) {
198 throw new HashDbManagerException(NbBundle.getMessage(HashDbManager.class, "HashDbManager.hashDbDoesNotExistExceptionMsg", path));
199 }
200
201 checkDbCollision(path, hashSetName);
202
203 hashDb = addHashDatabase(SleuthkitJNI.openHashDatabase(path), hashSetName, searchDuringIngest, sendIngestMessages, knownFilesType);
204 } catch (TskCoreException ex) {
205 throw new HashDbManagerException(ex.getMessage());
206 }
207 return hashDb;
208 }
209
228 public synchronized HashDb addNewHashDatabase(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages,
229 HashDb.KnownFilesType knownFilesType) throws HashDbManagerException {
230
231 HashDb hashDb = null;
232 hashDb = this.addNewHashDatabaseNoSave(hashSetName, path, searchDuringIngest, sendIngestMessages, knownFilesType);
233
234 this.save();
235
236 return hashDb;
237 }
238
239 public synchronized HashDb addNewHashDatabaseNoSave(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages,
240 HashDb.KnownFilesType knownFilesType) throws HashDbManagerException {
241 HashDb hashDb = null;
242 try {
243 File file = new File(path);
244 if (file.exists()) {
245 throw new HashDbManagerException(NbBundle.getMessage(HashDbManager.class, "HashDbManager.hashDbFileExistsExceptionMsg", path));
246 }
247 if (!FilenameUtils.getExtension(file.getName()).equalsIgnoreCase(HASH_DATABASE_FILE_EXTENSON)) {
248 throw new HashDbManagerException(NbBundle.getMessage(HashDbManager.class, "HashDbManager.illegalHashDbFileNameExtensionMsg",
249 getHashDatabaseFileExtension()));
250 }
251
252 checkDbCollision(path, hashSetName);
253
254 hashDb = addHashDatabase(SleuthkitJNI.createHashDatabase(path), hashSetName, searchDuringIngest, sendIngestMessages, knownFilesType);
255 } catch (TskCoreException ex) {
256 throw new HashDbManagerException(ex.getMessage());
257 }
258 return hashDb;
259 }
260
272 private void checkDbCollision(String path, String hashSetName) throws HashDbManagerException, MissingResourceException {
273 if (hashSetPaths.contains(path) || officialHashSetPaths.contains(path)) {
274 throw new HashDbManagerException(NbBundle.getMessage(HashDbManager.class, "HashDbManager.hashDbAlreadyAddedExceptionMsg", path));
275 }
276
277 if (hashSetNames.contains(hashSetName) || officialHashSetNames.contains(hashSetName)) {
278 throw new HashDbManagerException(NbBundle.getMessage(HashDbManager.class, "HashDbManager.duplicateHashSetNameExceptionMsg", hashSetName));
279 }
280 }
281
282 private SleuthkitHashSet addHashDatabase(int handle, String hashSetName, boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType) throws TskCoreException {
283 // Wrap an object around the handle.
284 SleuthkitHashSet hashDb = new SleuthkitHashSet(handle, hashSetName, searchDuringIngest, sendIngestMessages, knownFilesType);
285
286 // Get the indentity data before updating the collections since the
287 // accessor methods may throw.
288 String databasePath = hashDb.getDatabasePath();
289 String indexPath = hashDb.getIndexPath();
290
291 // Update the collections used to ensure that hash set names are unique
292 // and the same database is not added to the configuration more than once.
293 hashSetNames.add(hashDb.getHashSetName());
294 if (!databasePath.equals("None")) { //NON-NLS
295 hashSetPaths.add(databasePath);
296 }
297 if (!indexPath.equals("None")) { //NON-NLS
298 hashSetPaths.add(indexPath);
299 }
300
301 // Add the hash database to the collection
302 hashSets.add(hashDb);
303
304 // Let any external listeners know that there's a new set
305 try {
306 changeSupport.firePropertyChange(SetEvt.DB_ADDED.toString(), null, hashSetName);
307 } catch (Exception e) {
308 logger.log(Level.SEVERE, "HashDbManager listener threw exception", e); //NON-NLS
310 NbBundle.getMessage(this.getClass(), "HashDbManager.moduleErr"),
311 NbBundle.getMessage(this.getClass(), "HashDbManager.moduleErrorListeningToUpdatesMsg"),
313 }
314 return hashDb;
315 }
316
317 CentralRepoHashSet addExistingCentralRepoHashSet(String hashSetName, String version, int referenceSetID,
318 boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType,
319 boolean readOnly) throws TskCoreException {
320
322 throw new TskCoreException("Could not load central repository hash set " + hashSetName + " - central repository is not enabled");
323 }
324
325 CentralRepoHashSet db = new CentralRepoHashSet(hashSetName, version, referenceSetID, searchDuringIngest,
326 sendIngestMessages, knownFilesType, readOnly);
327
328 if (!db.isValid()) {
329 throw new TskCoreException("Error finding hash set " + hashSetName + " in central repository");
330 }
331
332 // Add the hash database to the collection
333 if(!hashSets.contains(db)) {
334 hashSets.add(db);
335
336 // Let any external listeners know that there's a new set
337 try {
338 changeSupport.firePropertyChange(SetEvt.DB_ADDED.toString(), null, hashSetName);
339 } catch (Exception e) {
340 logger.log(Level.SEVERE, "HashDbManager listener threw exception", e); //NON-NLS
341 MessageNotifyUtil.Notify.show(
342 NbBundle.getMessage(this.getClass(), "HashDbManager.moduleErr"),
343 NbBundle.getMessage(this.getClass(), "HashDbManager.moduleErrorListeningToUpdatesMsg"),
344 MessageNotifyUtil.MessageType.ERROR);
345 }
346 }
347 return db;
348
349 }
350
351 synchronized void indexHashDatabase(SleuthkitHashSet hashDb) {
352 hashDb.addPropertyChangeListener(this);
353 HashDbIndexer creator = new HashDbIndexer(hashDb);
354 creator.execute();
355 }
356
357 @Override
358 public void propertyChange(PropertyChangeEvent event) {
359 if (event.getPropertyName().equals(SleuthkitHashSet.Event.INDEXING_DONE.name())) {
360 SleuthkitHashSet hashDb = (SleuthkitHashSet) event.getNewValue();
361 if (null != hashDb) {
362 try {
363 String indexPath = hashDb.getIndexPath();
364 if (!indexPath.equals("None")) { //NON-NLS
365 hashSetPaths.add(indexPath);
366 }
367 } catch (TskCoreException ex) {
368 Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error getting index path of " + hashDb.getHashSetName() + " hash set after indexing", ex); //NON-NLS
369 }
370 }
371 }
372 }
373
382 public synchronized void removeHashDatabase(HashDb hashDb) throws HashDbManagerException {
383 this.removeHashDatabaseNoSave(hashDb);
384 this.save();
385 }
386
387 public synchronized void removeHashDatabaseNoSave(HashDb hashDb) throws HashDbManagerException {
388 // Don't remove a database if ingest is running
389 boolean ingestIsRunning = IngestManager.getInstance().isIngestRunning();
390 if (ingestIsRunning) {
391 throw new HashDbManagerException(NbBundle.getMessage(this.getClass(), "HashDbManager.ingestRunningExceptionMsg"));
392 }
393 // Remove the database from whichever hash set list it occupies,
394 // and remove its hash set name from the hash set used to ensure unique
395 // hash set names are used, before undertaking These operations will succeed and constitute
396 // a mostly effective removal, even if the subsequent operations fail.
397 String hashSetName = hashDb.getHashSetName();
398 hashSetNames.remove(hashSetName);
399 hashSets.remove(hashDb);
400
401 // Now undertake the operations that could throw.
402 // Indexing is only relevanet for sleuthkit hashsets
403 if (hashDb instanceof SleuthkitHashSet) {
404 SleuthkitHashSet hashDatabase = (SleuthkitHashSet) hashDb;
405 try {
406 if (hashDatabase.hasIndex()) {
407 hashSetPaths.remove(hashDatabase.getIndexPath());
408 }
409 } catch (TskCoreException ex) {
410 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
411 }
412
413 try {
414 if (!hashDatabase.hasIndexOnly()) {
415 hashSetPaths.remove(hashDatabase.getDatabasePath());
416 }
417 } catch (TskCoreException ex) {
418 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
419 }
420
421 try {
422 hashDatabase.close();
423 } catch (TskCoreException ex) {
424 Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error closing " + hashDb.getHashSetName() + " hash set when removing the hash set", ex); //NON-NLS
425 }
426 }
427
428 // Let any external listeners know that a set has been deleted
429 try {
430 changeSupport.firePropertyChange(SetEvt.DB_DELETED.toString(), null, hashSetName);
431 } catch (Exception e) {
432 logger.log(Level.SEVERE, "HashDbManager listener threw exception", e); //NON-NLS
434 NbBundle.getMessage(this.getClass(), "HashDbManager.moduleErr"),
435 NbBundle.getMessage(this.getClass(), "HashDbManager.moduleErrorListeningToUpdatesMsg"),
437 }
438 }
439
440 void save() throws HashDbManagerException {
441 try {
442 if (!HashLookupSettings.writeSettings(new HashLookupSettings(HashLookupSettings.convertHashSetList(this.hashSets)))) {
443 throw new HashDbManagerException(NbBundle.getMessage(this.getClass(), "HashDbManager.saveErrorExceptionMsg"));
444 }
445 } catch (HashLookupSettings.HashLookupSettingsException ex) {
446 throw new HashDbManagerException(NbBundle.getMessage(this.getClass(), "HashDbManager.saveErrorExceptionMsg"));
447 }
448 }
449
457 public synchronized List<HashDb> getAllHashSets() {
458 try {
460 } catch (TskCoreException ex) {
461 Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error loading central repository hash sets", ex); //NON-NLS
462 }
463
464 return Stream.concat(this.officialHashSets.stream(), this.hashSets.stream())
465 .collect(Collectors.toList());
466 }
467
473 public synchronized List<HashDb> getKnownFileHashSets() {
474 return getAllHashSets()
475 .stream()
476 .filter((db) -> (db.getKnownFilesType() == HashDb.KnownFilesType.KNOWN))
477 .collect(Collectors.toList());
478 }
479
485 public synchronized List<HashDb> getKnownBadFileHashSets() {
486 return getAllHashSets()
487 .stream()
488 .filter((db) -> (db.getKnownFilesType() == HashDb.KnownFilesType.KNOWN_BAD))
489 .collect(Collectors.toList());
490 }
491
497 public synchronized List<HashDb> getUpdateableHashSets() {
499 }
500
501 private List<HashDb> getUpdateableHashSets(List<HashDb> hashDbs) {
502 return hashDbs
503 .stream()
504 .filter((HashDb db) -> {
505 try {
506 return db.isUpdateable();
507 } catch (TskCoreException ex) {
508 Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error checking updateable status of " + db.getHashSetName() + " hash set", ex); //NON-NLS
509 return false;
510 }
511 })
512 .collect(Collectors.toList());
513 }
514
515 private List<HashDbInfo> getCentralRepoHashSetsFromDatabase() {
516 List<HashDbInfo> crHashSets = new ArrayList<>();
518 try {
520 for (CentralRepoFileSet globalSet : crSets) {
521
522 // Defaults for fields not stored in the central repository:
523 // searchDuringIngest: false
524 // sendIngestMessages: true if the hash set is notable
525 boolean sendIngestMessages = KnownFilesType.fromFileKnown(globalSet.getFileKnownStatus()).equals(HashDb.KnownFilesType.KNOWN_BAD);
526 crHashSets.add(new HashDbInfo(globalSet.getSetName(), globalSet.getVersion(),
527 globalSet.getGlobalSetID(), KnownFilesType.fromFileKnown(globalSet.getFileKnownStatus()), globalSet.isReadOnly(), false, sendIngestMessages));
528 }
529 } catch (CentralRepoException ex) {
530 Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error loading central repository hash sets", ex); //NON-NLS
531 }
532 }
533 return crHashSets;
534 }
535
540 public synchronized void loadLastSavedConfiguration() {
541 closeHashDatabases(this.hashSets);
542 hashSetNames.clear();
543 hashSetPaths.clear();
544
546 }
547
548 private void closeHashDatabases(List<HashDb> hashDatabases) {
549 for (HashDb database : hashDatabases) {
550 if (database instanceof SleuthkitHashSet) {
551 try {
552 ((SleuthkitHashSet) database).close();
553 } catch (TskCoreException ex) {
554 Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error closing " + database.getHashSetName() + " hash set", ex); //NON-NLS
555 }
556 }
557 }
558 hashDatabases.clear();
559 }
560
563
564 try {
565 HashLookupSettings settings = HashLookupSettings.readSettings();
567 } catch (HashLookupSettings.HashLookupSettingsException ex) {
568 Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Could not read Hash lookup settings from disk.", ex);
569 }
570 }
571
576 private void loadOfficialHashSets() {
577 officialHashSetPaths = new HashSet<>();
578 officialHashSetNames = new HashSet<>();
579
580 try {
582 officialHashSets.forEach(db -> {
583 officialHashSetNames.add(db.getHashSetName());
584 try {
585 String databasePath = db.getDatabasePath();
586 String indexPath = db.getIndexPath();
587
588 if (StringUtils.isNotBlank(databasePath) && !databasePath.equals("None")) { //NON-NLS
589 officialHashSetPaths.add(databasePath);
590 }
591 if (StringUtils.isNotBlank(indexPath) && !indexPath.equals("None")) { //NON-NLS
592 officialHashSetPaths.add(indexPath);
593 }
594 } catch (TskCoreException ex) {
595 logger.log(Level.SEVERE, "There was an error loading the official hash set name.", ex);
596 }
597 });
598 } catch (HashDbManagerException ex) {
599 logger.log(Level.WARNING, "There was an error loading the official hash sets.", ex);
600 officialHashSets = new ArrayList<HashDb>();
601 }
602 }
603
615 @Messages({
616 "# {0} - hashSetName",
617 "HashDbManager_handleNameConflict_conflictSuffix={0} (Custom)"
618 })
619 private List<HashDbInfo> handleNameConflict(List<HashDbInfo> curHashsets, Set<String> officialNames) {
620 Set<String> curNames = new HashSet<String>(officialNames);
621 boolean change = false;
622 List<HashDbInfo> newItems = new ArrayList<>();
623 for (HashDbInfo hashset : curHashsets) {
624 String thisName = hashset.getHashSetName();
625 if (curNames.contains(thisName)) {
626 while (curNames.contains(thisName)) {
627 thisName = Bundle.HashDbManager_handleNameConflict_conflictSuffix(thisName);
628 }
629
630 newItems.add(new HashDbInfo(
631 thisName,
632 hashset.getKnownFilesType(),
633 hashset.getSearchDuringIngest(),
634 hashset.getSendIngestMessages(),
635 hashset.getPath(),
636 hashset.getReferenceSetID(),
637 hashset.getVersion(),
638 hashset.isReadOnly(),
639 hashset.isCentralRepoDatabaseType()
640 ));
641 change = true;
642 } else {
643 newItems.add(hashset);
644 }
645
646 curNames.add(thisName);
647 }
648
649 if (!change) {
650 return curHashsets;
651 } else {
652 try {
653 HashLookupSettings.writeSettings(new HashLookupSettings(newItems));
654 HashLookupSettings toRet = HashLookupSettings.readSettings();
655 return toRet.getHashDbInfo();
656 } catch (HashLookupSettings.HashLookupSettingsException ex) {
657 logger.log(Level.SEVERE, "There was an error while trying to resave after name conflict.", ex);
658 return newItems;
659 }
660 }
661 }
662
672 private List<HashDb> loadOfficialHashSetsFromFolder(String folder) throws HashDbManagerException {
673 File configFolder = InstalledFileLocator.getDefault().locate(
674 folder, HashDbManager.class.getPackage().getName(), false);
675
676 if (configFolder == null || !configFolder.exists() || !configFolder.isDirectory()) {
677 throw new HashDbManagerException("Folder provided: " + folder + " does not exist.");
678 }
679
680 return Stream.of(configFolder.listFiles(DEFAULT_KDB_FILTER))
681 .map((f) -> {
682 try {
684 } catch (HashDbManagerException | TskCoreException ex) {
685 logger.log(Level.WARNING, String.format("Hashset: %s could not be properly read.", f.getAbsolutePath()), ex);
686 return null;
687 }
688 })
689 .filter((hashdb) -> hashdb != null)
690 .collect(Collectors.toList());
691 }
692
705 private HashDb getOfficialHashDbFromFile(File file) throws HashDbManagerException, TskCoreException {
706 if (file == null || !file.exists()) {
707 throw new HashDbManagerException(String.format("No file found for: %s", file == null ? "<null>" : file.getAbsolutePath()));
708 }
709 String filename = file.getName();
710 Matcher match = OFFICIAL_FILENAME.matcher(filename);
711 if (!match.find()) {
712 throw new HashDbManagerException(String.format("File with name: %s does not match regex of: %s", filename, OFFICIAL_FILENAME.toString()));
713 }
714
715 String hashdbName = match.group(DB_NAME_PARAM);
716 final String knownStatus = match.group(KNOWN_STATUS_PARAM);
717
718 KnownFilesType knownFilesType = Stream.of(HashDb.KnownFilesType.values())
719 .filter(k -> k.getIdentifier().toUpperCase().equals(knownStatus.toUpperCase()))
720 .findFirst()
721 .orElseThrow(() -> new HashDbManagerException(String.format("No KnownFilesType matches %s for file: %s", knownStatus, filename)));
722
723 return new SleuthkitHashSet(
724 SleuthkitJNI.openHashDatabase(file.getAbsolutePath()),
725 hashdbName,
726 true, //searchDuringIngest
727 false, //sendIngestMessages
728 knownFilesType,
729 true); // official set
730 }
731
740 @Messages({"# {0} - hash set name", "HashDbManager.noDbPath.message=Couldn't get valid hash set path for: {0}",
741 "HashDbManager.centralRepoLoadError.message=Error loading central repository hash sets"})
742 private void configureSettings(HashLookupSettings settings, Set<String> officialSetNames) {
744 List<HashDbInfo> hashDbInfoList = settings.getHashDbInfo();
745 hashDbInfoList = handleNameConflict(hashDbInfoList, officialSetNames);
746
747 for (HashDbInfo hashDbInfo : hashDbInfoList) {
748 configureLocalDb(hashDbInfo);
749 }
750
753 }
754
755 /*
756 * NOTE: When RuntimeProperties.coreComponentsAreActive() is "false", I
757 * don't think we should overwrite hash db settings file because we were
758 * unable to load a database. The user should have to fix the issue or
759 * remove the database from settings. Overwiting the settings
760 * effectively removes the database from HashLookupSettings and the user
761 * may not know about this because the dialogs are not being displayed.
762 * The next time user starts Autopsy, HashDB will load without errors
763 * and the user may think that the problem was solved.
764 */
766 try {
767 HashLookupSettings.writeSettings(new HashLookupSettings(HashLookupSettings.convertHashSetList(this.hashSets)));
769 } catch (HashLookupSettings.HashLookupSettingsException ex) {
771 logger.log(Level.SEVERE, "Could not overwrite hash set settings.", ex);
772 }
773 }
774 }
775
779 private void configureCrDbs() {
780 try {
782 } catch (TskCoreException ex) {
783 Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error opening hash set", ex); //NON-NLS
784
785 JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(),
786 Bundle.HashDbManager_centralRepoLoadError_message(),
787 NbBundle.getMessage(this.getClass(), "HashDbManager.openHashDbErr"),
788 JOptionPane.ERROR_MESSAGE);
790 }
791 }
792
797 private void configureLocalDb(HashDbInfo hashDbInfo) {
798 try {
799 if (hashDbInfo.isFileDatabaseType()) {
800 String dbPath = this.getValidFilePath(hashDbInfo.getHashSetName(), hashDbInfo.getPath());
801 if (dbPath != null) {
802 addHashDatabase(SleuthkitJNI.openHashDatabase(dbPath), hashDbInfo.getHashSetName(), hashDbInfo.getSearchDuringIngest(), hashDbInfo.getSendIngestMessages(), hashDbInfo.getKnownFilesType());
803 } else {
804 logger.log(Level.WARNING, Bundle.HashDbManager_noDbPath_message(hashDbInfo.getHashSetName()));
806 }
807 } else {
809 addExistingCentralRepoHashSet(hashDbInfo.getHashSetName(), hashDbInfo.getVersion(),
810 hashDbInfo.getReferenceSetID(),
811 hashDbInfo.getSearchDuringIngest(), hashDbInfo.getSendIngestMessages(),
812 hashDbInfo.getKnownFilesType(), hashDbInfo.isReadOnly());
813 }
814 }
815 } catch (TskCoreException ex) {
816 Logger.getLogger(HashDbManager.class.getName()).log(Level.SEVERE, "Error opening hash set", ex); //NON-NLS
817 JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(),
818 NbBundle.getMessage(this.getClass(),
819 "HashDbManager.unableToOpenHashDbMsg", hashDbInfo.getHashSetName()),
820 NbBundle.getMessage(this.getClass(), "HashDbManager.openHashDbErr"),
821 JOptionPane.ERROR_MESSAGE);
823 }
824 }
825
826 private void updateHashSetsFromCentralRepository() throws TskCoreException {
828 List<HashDbInfo> crHashDbInfoList = getCentralRepoHashSetsFromDatabase();
829 for (HashDbInfo hashDbInfo : crHashDbInfoList) {
830 if (hashDbInfoIsNew(hashDbInfo)) {
831 addExistingCentralRepoHashSet(hashDbInfo.getHashSetName(), hashDbInfo.getVersion(),
832 hashDbInfo.getReferenceSetID(),
833 hashDbInfo.getSearchDuringIngest(), hashDbInfo.getSendIngestMessages(), hashDbInfo.getKnownFilesType(),
834 hashDbInfo.isReadOnly());
835 }
836 }
837 }
838 }
839
840 private boolean hashDbInfoIsNew(HashDbInfo dbInfo) {
841 for (HashDb db : this.hashSets) {
842 if (dbInfo.matches(db)) {
843 return false;
844 }
845 }
846 return true;
847 }
848
849 private String getValidFilePath(String hashSetName, String configuredPath) {
850 // Check the configured path.
851 File database = new File(configuredPath);
852 if (database.exists()) {
853 return configuredPath;
854 }
855
856 // Give the user an opportunity to find the desired file.
857 String newPath = null;
859 && JOptionPane.showConfirmDialog(WindowManager.getDefault().getMainWindow(),
860 NbBundle.getMessage(this.getClass(), "HashDbManager.dlgMsg.dbNotFoundAtLoc",
861 hashSetName, configuredPath),
862 NbBundle.getMessage(this.getClass(), "HashDbManager.dlgTitle.MissingDb"),
863 JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
864 newPath = searchForFile();
865 if (null != newPath && !newPath.isEmpty()) {
866 database = new File(newPath);
867 if (!database.exists()) {
868 newPath = null;
869 }
870 }
871 }
872 return newPath;
873 }
874
875 private String searchForFile() {
876 String filePath = null;
877 JFileChooser fc = chooserHelper.getChooser();
878 fc.setDragEnabled(false);
879 fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
880 String[] EXTENSION = new String[]{"txt", "idx", "hash", "Hash", "kdb"}; //NON-NLS
881 FileNameExtensionFilter filter = new FileNameExtensionFilter(
882 NbBundle.getMessage(this.getClass(), "HashDbManager.fileNameExtensionFilter.title"), EXTENSION);
883 fc.setFileFilter(filter);
884 fc.setMultiSelectionEnabled(false);
885 if (fc.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
886 File f = fc.getSelectedFile();
887 try {
888 filePath = f.getCanonicalPath();
889 } catch (IOException ex) {
890 Logger.getLogger(HashDbManager.class.getName()).log(Level.WARNING, "Couldn't get selected file path", ex); //NON-NLS
891 }
892 }
893 return filePath;
894 }
895
896 public static abstract class HashDb {
897
902 @Messages({
903 "HashDbManager.noChange.text=No Change",
904 "HashDbManager.known.text=Known",
905 "HashDbManager.knownBad.text=Notable"
906 })
907 public enum KnownFilesType {
908
909 KNOWN(Bundle.HashDbManager_known_text(), "Known", TskData.FileKnown.KNOWN, false, false),
910 KNOWN_BAD(Bundle.HashDbManager_knownBad_text(), "Notable", TskData.FileKnown.BAD, true, true),
911 NO_CHANGE(Bundle.HashDbManager_noChange_text(), "NoChange", TskData.FileKnown.UNKNOWN, true, false);
912
913 private final String displayName;
914 private final String identifier;
915 private final TskData.FileKnown fileKnown;
916 private final boolean allowSendInboxMessages;
917 private final boolean defaultSendInboxMessages;
918
919 KnownFilesType(String displayName, String identifier, TskData.FileKnown fileKnown,
921
922 this.displayName = displayName;
923 this.identifier = identifier;
924 this.fileKnown = fileKnown;
925 this.allowSendInboxMessages = allowSendInboxMessages;
926 this.defaultSendInboxMessages = defaultSendInboxMessages;
927 }
928
938 }
939
950
957 String getIdentifier() {
958 return identifier;
959 }
960
961 public String getDisplayName() {
962 return this.displayName;
963 }
964
971 TskData.FileKnown getFileKnown() {
972 return this.fileKnown;
973 }
974
982 static KnownFilesType fromFileKnown(TskData.FileKnown fileKnown) {
983 if (fileKnown == null) {
984 return null;
985 }
986
987 return Stream.of(KnownFilesType.values())
988 .filter((type) -> type.getFileKnown() == fileKnown)
989 .findFirst()
990 .orElseThrow(() -> new IllegalArgumentException("Unknown TskData.FileKnown type: " + fileKnown));
991 }
992 }
993
997 public enum Event {
998
1000 }
1001
1002 public abstract String getHashSetName();
1003
1004 abstract String getDisplayName();
1005
1006 public abstract String getDatabasePath() throws TskCoreException;
1007
1009
1010 public abstract boolean getSearchDuringIngest();
1011
1012 abstract void setSearchDuringIngest(boolean useForIngest);
1013
1014 public abstract boolean getSendIngestMessages();
1015
1016 abstract void setSendIngestMessages(boolean showInboxMessages);
1017
1025 public abstract boolean isUpdateable() throws TskCoreException;
1026
1035 public abstract void addHashes(Content content) throws TskCoreException;
1036
1037 public abstract void addHashes(Content content, String comment) throws TskCoreException;
1038
1039 public abstract void addHashes(List<HashEntry> hashes) throws TskCoreException;
1040
1041 public abstract boolean lookupMD5Quick(Content content) throws TskCoreException;
1042
1043 public abstract HashHitInfo lookupMD5(Content content) throws TskCoreException;
1044
1053 abstract boolean isValid() throws TskCoreException;
1054
1055 public abstract String getIndexPath() throws TskCoreException;
1056
1057 public abstract boolean hasIndexOnly() throws TskCoreException;
1058
1059 public abstract void firePropertyChange(String propertyName, Object oldValue, Object newValue);
1060
1061 public abstract void addPropertyChangeListener(PropertyChangeListener pcl);
1062
1063 public abstract void removePropertyChangeListener(PropertyChangeListener pcl);
1064
1065 @Override
1066 public abstract String toString();
1067
1068 }
1069
1074 class SleuthkitHashSet extends HashDb {
1075
1076 private static final long serialVersionUID = 1L;
1077 private final int handle;
1078 private final String hashSetName;
1079 private boolean searchDuringIngest;
1080 private boolean sendIngestMessages;
1081 private final HashDb.KnownFilesType knownFilesType;
1082 private boolean indexing;
1083 private final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
1084 private final boolean officialSet;
1085
1086 private SleuthkitHashSet(int handle, String hashSetName, boolean useForIngest, boolean sendHitMessages, KnownFilesType knownFilesType) {
1087 this(handle, hashSetName, useForIngest, sendHitMessages, knownFilesType, false);
1088 }
1089
1090 private SleuthkitHashSet(int handle, String hashSetName, boolean useForIngest, boolean sendHitMessages, KnownFilesType knownFilesType, boolean officialSet) {
1091 this.handle = handle;
1092 this.hashSetName = hashSetName;
1093 this.searchDuringIngest = useForIngest;
1094 this.sendIngestMessages = sendHitMessages;
1095 this.knownFilesType = knownFilesType;
1096 this.indexing = false;
1097 this.officialSet = officialSet;
1098 }
1099
1106 @Override
1107 public void addPropertyChangeListener(PropertyChangeListener pcl) {
1108 propertyChangeSupport.addPropertyChangeListener(pcl);
1109 }
1110
1116 @Override
1117 public void removePropertyChangeListener(PropertyChangeListener pcl) {
1118 propertyChangeSupport.removePropertyChangeListener(pcl);
1119 }
1120
1121 int getHandle() {
1122 return handle;
1123 }
1124
1125 @Override
1126 public String getHashSetName() {
1127 return hashSetName;
1128 }
1129
1130 @Override
1131 String getDisplayName() {
1132 return getHashSetName();
1133 }
1134
1135 @Override
1136 public String getDatabasePath() throws TskCoreException {
1137 return SleuthkitJNI.getHashDatabasePath(handle);
1138 }
1139
1140 public void setIndexing(boolean indexing) {
1141 this.indexing = indexing;
1142 }
1143
1144 @Override
1145 public String getIndexPath() throws TskCoreException {
1146 return SleuthkitJNI.getHashDatabaseIndexPath(handle);
1147 }
1148
1149 @Override
1151 return knownFilesType;
1152 }
1153
1154 @Override
1155 public boolean getSearchDuringIngest() {
1156 return searchDuringIngest;
1157 }
1158
1159 @Override
1160 void setSearchDuringIngest(boolean useForIngest) {
1161 this.searchDuringIngest = useForIngest;
1162 }
1163
1164 @Override
1165 public boolean getSendIngestMessages() {
1166 return sendIngestMessages;
1167 }
1168
1169 @Override
1170 void setSendIngestMessages(boolean showInboxMessages) {
1171 this.sendIngestMessages = showInboxMessages;
1172 }
1173
1181 @Override
1182 public boolean isUpdateable() throws TskCoreException {
1183 if (isOfficialSet()) {
1184 return false;
1185 }
1186
1187 return SleuthkitJNI.isUpdateableHashDatabase(this.handle);
1188 }
1189
1198 @Override
1199 public void addHashes(Content content) throws TskCoreException {
1200 addHashes(content, null);
1201 }
1202
1213 @Override
1214 public void addHashes(Content content, String comment) throws TskCoreException {
1215 // This only works for AbstractFiles and MD5 hashes at present.
1216 assert content instanceof AbstractFile;
1217 officialSetCheck();
1218 if (content instanceof AbstractFile) {
1219 AbstractFile file = (AbstractFile) content;
1220 if (null != file.getMd5Hash()) {
1221 SleuthkitJNI.addToHashDatabase(null, file.getMd5Hash(), null, null, comment, handle);
1222 }
1223 }
1224 }
1225
1231 private void officialSetCheck() throws TskCoreException {
1232 if (isOfficialSet()) {
1233 throw new TskCoreException("Hashes cannot be added to an official set");
1234 }
1235 }
1236
1244 @Override
1245 public void addHashes(List<HashEntry> hashes) throws TskCoreException {
1246 officialSetCheck();
1247 SleuthkitJNI.addToHashDatabase(hashes, handle);
1248 }
1249
1259 @Override
1260 public boolean lookupMD5Quick(Content content) throws TskCoreException {
1261 boolean result = false;
1262 assert content instanceof AbstractFile;
1263 if (content instanceof AbstractFile) {
1264 AbstractFile file = (AbstractFile) content;
1265 if (null != file.getMd5Hash()) {
1266 result = SleuthkitJNI.lookupInHashDatabase(file.getMd5Hash(), handle);
1267 }
1268 }
1269 return result;
1270 }
1271
1281 @Override
1282 public HashHitInfo lookupMD5(Content content) throws TskCoreException {
1283 HashHitInfo result = null;
1284 // This only works for AbstractFiles and MD5 hashes at present.
1285 assert content instanceof AbstractFile;
1286 if (content instanceof AbstractFile) {
1287 AbstractFile file = (AbstractFile) content;
1288 if (null != file.getMd5Hash()) {
1289 result = SleuthkitJNI.lookupInHashDatabaseVerbose(file.getMd5Hash(), handle);
1290 }
1291 }
1292 return result;
1293 }
1294
1303 @Override
1304 boolean isValid() throws TskCoreException {
1305 return hasIndex();
1306 }
1307
1308 boolean hasIndex() throws TskCoreException {
1309 return SleuthkitJNI.hashDatabaseHasLookupIndex(handle);
1310 }
1311
1312 @Override
1313 public boolean hasIndexOnly() throws TskCoreException {
1314 return SleuthkitJNI.hashDatabaseIsIndexOnly(handle);
1315 }
1316
1317 boolean canBeReIndexed() throws TskCoreException {
1318 return SleuthkitJNI.hashDatabaseCanBeReindexed(handle);
1319 }
1320
1321 boolean isIndexing() {
1322 return indexing;
1323 }
1324
1325 @Override
1326 public void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
1327 this.propertyChangeSupport.firePropertyChange(propertyName, oldValue, newValue);
1328 }
1329
1330 private void close() throws TskCoreException {
1331 SleuthkitJNI.closeHashDatabase(handle);
1332 }
1333
1334 @Override
1335 public String toString() {
1336 return getHashSetName();
1337 }
1338
1339 @Override
1340 public int hashCode() {
1341 int code = 23;
1342 code = 47 * code + Integer.hashCode(handle);
1343 code = 47 * code + Objects.hashCode(this.hashSetName);
1344 code = 47 * code + Objects.hashCode(this.propertyChangeSupport);
1345 code = 47 * code + Objects.hashCode(this.knownFilesType);
1346 return code;
1347 }
1348
1349 @Override
1350 public boolean equals(Object obj) {
1351 if (obj == null) {
1352 return false;
1353 }
1354 if (getClass() != obj.getClass()) {
1355 return false;
1356 }
1357 final SleuthkitHashSet other = (SleuthkitHashSet) obj;
1358 if (!Objects.equals(this.hashSetName, other.hashSetName)) {
1359 return false;
1360 }
1361 if (this.knownFilesType != other.knownFilesType) {
1362 return false;
1363 }
1364 return true;
1365 }
1366
1373 boolean isOfficialSet() {
1374 return officialSet;
1375 }
1376 }
1377
1382 class CentralRepoHashSet extends HashDb {
1383
1384 private static final long serialVersionUID = 1L;
1385 private final String hashSetName;
1386 private boolean searchDuringIngest;
1387 private boolean sendIngestMessages;
1388 private final HashDb.KnownFilesType knownFilesType;
1389 private final int referenceSetID;
1390 private final String version;
1391 private String orgName;
1392 private final boolean readOnly;
1393 private final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
1394
1395 @Messages({"HashDbManager.CentralRepoHashDb.orgError=Error loading organization"})
1396 private CentralRepoHashSet(String hashSetName, String version, int referenceSetID,
1397 boolean useForIngest, boolean sendHitMessages, HashDb.KnownFilesType knownFilesType,
1398 boolean readOnly)
1399 throws TskCoreException {
1400 this.hashSetName = hashSetName;
1401 this.version = version;
1402 this.referenceSetID = referenceSetID;
1403 this.searchDuringIngest = useForIngest;
1404 this.sendIngestMessages = sendHitMessages;
1405 this.knownFilesType = knownFilesType;
1406 this.readOnly = readOnly;
1407
1408 try {
1410 } catch (CentralRepoException ex) {
1411 Logger.getLogger(SleuthkitHashSet.class.getName()).log(Level.SEVERE, "Error looking up central repository organization for reference set " + referenceSetID, ex); //NON-NLS
1412 orgName = Bundle.HashDbManager_CentralRepoHashDb_orgError();
1413 }
1414 }
1415
1422 @Override
1423 public void addPropertyChangeListener(PropertyChangeListener pcl) {
1424 propertyChangeSupport.addPropertyChangeListener(pcl);
1425 }
1426
1432 @Override
1433 public void removePropertyChangeListener(PropertyChangeListener pcl) {
1434 propertyChangeSupport.removePropertyChangeListener(pcl);
1435 }
1436
1437 @Override
1438 public boolean hasIndexOnly() throws TskCoreException {
1439 return true;
1440 }
1441
1442 @Override
1443 public String getHashSetName() {
1444 return hashSetName;
1445 }
1446
1447 @Override
1448 public String getDisplayName() {
1449 if (!getVersion().isEmpty()) {
1450 return getHashSetName() + " " + getVersion() + " (remote)";
1451 } else {
1452 return getHashSetName() + " (remote)";
1453 }
1454 }
1455
1456 String getVersion() {
1457 return version;
1458 }
1459
1460 String getOrgName() {
1461 return orgName;
1462 }
1463
1464 int getReferenceSetID() {
1465 return referenceSetID;
1466 }
1467
1468 @Override
1469 public String getDatabasePath() throws TskCoreException {
1470 return "";
1471 }
1472
1473 @Override
1474 public String getIndexPath() throws TskCoreException {
1475 return "";
1476 }
1477
1478 @Override
1479 public HashDb.KnownFilesType getKnownFilesType() {
1480 return knownFilesType;
1481 }
1482
1483 @Override
1484 public boolean getSearchDuringIngest() {
1485 return searchDuringIngest;
1486 }
1487
1488 @Override
1489 void setSearchDuringIngest(boolean useForIngest) {
1490 this.searchDuringIngest = useForIngest;
1491 }
1492
1493 @Override
1494 public boolean getSendIngestMessages() {
1495 return sendIngestMessages;
1496 }
1497
1498 @Override
1499 void setSendIngestMessages(boolean showInboxMessages) {
1500 this.sendIngestMessages = showInboxMessages;
1501 }
1502
1510 @Override
1511 public boolean isUpdateable() throws TskCoreException {
1512 return (!readOnly);
1513 }
1514
1523 @Override
1524 public void addHashes(Content content) throws TskCoreException {
1525 addHashes(content, null);
1526 }
1527
1538 @Override
1539 public void addHashes(Content content, String comment) throws TskCoreException {
1540 // This only works for AbstractFiles and MD5 hashes at present.
1541 assert content instanceof AbstractFile;
1542 if (content instanceof AbstractFile) {
1543 AbstractFile file = (AbstractFile) content;
1544 if (null != file.getMd5Hash()) {
1545 TskData.FileKnown type = knownFilesType.getFileKnown();
1546
1547 try {
1548 CentralRepoFileInstance fileInstance = new CentralRepoFileInstance(referenceSetID, file.getMd5Hash(),
1549 type, comment);
1550 CentralRepository.getInstance().addReferenceInstance(fileInstance, CentralRepository.getInstance().getCorrelationTypeById(CorrelationAttributeInstance.FILES_TYPE_ID));
1551 } catch (CentralRepoException | CorrelationAttributeNormalizationException ex) {
1552 throw new TskCoreException("Error adding hashes to " + getDisplayName(), ex); //NON-NLS
1553 }
1554 }
1555 }
1556 }
1557
1565 @Override
1566 public void addHashes(List<HashEntry> hashes) throws TskCoreException {
1567 Set<CentralRepoFileInstance> globalFileInstances = new HashSet<>();
1568 for (HashEntry hashEntry : hashes) {
1569 TskData.FileKnown type = knownFilesType.getFileKnown();
1570
1571 try {
1572 globalFileInstances.add(new CentralRepoFileInstance(referenceSetID, hashEntry.getMd5Hash(), type, hashEntry.getComment()));
1573 } catch (CentralRepoException | CorrelationAttributeNormalizationException ex) {
1574 throw new TskCoreException("Error adding hashes to " + getDisplayName(), ex);
1575 }
1576 }
1577
1578 try {
1579 CentralRepository.getInstance().bulkInsertReferenceTypeEntries(globalFileInstances,
1580 CentralRepository.getInstance().getCorrelationTypeById(CorrelationAttributeInstance.FILES_TYPE_ID));
1581 } catch (CentralRepoException ex) {
1582 throw new TskCoreException("Error adding hashes to " + getDisplayName(), ex);
1583 }
1584 }
1585
1595 @Override
1596 public boolean lookupMD5Quick(Content content) throws TskCoreException {
1597 // This only works for AbstractFiles and MD5 hashes
1598 assert content instanceof AbstractFile;
1599 if (content instanceof AbstractFile) {
1600 AbstractFile file = (AbstractFile) content;
1601 if (null != file.getMd5Hash()) {
1602 try {
1603 return CentralRepository.getInstance().isFileHashInReferenceSet(file.getMd5Hash(), this.referenceSetID);
1604 } catch (CentralRepoException | CorrelationAttributeNormalizationException ex) {
1605 Logger.getLogger(SleuthkitHashSet.class.getName()).log(Level.SEVERE, "Error performing central reposiotry hash lookup for hash "
1606 + file.getMd5Hash() + " in reference set " + referenceSetID, ex); //NON-NLS
1607 throw new TskCoreException("Error performing central reposiotry hash lookup", ex);
1608 }
1609 }
1610 }
1611 return false;
1612 }
1613
1623 @Override
1624 public HashHitInfo lookupMD5(Content content) throws TskCoreException {
1625 HashHitInfo result = null;
1626 // This only works for AbstractFiles and MD5 hashes
1627 assert content instanceof AbstractFile;
1628 if (content instanceof AbstractFile) {
1629 AbstractFile file = (AbstractFile) content;
1630 if (null != file.getMd5Hash()) {
1631 try {
1632 return CentralRepository.getInstance().lookupHash(file.getMd5Hash(), referenceSetID);
1633 } catch (CentralRepoException | CorrelationAttributeNormalizationException ex) {
1634 Logger.getLogger(SleuthkitHashSet.class.getName()).log(Level.SEVERE, "Error performing central reposiotry hash lookup for hash "
1635 + file.getMd5Hash() + " in reference set " + referenceSetID, ex); //NON-NLS
1636 throw new TskCoreException("Error performing central reposiotry hash lookup", ex);
1637 }
1638 }
1639 }
1640 return result;
1641 }
1642
1648 @Override
1649 boolean isValid() {
1650 if (!CentralRepository.isEnabled()) {
1651 return false;
1652 }
1653 try {
1654 return CentralRepository.getInstance().referenceSetIsValid(this.referenceSetID, this.hashSetName, this.version);
1655 } catch (CentralRepoException ex) {
1656 Logger.getLogger(CentralRepoHashSet.class.getName()).log(Level.SEVERE, "Error validating hash set " + hashSetName, ex); //NON-NLS
1657 return false;
1658 }
1659 }
1660
1661 @Override
1662 public void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
1663 this.propertyChangeSupport.firePropertyChange(propertyName, oldValue, newValue);
1664 }
1665
1666 @Override
1667 public String toString() {
1668 return getDisplayName();
1669 }
1670
1671 @Override
1672 public int hashCode() {
1673 int code = 23;
1674 code = 47 * code + Objects.hashCode(this.hashSetName);
1675 code = 47 * code + Objects.hashCode(this.version);
1676 code = 47 * code + Integer.hashCode(this.referenceSetID);
1677 code = 47 * code + Objects.hashCode(this.knownFilesType);
1678 return code;
1679 }
1680
1681 @Override
1682 public boolean equals(Object obj) {
1683 if (obj == null) {
1684 return false;
1685 }
1686 if (getClass() != obj.getClass()) {
1687 return false;
1688 }
1689 final CentralRepoHashSet other = (CentralRepoHashSet) obj;
1690 if (!Objects.equals(this.hashSetName, other.hashSetName)) {
1691 return false;
1692 }
1693 if (!Objects.equals(this.version, other.version)) {
1694 return false;
1695 }
1696 if (this.knownFilesType != other.knownFilesType) {
1697 return false;
1698 }
1699 return true;
1700 }
1701 }
1702
1706 private class HashDbIndexer extends SwingWorker<Object, Void> {
1707
1708 private ProgressHandle progress = null;
1709 private SleuthkitHashSet hashDb = null;
1710
1711 HashDbIndexer(SleuthkitHashSet hashDb) {
1712 this.hashDb = hashDb;
1713 }
1714
1715 @Override
1716 protected Object doInBackground() {
1717 hashDb.setIndexing(true);
1718 progress = ProgressHandle.createHandle(
1719 NbBundle.getMessage(this.getClass(), "HashDbManager.progress.indexingHashSet", hashDb.getHashSetName()));
1720 progress.start();
1721 progress.switchToIndeterminate();
1722 try {
1723 SleuthkitJNI.createLookupIndexForHashDatabase(hashDb.getHandle());
1724 } catch (TskCoreException ex) {
1725 Logger.getLogger(HashDbIndexer.class.getName()).log(Level.SEVERE, "Error indexing hash set " + hashDb.getHashSetName(), ex); //NON-NLS
1726 JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(),
1727 NbBundle.getMessage(this.getClass(),
1728 "HashDbManager.dlgMsg.errorIndexingHashSet",
1729 hashDb.getHashSetName()),
1730 NbBundle.getMessage(this.getClass(), "HashDbManager.hashDbIndexingErr"),
1731 JOptionPane.ERROR_MESSAGE);
1732 }
1733 return null;
1734 }
1735
1736 @Override
1737 protected void done() {
1738 hashDb.setIndexing(false);
1739 progress.finish();
1740
1741 // see if we got any errors
1742 try {
1743 get();
1744 } catch (InterruptedException | ExecutionException ex) {
1745 logger.log(Level.SEVERE, "Error creating index", ex); //NON-NLS
1747 NbBundle.getMessage(this.getClass(), "HashDbManager.errCreatingIndex.title"),
1748 NbBundle.getMessage(this.getClass(), "HashDbManager.errCreatingIndex.msg", ex.getMessage()),
1750 } // catch and ignore if we were cancelled
1751 catch (java.util.concurrent.CancellationException ex) {
1752 }
1753
1754 try {
1755 hashDb.firePropertyChange(SleuthkitHashSet.Event.INDEXING_DONE.toString(), null, hashDb);
1756 hashDb.firePropertyChange(HashDbManager.SetEvt.DB_INDEXED.toString(), null, hashDb.getHashSetName());
1757 } catch (Exception e) {
1758 logger.log(Level.SEVERE, "HashDbManager listener threw exception", e); //NON-NLS
1760 NbBundle.getMessage(this.getClass(), "HashDbManager.moduleErr"),
1761 NbBundle.getMessage(this.getClass(), "HashDbManager.moduleErrorListeningToUpdatesMsg"),
1763 }
1764 }
1765 }
1766}
synchronized static Logger getLogger(String name)
Definition Logger.java:124
static void show(String title, String message, MessageType type, ActionListener actionListener)
static synchronized IngestManager getInstance()
abstract void removePropertyChangeListener(PropertyChangeListener pcl)
abstract void firePropertyChange(String propertyName, Object oldValue, Object newValue)
abstract void addPropertyChangeListener(PropertyChangeListener pcl)
SleuthkitHashSet addHashDatabase(int handle, String hashSetName, boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType)
List< HashDb > getUpdateableHashSets(List< HashDb > hashDbs)
void checkDbCollision(String path, String hashSetName)
synchronized HashDb addNewHashDatabaseNoSave(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType)
synchronized void removePropertyChangeListener(PropertyChangeListener listener)
synchronized HashDb addExistingHashDatabase(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType)
synchronized void addPropertyChangeListener(PropertyChangeListener listener)
void configureSettings(HashLookupSettings settings, Set< String > officialSetNames)
synchronized HashDb addNewHashDatabase(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType)
List< HashDbInfo > handleNameConflict(List< HashDbInfo > curHashsets, Set< String > officialNames)
String getValidFilePath(String hashSetName, String configuredPath)
KnownFilesType(String displayName, String identifier, TskData.FileKnown fileKnown, boolean allowSendInboxMessages, boolean defaultSendInboxMessages)
CorrelationAttributeInstance.Type getCorrelationTypeById(int typeId)
List< CentralRepoFileSet > getAllReferenceSets(CorrelationAttributeInstance.Type correlationType)
CentralRepoOrganization getReferenceSetOrganization(int referenceSetID)

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