19 package org.sleuthkit.autopsy.modules.hashdatabase;
21 import java.beans.PropertyChangeEvent;
22 import java.beans.PropertyChangeListener;
23 import java.beans.PropertyChangeSupport;
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;
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;
79 private List<HashDb>
hashSets =
new ArrayList<>();
87 PropertyChangeSupport changeSupport =
new PropertyChangeSupport(
HashDbManager.class);
92 private static final String
KDB_EXT =
"kdb";
96 private static final Pattern
OFFICIAL_FILENAME = Pattern.compile(
"(?<" + DB_NAME_PARAM +
">.+?)\\.(?<" + KNOWN_STATUS_PARAM +
">.+?)\\." + KDB_EXT);
102 public boolean accept(File dir, String name) {
103 return name.endsWith(
"." + KDB_EXT);
114 DB_ADDED, DB_DELETED, DB_INDEXED
123 if (instance == null) {
130 changeSupport.addPropertyChangeListener(listener);
134 changeSupport.removePropertyChangeListener(listener);
137 synchronized boolean verifyAllDatabasesLoadedCorrectly() {
151 static String getHashDatabaseFileExtension() {
164 super(message, exception);
189 hashDb = this.addExistingHashDatabaseNoSave(hashSetName, path, searchDuringIngest, sendIngestMessages, knownFilesType);
197 if (!
new File(path).exists()) {
198 throw new HashDbManagerException(NbBundle.getMessage(
HashDbManager.class,
"HashDbManager.hashDbDoesNotExistExceptionMsg", path));
203 hashDb =
addHashDatabase(SleuthkitJNI.openHashDatabase(path), hashSetName, searchDuringIngest, sendIngestMessages, knownFilesType);
204 }
catch (TskCoreException ex) {
205 throw new HashDbManagerException(ex.getMessage());
228 public synchronized HashDb addNewHashDatabase(String hashSetName, String path,
boolean searchDuringIngest,
boolean sendIngestMessages,
243 File file =
new File(path);
245 throw new HashDbManagerException(NbBundle.getMessage(
HashDbManager.class,
"HashDbManager.hashDbFileExistsExceptionMsg", path));
247 if (!FilenameUtils.getExtension(file.getName()).equalsIgnoreCase(HASH_DATABASE_FILE_EXTENSON)) {
248 throw new HashDbManagerException(NbBundle.getMessage(
HashDbManager.class,
"HashDbManager.illegalHashDbFileNameExtensionMsg",
249 getHashDatabaseFileExtension()));
254 hashDb =
addHashDatabase(SleuthkitJNI.createHashDatabase(path), hashSetName, searchDuringIngest, sendIngestMessages, knownFilesType);
255 }
catch (TskCoreException ex) {
256 throw new HashDbManagerException(ex.getMessage());
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));
277 if (hashSetNames.contains(hashSetName) || officialHashSetNames.contains(hashSetName)) {
278 throw new HashDbManagerException(NbBundle.getMessage(
HashDbManager.class,
"HashDbManager.duplicateHashSetNameExceptionMsg", hashSetName));
282 private SleuthkitHashSet
addHashDatabase(
int handle, String hashSetName,
boolean searchDuringIngest,
boolean sendIngestMessages,
HashDb.
KnownFilesType knownFilesType) throws TskCoreException {
284 SleuthkitHashSet hashDb =
new SleuthkitHashSet(handle, hashSetName, searchDuringIngest, sendIngestMessages, knownFilesType);
288 String databasePath = hashDb.getDatabasePath();
289 String indexPath = hashDb.getIndexPath();
293 hashSetNames.add(hashDb.getHashSetName());
294 if (!databasePath.equals(
"None")) {
295 hashSetPaths.add(databasePath);
297 if (!indexPath.equals(
"None")) {
298 hashSetPaths.add(indexPath);
302 hashSets.add(hashDb);
306 changeSupport.firePropertyChange(
SetEvt.
DB_ADDED.toString(), null, hashSetName);
307 }
catch (Exception e) {
308 logger.log(Level.SEVERE,
"HashDbManager listener threw exception", e);
310 NbBundle.getMessage(
this.getClass(),
"HashDbManager.moduleErr"),
311 NbBundle.getMessage(
this.getClass(),
"HashDbManager.moduleErrorListeningToUpdatesMsg"),
317 CentralRepoHashSet addExistingCentralRepoHashSet(String hashSetName, String version,
int referenceSetID,
319 boolean readOnly)
throws TskCoreException {
322 throw new TskCoreException(
"Could not load central repository hash set " + hashSetName +
" - central repository is not enabled");
325 CentralRepoHashSet db =
new CentralRepoHashSet(hashSetName, version, referenceSetID, searchDuringIngest,
326 sendIngestMessages, knownFilesType, readOnly);
329 throw new TskCoreException(
"Error finding hash set " + hashSetName +
" in central repository");
333 if(!hashSets.contains(db)) {
338 changeSupport.firePropertyChange(SetEvt.DB_ADDED.toString(), null, hashSetName);
339 }
catch (Exception e) {
340 logger.log(Level.SEVERE,
"HashDbManager listener threw exception", e);
341 MessageNotifyUtil.Notify.show(
342 NbBundle.getMessage(
this.getClass(),
"HashDbManager.moduleErr"),
343 NbBundle.getMessage(
this.getClass(),
"HashDbManager.moduleErrorListeningToUpdatesMsg"),
344 MessageNotifyUtil.MessageType.ERROR);
351 synchronized void indexHashDatabase(SleuthkitHashSet hashDb) {
352 hashDb.addPropertyChangeListener(
this);
353 HashDbIndexer creator =
new HashDbIndexer(hashDb);
359 if (event.getPropertyName().equals(SleuthkitHashSet.Event.INDEXING_DONE.name())) {
360 SleuthkitHashSet hashDb = (SleuthkitHashSet) event.getNewValue();
361 if (null != hashDb) {
363 String indexPath = hashDb.getIndexPath();
364 if (!indexPath.equals(
"None")) {
365 hashSetPaths.add(indexPath);
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);
390 if (ingestIsRunning) {
391 throw new HashDbManagerException(NbBundle.getMessage(
this.getClass(),
"HashDbManager.ingestRunningExceptionMsg"));
397 String hashSetName = hashDb.getHashSetName();
398 hashSetNames.remove(hashSetName);
399 hashSets.remove(hashDb);
403 if (hashDb instanceof SleuthkitHashSet) {
404 SleuthkitHashSet hashDatabase = (SleuthkitHashSet) hashDb;
406 if (hashDatabase.hasIndex()) {
407 hashSetPaths.remove(hashDatabase.getIndexPath());
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);
414 if (!hashDatabase.hasIndexOnly()) {
415 hashSetPaths.remove(hashDatabase.getDatabasePath());
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);
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);
430 changeSupport.firePropertyChange(
SetEvt.
DB_DELETED.toString(), null, hashSetName);
431 }
catch (Exception e) {
432 logger.log(Level.SEVERE,
"HashDbManager listener threw exception", e);
434 NbBundle.getMessage(
this.getClass(),
"HashDbManager.moduleErr"),
435 NbBundle.getMessage(
this.getClass(),
"HashDbManager.moduleErrorListeningToUpdatesMsg"),
440 void save() throws HashDbManagerException {
442 if (!HashLookupSettings.writeSettings(
new HashLookupSettings(HashLookupSettings.convertHashSetList(
this.hashSets)))) {
443 throw new HashDbManagerException(NbBundle.getMessage(
this.getClass(),
"HashDbManager.saveErrorExceptionMsg"));
445 }
catch (HashLookupSettings.HashLookupSettingsException ex) {
446 throw new HashDbManagerException(NbBundle.getMessage(
this.getClass(),
"HashDbManager.saveErrorExceptionMsg"));
460 }
catch (TskCoreException ex) {
464 return Stream.concat(this.officialHashSets.stream(), this.hashSets.stream())
465 .collect(Collectors.toList());
477 .collect(Collectors.toList());
489 .collect(Collectors.toList());
507 }
catch (TskCoreException ex) {
512 .collect(Collectors.toList());
516 List<HashDbInfo> crHashSets =
new ArrayList<>();
526 crHashSets.add(
new HashDbInfo(globalSet.getSetName(), globalSet.getVersion(),
527 globalSet.getGlobalSetID(),
KnownFilesType.
fromFileKnown(globalSet.getFileKnownStatus()), globalSet.isReadOnly(),
false, sendIngestMessages));
542 hashSetNames.clear();
543 hashSetPaths.clear();
549 for (
HashDb database : hashDatabases) {
550 if (database instanceof SleuthkitHashSet) {
552 ((SleuthkitHashSet) database).close();
553 }
catch (TskCoreException ex) {
558 hashDatabases.clear();
565 HashLookupSettings settings = HashLookupSettings.readSettings();
567 }
catch (HashLookupSettings.HashLookupSettingsException ex) {
577 officialHashSetPaths =
new HashSet<>();
578 officialHashSetNames =
new HashSet<>();
582 officialHashSets.forEach(db -> {
583 officialHashSetNames.add(db.getHashSetName());
585 String databasePath = db.getDatabasePath();
586 String indexPath = db.getIndexPath();
588 if (StringUtils.isNotBlank(databasePath) && !databasePath.equals(
"None")) {
589 officialHashSetPaths.add(databasePath);
591 if (StringUtils.isNotBlank(indexPath) && !indexPath.equals(
"None")) {
592 officialHashSetPaths.add(indexPath);
594 }
catch (TskCoreException ex) {
595 logger.log(Level.SEVERE,
"There was an error loading the official hash set name.", ex);
598 }
catch (HashDbManagerException ex) {
599 logger.log(Level.WARNING,
"There was an error loading the official hash sets.", ex);
600 officialHashSets =
new ArrayList<HashDb>();
616 "# {0} - hashSetName",
617 "HashDbManager_handleNameConflict_conflictSuffix={0} (Custom)"
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);
630 newItems.add(
new HashDbInfo(
632 hashset.getKnownFilesType(),
633 hashset.getSearchDuringIngest(),
634 hashset.getSendIngestMessages(),
636 hashset.getReferenceSetID(),
637 hashset.getVersion(),
638 hashset.isReadOnly(),
639 hashset.isCentralRepoDatabaseType()
643 newItems.add(hashset);
646 curNames.add(thisName);
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);
673 File configFolder = InstalledFileLocator.getDefault().locate(
676 if (configFolder == null || !configFolder.exists() || !configFolder.isDirectory()) {
677 throw new HashDbManagerException(
"Folder provided: " + folder +
" does not exist.");
680 return Stream.of(configFolder.listFiles(DEFAULT_KDB_FILTER))
684 }
catch (HashDbManagerException | TskCoreException ex) {
685 logger.log(Level.WARNING, String.format(
"Hashset: %s could not be properly read.", f.getAbsolutePath()), ex);
689 .filter((hashdb) -> hashdb != null)
690 .collect(Collectors.toList());
706 if (file == null || !file.exists()) {
707 throw new HashDbManagerException(String.format(
"No file found for: %s", file == null ?
"<null>" : file.getAbsolutePath()));
709 String filename = file.getName();
710 Matcher match = OFFICIAL_FILENAME.matcher(filename);
712 throw new HashDbManagerException(String.format(
"File with name: %s does not match regex of: %s", filename, OFFICIAL_FILENAME.toString()));
715 String hashdbName = match.group(DB_NAME_PARAM);
716 final String knownStatus = match.group(KNOWN_STATUS_PARAM);
719 .filter(k -> k.getIdentifier().toUpperCase().equals(knownStatus.toUpperCase()))
721 .orElseThrow(() ->
new HashDbManagerException(String.format(
"No KnownFilesType matches %s for file: %s", knownStatus, filename)));
723 return new SleuthkitHashSet(
724 SleuthkitJNI.openHashDatabase(file.getAbsolutePath()),
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"})
743 allDatabasesLoadedCorrectly =
true;
744 List<HashDbInfo> hashDbInfoList = settings.getHashDbInfo();
747 for (HashDbInfo hashDbInfo : hashDbInfoList) {
767 HashLookupSettings.writeSettings(
new HashLookupSettings(HashLookupSettings.convertHashSetList(
this.hashSets)));
768 allDatabasesLoadedCorrectly =
true;
769 }
catch (HashLookupSettings.HashLookupSettingsException ex) {
770 allDatabasesLoadedCorrectly =
false;
771 logger.log(Level.SEVERE,
"Could not overwrite hash set settings.", ex);
782 }
catch (TskCoreException ex) {
785 JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(),
786 Bundle.HashDbManager_centralRepoLoadError_message(),
787 NbBundle.getMessage(this.getClass(),
"HashDbManager.openHashDbErr"),
788 JOptionPane.ERROR_MESSAGE);
789 allDatabasesLoadedCorrectly =
false;
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());
804 logger.log(Level.WARNING, Bundle.HashDbManager_noDbPath_message(hashDbInfo.getHashSetName()));
805 allDatabasesLoadedCorrectly =
false;
809 addExistingCentralRepoHashSet(hashDbInfo.getHashSetName(), hashDbInfo.getVersion(),
810 hashDbInfo.getReferenceSetID(),
811 hashDbInfo.getSearchDuringIngest(), hashDbInfo.getSendIngestMessages(),
812 hashDbInfo.getKnownFilesType(), hashDbInfo.isReadOnly());
815 }
catch (TskCoreException ex) {
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);
822 allDatabasesLoadedCorrectly =
false;
829 for (HashDbInfo hashDbInfo : crHashDbInfoList) {
831 addExistingCentralRepoHashSet(hashDbInfo.getHashSetName(), hashDbInfo.getVersion(),
832 hashDbInfo.getReferenceSetID(),
833 hashDbInfo.getSearchDuringIngest(), hashDbInfo.getSendIngestMessages(), hashDbInfo.getKnownFilesType(),
834 hashDbInfo.isReadOnly());
841 for (
HashDb db : this.hashSets) {
842 if (dbInfo.matches(db)) {
851 File database =
new File(configuredPath);
852 if (database.exists()) {
853 return configuredPath;
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) {
865 if (null != newPath && !newPath.isEmpty()) {
866 database =
new File(newPath);
867 if (!database.exists()) {
876 String filePath = null;
878 fc.setDragEnabled(
false);
879 fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
880 String[] EXTENSION =
new String[]{
"txt",
"idx",
"hash",
"Hash",
"kdb"};
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();
888 filePath = f.getCanonicalPath();
889 }
catch (IOException ex) {
903 "HashDbManager.noChange.text=No Change",
904 "HashDbManager.known.text=Known",
905 "HashDbManager.knownBad.text=Notable"
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);
919 KnownFilesType(String displayName, String identifier, TskData.FileKnown fileKnown,
920 boolean allowSendInboxMessages,
boolean defaultSendInboxMessages) {
922 this.displayName = displayName;
923 this.identifier = identifier;
924 this.fileKnown = fileKnown;
925 this.allowSendInboxMessages = allowSendInboxMessages;
926 this.defaultSendInboxMessages = defaultSendInboxMessages;
937 return allowSendInboxMessages;
948 return defaultSendInboxMessages;
962 return this.displayName;
972 return this.fileKnown;
983 if (fileKnown == null) {
988 .filter((type) -> type.getFileKnown() == fileKnown)
990 .orElseThrow(() ->
new IllegalArgumentException(
"Unknown TskData.FileKnown type: " + fileKnown));
1004 abstract String getDisplayName();
1012 abstract
void setSearchDuringIngest(
boolean useForIngest);
1016 abstract
void setSendIngestMessages(
boolean showInboxMessages);
1025 public abstract
boolean isUpdateable() throws TskCoreException;
1035 public abstract
void addHashes(Content content) throws TskCoreException;
1037 public abstract
void addHashes(Content content, String comment) throws TskCoreException;
1039 public abstract
void addHashes(List<HashEntry> hashes) throws TskCoreException;
1041 public abstract
boolean lookupMD5Quick(Content content) throws TskCoreException;
1043 public abstract HashHitInfo
lookupMD5(Content content) throws TskCoreException;
1053 abstract
boolean isValid() throws TskCoreException;
1055 public abstract String
getIndexPath() throws TskCoreException;
1057 public abstract
boolean hasIndexOnly() throws TskCoreException;
1059 public abstract
void firePropertyChange(String propertyName, Object oldValue, Object newValue);
1074 class SleuthkitHashSet extends
HashDb {
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;
1082 private boolean indexing;
1083 private final PropertyChangeSupport propertyChangeSupport =
new PropertyChangeSupport(
this);
1084 private final boolean officialSet;
1086 private SleuthkitHashSet(
int handle, String hashSetName,
boolean useForIngest,
boolean sendHitMessages,
KnownFilesType knownFilesType) {
1087 this(handle, hashSetName, useForIngest, sendHitMessages, knownFilesType,
false);
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;
1108 propertyChangeSupport.addPropertyChangeListener(pcl);
1118 propertyChangeSupport.removePropertyChangeListener(pcl);
1131 String getDisplayName() {
1137 return SleuthkitJNI.getHashDatabasePath(handle);
1140 public void setIndexing(
boolean indexing) {
1141 this.indexing = indexing;
1146 return SleuthkitJNI.getHashDatabaseIndexPath(handle);
1151 return knownFilesType;
1156 return searchDuringIngest;
1160 void setSearchDuringIngest(
boolean useForIngest) {
1161 this.searchDuringIngest = useForIngest;
1166 return sendIngestMessages;
1170 void setSendIngestMessages(
boolean showInboxMessages) {
1171 this.sendIngestMessages = showInboxMessages;
1182 public boolean isUpdateable() throws TskCoreException {
1183 if (isOfficialSet()) {
1187 return SleuthkitJNI.isUpdateableHashDatabase(this.handle);
1199 public void addHashes(Content content)
throws TskCoreException {
1214 public void addHashes(Content content, String comment)
throws TskCoreException {
1216 assert content instanceof AbstractFile;
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);
1231 private void officialSetCheck() throws TskCoreException {
1232 if (isOfficialSet()) {
1233 throw new TskCoreException(
"Hashes cannot be added to an official set");
1245 public void addHashes(List<HashEntry> hashes)
throws TskCoreException {
1247 SleuthkitJNI.addToHashDatabase(hashes, handle);
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);
1282 public HashHitInfo
lookupMD5(Content content)
throws TskCoreException {
1283 HashHitInfo result = null;
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);
1304 boolean isValid() throws TskCoreException {
1308 boolean hasIndex() throws TskCoreException {
1309 return SleuthkitJNI.hashDatabaseHasLookupIndex(handle);
1313 public boolean hasIndexOnly() throws TskCoreException {
1314 return SleuthkitJNI.hashDatabaseIsIndexOnly(handle);
1317 boolean canBeReIndexed() throws TskCoreException {
1318 return SleuthkitJNI.hashDatabaseCanBeReindexed(handle);
1321 boolean isIndexing() {
1326 public void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
1327 this.propertyChangeSupport.firePropertyChange(propertyName, oldValue, newValue);
1330 private void close() throws TskCoreException {
1331 SleuthkitJNI.closeHashDatabase(handle);
1340 public int hashCode() {
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);
1350 public boolean equals(Object obj) {
1354 if (getClass() != obj.getClass()) {
1357 final SleuthkitHashSet other = (SleuthkitHashSet) obj;
1358 if (!Objects.equals(
this.hashSetName, other.hashSetName)) {
1361 if (this.knownFilesType != other.knownFilesType) {
1373 boolean isOfficialSet() {
1382 class CentralRepoHashSet
extends HashDb {
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);
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,
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;
1409 orgName = CentralRepository.getInstance().getReferenceSetOrganization(referenceSetID).getName();
1410 }
catch (CentralRepoException ex) {
1411 Logger.getLogger(SleuthkitHashSet.class.getName()).log(Level.SEVERE,
"Error looking up central repository organization for reference set " + referenceSetID, ex);
1412 orgName = Bundle.HashDbManager_CentralRepoHashDb_orgError();
1424 propertyChangeSupport.addPropertyChangeListener(pcl);
1434 propertyChangeSupport.removePropertyChangeListener(pcl);
1438 public boolean hasIndexOnly() throws TskCoreException {
1448 public String getDisplayName() {
1449 if (!getVersion().isEmpty()) {
1456 String getVersion() {
1460 String getOrgName() {
1464 int getReferenceSetID() {
1465 return referenceSetID;
1480 return knownFilesType;
1485 return searchDuringIngest;
1489 void setSearchDuringIngest(
boolean useForIngest) {
1490 this.searchDuringIngest = useForIngest;
1495 return sendIngestMessages;
1499 void setSendIngestMessages(
boolean showInboxMessages) {
1500 this.sendIngestMessages = showInboxMessages;
1511 public boolean isUpdateable() throws TskCoreException {
1524 public void addHashes(Content content)
throws TskCoreException {
1539 public void addHashes(Content content, String comment)
throws TskCoreException {
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();
1548 CentralRepoFileInstance fileInstance =
new CentralRepoFileInstance(referenceSetID, file.getMd5Hash(),
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);
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();
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);
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);
1596 public boolean lookupMD5Quick(Content content)
throws TskCoreException {
1598 assert content instanceof AbstractFile;
1599 if (content instanceof AbstractFile) {
1600 AbstractFile file = (AbstractFile) content;
1601 if (null != file.getMd5Hash()) {
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);
1607 throw new TskCoreException(
"Error performing central reposiotry hash lookup", ex);
1624 public HashHitInfo
lookupMD5(Content content)
throws TskCoreException {
1625 HashHitInfo result = null;
1627 assert content instanceof AbstractFile;
1628 if (content instanceof AbstractFile) {
1629 AbstractFile file = (AbstractFile) content;
1630 if (null != file.getMd5Hash()) {
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);
1636 throw new TskCoreException(
"Error performing central reposiotry hash lookup", ex);
1650 if (!CentralRepository.isEnabled()) {
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);
1662 public void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
1663 this.propertyChangeSupport.firePropertyChange(propertyName, oldValue, newValue);
1668 return getDisplayName();
1672 public int hashCode() {
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);
1682 public boolean equals(Object obj) {
1686 if (getClass() != obj.getClass()) {
1689 final CentralRepoHashSet other = (CentralRepoHashSet) obj;
1690 if (!Objects.equals(
this.hashSetName, other.hashSetName)) {
1693 if (!Objects.equals(
this.version, other.version)) {
1696 if (this.knownFilesType != other.knownFilesType) {
1708 private ProgressHandle progress = null;
1709 private SleuthkitHashSet hashDb = null;
1712 this.hashDb = hashDb;
1717 hashDb.setIndexing(
true);
1718 progress = ProgressHandle.createHandle(
1719 NbBundle.getMessage(
this.getClass(),
"HashDbManager.progress.indexingHashSet", hashDb.getHashSetName()));
1721 progress.switchToIndeterminate();
1723 SleuthkitJNI.createLookupIndexForHashDatabase(hashDb.getHandle());
1724 }
catch (TskCoreException ex) {
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);
1738 hashDb.setIndexing(
false);
1744 }
catch (InterruptedException | ExecutionException ex) {
1745 logger.log(Level.SEVERE,
"Error creating index", ex);
1747 NbBundle.getMessage(
this.getClass(),
"HashDbManager.errCreatingIndex.title"),
1748 NbBundle.getMessage(
this.getClass(),
"HashDbManager.errCreatingIndex.msg", ex.getMessage()),
1751 catch (java.util.concurrent.CancellationException ex) {
1755 hashDb.firePropertyChange(SleuthkitHashSet.Event.INDEXING_DONE.toString(), null, hashDb);
1757 }
catch (Exception e) {
1758 logger.log(Level.SEVERE,
"HashDbManager listener threw exception", e);
1760 NbBundle.getMessage(
this.getClass(),
"HashDbManager.moduleErr"),
1761 NbBundle.getMessage(
this.getClass(),
"HashDbManager.moduleErrorListeningToUpdatesMsg"),
abstract boolean getSendIngestMessages()
Set< String > hashSetPaths
abstract String getIndexPath()
static final Pattern OFFICIAL_FILENAME
static final Logger logger
static final String HASH_DATABASE_FILE_EXTENSON
void loadHashsetsConfiguration()
static synchronized IngestManager getInstance()
Set< String > officialHashSetPaths
static final String DB_NAME_PARAM
Set< String > officialHashSetNames
static boolean runningWithGUI
synchronized void addPropertyChangeListener(PropertyChangeListener listener)
HashDbManagerException(String message)
void checkDbCollision(String path, String hashSetName)
List< CentralRepoFileSet > getAllReferenceSets(CorrelationAttributeInstance.Type correlationType)
static KnownFilesType fromFileKnown(TskData.FileKnown fileKnown)
abstract String getHashSetName()
List< HashDbInfo > getCentralRepoHashSetsFromDatabase()
List< HashDb > loadOfficialHashSetsFromFolder(String folder)
boolean isIngestRunning()
static final long serialVersionUID
final TskData.FileKnown fileKnown
List< HashDb > getUpdateableHashSets(List< HashDb > hashDbs)
abstract String toString()
static final String KDB_EXT
synchronized HashDb addNewHashDatabaseNoSave(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType)
void configureSettings(HashLookupSettings settings, Set< String > officialSetNames)
HashDbManagerException(String message, Throwable exception)
synchronized void removeHashDatabase(HashDb hashDb)
static final String OFFICIAL_HASH_SETS_FOLDER
final boolean allowSendInboxMessages
boolean allDatabasesLoadedCorrectly
abstract void firePropertyChange(String propertyName, Object oldValue, Object newValue)
void loadOfficialHashSets()
synchronized List< HashDb > getKnownBadFileHashSets()
boolean hashDbInfoIsNew(HashDbInfo dbInfo)
TskData.FileKnown getFileKnown()
synchronized void removeHashDatabaseNoSave(HashDb hashDb)
static HashDbManager instance
Set< String > hashSetNames
static synchronized HashDbManager getInstance()
String getValidFilePath(String hashSetName, String configuredPath)
static final String KNOWN_STATUS_PARAM
final JFileChooserFactory chooserHelper
abstract HashDb.KnownFilesType getKnownFilesType()
synchronized HashDb addNewHashDatabase(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType)
boolean isDefaultInboxMessages()
synchronized void removePropertyChangeListener(PropertyChangeListener listener)
JFileChooser getChooser()
abstract HashHitInfo lookupMD5(Content content)
synchronized List< HashDb > getUpdateableHashSets()
synchronized List< HashDb > getAllHashSets()
abstract boolean isUpdateable()
abstract boolean lookupMD5Quick(Content content)
abstract String getDatabasePath()
void propertyChange(PropertyChangeEvent event)
void closeHashDatabases(List< HashDb > hashDatabases)
synchronized void loadLastSavedConfiguration()
HashDb getOfficialHashDbFromFile(File file)
abstract void addPropertyChangeListener(PropertyChangeListener pcl)
synchronized static Logger getLogger(String name)
final boolean defaultSendInboxMessages
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)
boolean isInboxMessagesAllowed()
abstract boolean hasIndexOnly()
SleuthkitHashSet addHashDatabase(int handle, String hashSetName, boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType)
abstract boolean getSearchDuringIngest()
static CentralRepository getInstance()
void updateHashSetsFromCentralRepository()
synchronized List< HashDb > getKnownFileHashSets()
void configureLocalDb(HashDbInfo hashDbInfo)
synchronized HashDb addExistingHashDatabase(String hashSetName, String path, boolean searchDuringIngest, boolean sendIngestMessages, HashDb.KnownFilesType knownFilesType)
static final int FILES_TYPE_ID
static final FilenameFilter DEFAULT_KDB_FILTER
static boolean isEnabled()
abstract void addHashes(Content content)
abstract void removePropertyChangeListener(PropertyChangeListener pcl)
List< HashDb > officialHashSets
List< HashDbInfo > handleNameConflict(List< HashDbInfo > curHashsets, Set< String > officialNames)