diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeInstance.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeInstance.java index a8974f8e5a..12fd9eac04 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeInstance.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeInstance.java @@ -260,7 +260,7 @@ public class CorrelationAttributeInstance implements Serializable { for (Account.Type type : Account.Type.PREDEFINED_ACCOUNT_TYPES) { // Skip Phone and Email accounts as there are already Correlation types defined for those. if (type != Account.Type.EMAIL && type != Account.Type.PHONE) { - defaultCorrelationTypes.add(new CorrelationAttributeInstance.Type(correlationTypeId, type.getDisplayName(), type.getTypeName().toLowerCase(), true, true)); //NON-NLS + defaultCorrelationTypes.add(new CorrelationAttributeInstance.Type(correlationTypeId, type.getDisplayName(), type.getTypeName().toLowerCase() + "_acct", true, true)); //NON-NLS correlationTypeId++; } } diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepoFactory.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepoFactory.java index 963809c5d7..2fa248598e 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepoFactory.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepoFactory.java @@ -701,8 +701,10 @@ public class RdbmsCentralRepoFactory { + "created_date " + getBigIntType(selectedPlatform) + " ," + "modified_date " + getBigIntType(selectedPlatform) + " ," + "status_id integer NOT NULL," + + "examiner_id integer NOT NULL," + "CONSTRAINT uuid_unique UNIQUE(uuid)," - + "FOREIGN KEY (status_id) REFERENCES persona_status(status_id)" + + "FOREIGN KEY (status_id) REFERENCES persona_status(status_id), " + + "FOREIGN KEY (examiner_id) REFERENCES examiners(id)" + ")"; } diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Installer.java b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Installer.java index 1609047e6d..54a642b0dc 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Installer.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Installer.java @@ -19,6 +19,7 @@ package org.sleuthkit.autopsy.centralrepository.eventlisteners; import java.lang.reflect.InvocationTargetException; +import java.util.Map; import java.util.logging.Level; import javax.swing.JOptionPane; import javax.swing.SwingUtilities; @@ -28,8 +29,6 @@ import org.openide.windows.WindowManager; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoDbManager; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoException; -import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoDbUtil; -import org.sleuthkit.autopsy.centralrepository.datamodel.SqliteCentralRepoSettings; import org.sleuthkit.autopsy.core.RuntimeProperties; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.ModuleSettings; @@ -68,10 +67,25 @@ public class Installer extends ModuleInstall { Case.addPropertyChangeListener(pcl); ieListener.installListeners(); - String initialized = ModuleSettings.getConfigSetting("CentralRepository", "initialized"); + + Map centralRepoSettings = ModuleSettings.getConfigSettings("CentralRepository"); + String initializedStr = centralRepoSettings.get("initialized"); + + // check to see if the repo has been initialized asking to setup cr + boolean initialized = Boolean.parseBoolean(initializedStr); + + // if it hasn't received that flag, check for a previous install where cr is already setup + if (!initialized) { + boolean prevRepo = Boolean.parseBoolean(centralRepoSettings.get("db.useCentralRepo")); + // if it has been previously set up and is in use, mark as previously initialized and save the settings + if (prevRepo) { + initialized = true; + ModuleSettings.setConfigSetting("CentralRepository", "initialized", "true"); + } + } // if central repository hasn't been previously initialized, initialize it - if (!Boolean.parseBoolean(initialized)) { + if (!initialized) { // if running with a GUI, prompt the user if (RuntimeProperties.runningWithGUI()) { try { diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextViewer.java index 2e183755f1..1baa412495 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextViewer.java @@ -287,7 +287,8 @@ public final class ContextViewer extends javax.swing.JPanel implements DataConte */ @NbBundle.Messages({ "ContextViewer.attachmentSource=Attached to: ", - "ContextViewer.downloadSource=Downloaded from: " + "ContextViewer.downloadSource=Downloaded from: ", + "ContextViewer.recentDocs=Recent Documents: " }) private void setSourceFields(BlackboardArtifact associatedArtifact) throws TskCoreException { if (BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE.getTypeID() == associatedArtifact.getArtifactTypeID() @@ -301,6 +302,10 @@ public final class ContextViewer extends javax.swing.JPanel implements DataConte setSourceName(Bundle.ContextViewer_downloadSource()); setSourceText(webDownloadArtifactToString(associatedArtifact)); + } else if (BlackboardArtifact.ARTIFACT_TYPE.TSK_RECENT_OBJECT.getTypeID() == associatedArtifact.getArtifactTypeID()) { + setSourceName(Bundle.ContextViewer_recentDocs()); + setSourceText(recentDocArtifactToString(associatedArtifact)); + } } @@ -355,6 +360,31 @@ public final class ContextViewer extends javax.swing.JPanel implements DataConte return sb.toString(); } + /** + * Returns a display string with recent Doc + * artifact. + * + * @param artifact artifact to get doc from. + * + * @return Display string with download URL and date/time. + * + * @throws TskCoreException + */ + @NbBundle.Messages({ + "ContextViewer.file=File", + "ContextViewer.on=On" + }) + private String recentDocArtifactToString(BlackboardArtifact artifact) throws TskCoreException { + StringBuilder sb = new StringBuilder(ARTIFACT_STR_MAX_LEN); + Map attributesMap = getAttributesMap(artifact); + + if (BlackboardArtifact.ARTIFACT_TYPE.TSK_RECENT_OBJECT.getTypeID() == artifact.getArtifactTypeID()) { + appendAttributeString(sb, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH, attributesMap, Bundle.ContextViewer_file()); + appendAttributeString(sb, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME, attributesMap, Bundle.ContextViewer_on()); + } + return sb.toString(); + } + /** * Returns a abbreviated display string for a message artifact. * diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java index 2d56c7b6fe..0b119e00d0 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java @@ -56,6 +56,7 @@ import org.xml.sax.SAXException; import java.nio.file.Path; import java.util.AbstractMap; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Collection; import java.util.Date; @@ -74,7 +75,9 @@ import org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchService; import org.sleuthkit.autopsy.recentactivity.ShellBagParser.ShellBag; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.BlackboardArtifact; +import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_ASSOCIATED_OBJECT; import org.sleuthkit.datamodel.BlackboardAttribute; +import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT; import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED; import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_CREATED; import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_MODIFIED; @@ -1201,8 +1204,6 @@ class ExtractRegistry extends Extract { /** * Create recently used artifacts from adobemru records * - * @param regFileName name of the regripper output file - * * @param regFile registry file the artifact is associated with * * @param reader buffered reader to parse adobemru records @@ -1230,7 +1231,6 @@ class ExtractRegistry extends Extract { if (fileName.charAt(0) == '/') { fileName = fileName.substring(1,fileName.length() - 1); fileName = fileName.replaceFirst("/", ":/"); - fileName = FilenameUtils.normalize(fileName, true); } // Check to see if more then 2 tokens, Date may not be populated, will default to 0 if (tokens.length > 2) { @@ -1251,12 +1251,17 @@ class ExtractRegistry extends Extract { BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, regFile, attributes); if(bba != null) { bbartifacts.add(bba); + fileName = fileName.replace("\0", ""); + bba = createAssociatedArtifact(FilenameUtils.normalize(fileName, true), bba); + if (bba != null) { + bbartifacts.add(bba); + } } line = reader.readLine(); } line = line.trim(); } - } + } if (!bbartifacts.isEmpty()) { postArtifacts(bbartifacts); } @@ -1265,8 +1270,6 @@ class ExtractRegistry extends Extract { /** * Create recently used artifacts to parse the mpmru records * - * @param regFileName name of the regripper output file - * * @param regFile registry file the artifact is associated with * * @param reader buffered reader to parse adobemru records @@ -1287,12 +1290,19 @@ class ExtractRegistry extends Extract { // Split line on "> " which is the record delimiter between position and file String tokens[] = line.split("> "); String fileName = tokens[1]; - fileName = FilenameUtils.normalize(fileName, true); Collection attributes = new ArrayList<>(); attributes.add(new BlackboardAttribute(TSK_PATH, getName(), fileName)); BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, regFile, attributes); if(bba != null) { bbartifacts.add(bba); + bba = createAssociatedArtifact(fileName, bba); + if (bba != null) { + bbartifacts.add(bba); + bba = createAssociatedArtifact(FilenameUtils.normalize(fileName, true), bba); + if (bba != null) { + bbartifacts.add(bba); + } + } } line = reader.readLine(); } @@ -1307,8 +1317,6 @@ class ExtractRegistry extends Extract { /** * Create recently used artifacts to parse the regripper output * - * @param regFileName name of the regripper output file - * * @param regFile registry file the artifact is associated with * * @param reader buffered reader to parse adobemru records @@ -1329,12 +1337,15 @@ class ExtractRegistry extends Extract { // Split line on "> " which is the record delimiter between position and file String tokens[] = line.split("> "); String fileName = tokens[1]; - fileName = FilenameUtils.normalize(fileName, true); Collection attributes = new ArrayList<>(); attributes.add(new BlackboardAttribute(TSK_PATH, getName(), fileName)); BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, regFile, attributes); if(bba != null) { bbartifacts.add(bba); + bba = createAssociatedArtifact(FilenameUtils.normalize(fileName, true), bba); + if (bba != null) { + bbartifacts.add(bba); + } } line = reader.readLine(); } @@ -1349,8 +1360,6 @@ class ExtractRegistry extends Extract { /** * Create recently used artifacts to parse the WinRAR output * - * @param regFileName name of the regripper output file - * * @param regFile registry file the artifact is associated with * * @param reader buffered reader to parse adobemru records @@ -1372,12 +1381,15 @@ class ExtractRegistry extends Extract { // Split line on "> " which is the record delimiter between position and file String tokens[] = line.split("> "); String fileName = tokens[1]; - fileName = FilenameUtils.normalize(fileName, true); Collection attributes = new ArrayList<>(); attributes.add(new BlackboardAttribute(TSK_PATH, getName(), fileName)); BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, regFile, attributes); if(bba != null) { bbartifacts.add(bba); + bba = createAssociatedArtifact(FilenameUtils.normalize(fileName, true), bba); + if (bba != null) { + bbartifacts.add(bba); + } } line = reader.readLine(); } @@ -1393,8 +1405,6 @@ class ExtractRegistry extends Extract { /** * Create recently used artifacts to parse the runmru ArcHistory records * - * @param regFileName name of the regripper output file - * * @param regFile registry file the artifact is associated with * * @param reader buffered reader to parse adobemru records @@ -1410,12 +1420,15 @@ class ExtractRegistry extends Extract { // Columns are // String fileName = line; - fileName = FilenameUtils.normalize(fileName, true); Collection attributes = new ArrayList<>(); attributes.add(new BlackboardAttribute(TSK_PATH, getName(), fileName)); BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, regFile, attributes); if (bba != null) { bbartifacts.add(bba); + bba = createAssociatedArtifact(FilenameUtils.normalize(fileName, true), bba); + if (bba != null) { + bbartifacts.add(bba); + } } line = reader.readLine(); line = line.trim(); @@ -1429,8 +1442,6 @@ class ExtractRegistry extends Extract { /** * Create recently used artifacts to parse the Office Documents 2010 records * - * @param regFileName name of the regripper output file - * * @param regFile registry file the artifact is associated with * * @param reader buffered reader to parse adobemru records @@ -1454,13 +1465,16 @@ class ExtractRegistry extends Extract { Long docDate = Long.valueOf(tokens[0]); String fileNameTokens[] = tokens[4].split(" - "); String fileName = fileNameTokens[1]; - fileName = FilenameUtils.normalize(fileName, true); Collection attributes = new ArrayList<>(); attributes.add(new BlackboardAttribute(TSK_PATH, getName(), fileName)); attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, getName(), docDate)); BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, regFile, attributes); if(bba != null) { bbartifacts.add(bba); + bba = createAssociatedArtifact(FilenameUtils.normalize(fileName, true), bba); + if (bba != null) { + bbartifacts.add(bba); + } } line = reader.readLine(); line = line.trim(); @@ -1473,8 +1487,6 @@ class ExtractRegistry extends Extract { /** * Create recently used artifacts to parse the trustrecords records * - * @param regFileName name of the regripper output file - * * @param regFile registry file the artifact is associated with * * @param reader buffered reader to parse adobemru records @@ -1501,7 +1513,6 @@ class ExtractRegistry extends Extract { String tokens[] = line.split(" : "); fileName = tokens[1]; fileName = fileName.replace("%USERPROFILE%", userProfile); - fileName = FilenameUtils.normalize(fileName, true); // Time in the format of Wed May 31 14:33:03 2017 Z try { String fileUsedTime = tokens[0].replaceAll(" Z",""); @@ -1518,6 +1529,10 @@ class ExtractRegistry extends Extract { BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, regFile, attributes); if(bba != null) { bbartifacts.add(bba); + bba = createAssociatedArtifact(FilenameUtils.normalize(fileName, true), bba); + if (bba != null) { + bbartifacts.add(bba); + } } line = line.trim(); } @@ -1526,6 +1541,46 @@ class ExtractRegistry extends Extract { postArtifacts(bbartifacts); } } + + /** + * Create associated artifacts using file name and path and the artifact it associates with + * + * @param filePathName file and path of object being associated with + * + * @param bba blackboard artifact to associate with + * + * @returnv BlackboardArtifact or a null value + */ + private BlackboardArtifact createAssociatedArtifact(String filePathName, BlackboardArtifact bba) { + org.sleuthkit.autopsy.casemodule.services.FileManager fileManager = currentCase.getServices().getFileManager(); + String fileName = FilenameUtils.getName(filePathName); + String filePath = FilenameUtils.getPath(filePathName); + List sourceFiles; + try { + sourceFiles = fileManager.findFiles(dataSource, fileName, filePath); //NON-NLS + if (!sourceFiles.isEmpty()) { + for (AbstractFile sourceFile : sourceFiles) { + if (sourceFile.getParentPath().endsWith(filePath)) { + Collection bbattributes2 = new ArrayList<>(); + bbattributes2.addAll(Arrays.asList( + new BlackboardAttribute(TSK_ASSOCIATED_ARTIFACT, this.getName(), + bba.getArtifactID()))); + + BlackboardArtifact associatedObjectBba = createArtifactWithAttributes(TSK_ASSOCIATED_OBJECT, sourceFile, bbattributes2); + if (associatedObjectBba != null) { + return associatedObjectBba; + } + } + } + } + } catch (TskCoreException ex) { + // only catching the error and displaying the message as the file may not exist on the + // system anymore + logger.log(Level.WARNING, String.format("Error finding actual file %s. file may not exist", filePathName)); //NON-NLS + } + + return null; + } /** * Create the shellbag artifacts from the list of ShellBag objects. diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RecentDocumentsByLnk.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RecentDocumentsByLnk.java index 7898613373..42e5d2ecb0 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RecentDocumentsByLnk.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RecentDocumentsByLnk.java @@ -23,6 +23,7 @@ package org.sleuthkit.autopsy.recentactivity; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.logging.Level; @@ -42,6 +43,8 @@ import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE; import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.*; +import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_ASSOCIATED_OBJECT; +import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT; /** * Recent documents class that will extract recent documents in the form of .lnk @@ -108,7 +111,7 @@ class RecentDocumentsByLnk extends Extract { } Collection bbattributes = new ArrayList<>(); - String path = FilenameUtils.normalize(lnk.getBestPath(), true); + String path = lnk.getBestPath(); bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH, NbBundle.getMessage(this.getClass(), "RecentDocumentsByLnk.parentModuleName.noSpace"), @@ -124,12 +127,53 @@ class RecentDocumentsByLnk extends Extract { BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, recentFile, bbattributes); if(bba != null) { bbartifacts.add(bba); + bba = createAssociatedArtifact(path, bba); + if (bba != null) { + bbartifacts.add(bba); + } } } - + postArtifacts(bbartifacts); } + /** + * Create associated artifacts using file name and path and the artifact it associates with + * + * @param filePathName file and path of object being associated with + * + * @param bba blackboard artifact to associate with + * + * @returnv BlackboardArtifact or a null value + */ + private BlackboardArtifact createAssociatedArtifact(String filePathName, BlackboardArtifact bba) { + org.sleuthkit.autopsy.casemodule.services.FileManager fileManager = currentCase.getServices().getFileManager(); + String normalizePathName = FilenameUtils.normalize(filePathName, true); + String fileName = FilenameUtils.getName(normalizePathName); + String filePath = FilenameUtils.getPath(normalizePathName); + List sourceFiles; + try { + sourceFiles = fileManager.findFiles(dataSource, fileName, filePath); //NON-NLS + for (AbstractFile sourceFile : sourceFiles) { + if (sourceFile.getParentPath().endsWith(filePath)) { + Collection bbattributes2 = new ArrayList<>(); + bbattributes2.addAll(Arrays.asList( + new BlackboardAttribute(TSK_ASSOCIATED_ARTIFACT, this.getName(), + bba.getArtifactID()))); + + BlackboardArtifact associatedObjectBba = createArtifactWithAttributes(TSK_ASSOCIATED_OBJECT, sourceFile, bbattributes2); + if (associatedObjectBba != null) { + return associatedObjectBba; + } + } + } + } catch (TskCoreException ex) { + logger.log(Level.WARNING, String.format("Error finding actual file %s. file may not exist", filePathName)); //NON-NLS + } + + return null; + } + @Override public void process(Content dataSource, IngestJobContext context, DataSourceIngestModuleProgress progressBar) { this.dataSource = dataSource;