mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-14 17:06:16 +00:00
Merge pull request #7050 from APriestman/7698_pcArtifacts
7698 Copy DataArtifacts and AnalysisResults into the portable case
This commit is contained in:
commit
ecff05d338
@ -62,6 +62,7 @@ import org.sleuthkit.autopsy.report.ReportProgressPanel;
|
||||
import org.sleuthkit.caseuco.CaseUcoExporter;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.Account;
|
||||
import org.sleuthkit.datamodel.AnalysisResult;
|
||||
import org.sleuthkit.datamodel.Blackboard.BlackboardException;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifactTag;
|
||||
@ -69,12 +70,19 @@ import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
import org.sleuthkit.datamodel.CaseDbAccessManager;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.datamodel.ContentTag;
|
||||
import org.sleuthkit.datamodel.DataArtifact;
|
||||
import org.sleuthkit.datamodel.DataSource;
|
||||
import org.sleuthkit.datamodel.FileSystem;
|
||||
import org.sleuthkit.datamodel.Host;
|
||||
import org.sleuthkit.datamodel.Image;
|
||||
import org.sleuthkit.datamodel.LocalFilesDataSource;
|
||||
import org.sleuthkit.datamodel.OsAccount;
|
||||
import org.sleuthkit.datamodel.OsAccountManager;
|
||||
import org.sleuthkit.datamodel.OsAccountManager.NotUserSIDException;
|
||||
import org.sleuthkit.datamodel.OsAccountRealm;
|
||||
import org.sleuthkit.datamodel.OsAccountRealmManager;
|
||||
import org.sleuthkit.datamodel.Pool;
|
||||
import org.sleuthkit.datamodel.Score;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase.CaseDbTransaction;
|
||||
import org.sleuthkit.datamodel.TagName;
|
||||
@ -133,6 +141,12 @@ public class PortableCaseReportModule implements ReportModule {
|
||||
// Map of old artifact ID to new artifact
|
||||
private final Map<Long, BlackboardArtifact> oldArtifactIdToNewArtifact = new HashMap<>();
|
||||
|
||||
// Map of old OS account id to new OS account id
|
||||
private final Map<Long, Long> oldOsAccountIdToNewOsAccountId = new HashMap<>();
|
||||
|
||||
// Map of old OS account realm id to new OS account ream id
|
||||
private final Map<Long, OsAccountRealm> oldRealmIdToNewRealm = new HashMap<>();
|
||||
|
||||
public PortableCaseReportModule() {
|
||||
}
|
||||
|
||||
@ -392,8 +406,8 @@ public class PortableCaseReportModule implements ReportModule {
|
||||
// Copy interesting files and results
|
||||
if (!setNames.isEmpty()) {
|
||||
try {
|
||||
List<BlackboardArtifact> interestingFiles = currentCase.getSleuthkitCase().getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT);
|
||||
for (BlackboardArtifact art : interestingFiles) {
|
||||
List<AnalysisResult> interestingFiles = currentCase.getSleuthkitCase().getBlackboard().getAnalysisResultsByType(BlackboardArtifact.Type.TSK_INTERESTING_FILE_HIT.getTypeID());
|
||||
for (AnalysisResult art : interestingFiles) {
|
||||
// Check for cancellation
|
||||
if (progressPanel.getStatus() == ReportProgressPanel.ReportStatus.CANCELED) {
|
||||
handleCancellation(progressPanel);
|
||||
@ -411,8 +425,8 @@ public class PortableCaseReportModule implements ReportModule {
|
||||
}
|
||||
|
||||
try {
|
||||
List<BlackboardArtifact> interestingResults = currentCase.getSleuthkitCase().getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT);
|
||||
for (BlackboardArtifact art : interestingResults) {
|
||||
List<AnalysisResult> interestingResults = currentCase.getSleuthkitCase().getBlackboard().getAnalysisResultsByType(BlackboardArtifact.Type.TSK_INTERESTING_ARTIFACT_HIT.getTypeID());
|
||||
for (AnalysisResult art : interestingResults) {
|
||||
// Check for cancellation
|
||||
if (progressPanel.getStatus() == ReportProgressPanel.ReportStatus.CANCELED) {
|
||||
handleCancellation(progressPanel);
|
||||
@ -936,9 +950,6 @@ public class PortableCaseReportModule implements ReportModule {
|
||||
String.join(",", oldAssociatedAttribute.getSources()), newAssociatedArtifact.getArtifactID()));
|
||||
}
|
||||
|
||||
// Create the new artifact
|
||||
int newArtifactTypeId = getNewArtifactTypeId(artifactToCopy);
|
||||
BlackboardArtifact newArtifact = portableSkCase.newBlackboardArtifact(newArtifactTypeId, newContentId);
|
||||
List<BlackboardAttribute> oldAttrs = artifactToCopy.getAttributes();
|
||||
|
||||
// Copy over each attribute, making sure the type is in the new case.
|
||||
@ -977,8 +988,62 @@ public class PortableCaseReportModule implements ReportModule {
|
||||
throw new TskCoreException("Unexpected attribute value type found: " + oldAttr.getValueType().getLabel()); // NON-NLS
|
||||
}
|
||||
}
|
||||
// Create the new artifact
|
||||
int newArtifactTypeId = getNewArtifactTypeId(artifactToCopy);
|
||||
BlackboardArtifact.Type newArtifactType = portableSkCase.getBlackboard().getArtifactType(newArtifactTypeId);
|
||||
BlackboardArtifact newArtifact;
|
||||
|
||||
newArtifact.addAttributes(newAttrs);
|
||||
// First, check if the artifact being copied is an AnalysisResult or a DataArtifact. If it
|
||||
// is neither, attempt to reload it as the appropriate subclass.
|
||||
if (!((artifactToCopy instanceof AnalysisResult) || (artifactToCopy instanceof DataArtifact))) {
|
||||
try {
|
||||
if (newArtifactType.getCategory().equals(BlackboardArtifact.Category.ANALYSIS_RESULT)) {
|
||||
AnalysisResult ar = currentCase.getSleuthkitCase().getBlackboard().getAnalysisResultById(artifactToCopy.getId());
|
||||
if (ar != null) {
|
||||
artifactToCopy = ar;
|
||||
}
|
||||
} else {
|
||||
DataArtifact da = currentCase.getSleuthkitCase().getBlackboard().getDataArtifactById(artifactToCopy.getId());
|
||||
if (da != null) {
|
||||
artifactToCopy = da;
|
||||
}
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
// If the lookup failed, just use the orginal BlackboardArtifact
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
if (artifactToCopy instanceof AnalysisResult) {
|
||||
AnalysisResult analysisResultToCopy = (AnalysisResult) artifactToCopy;
|
||||
newArtifact = portableSkCase.getBlackboard().newAnalysisResult(newArtifactType, newContentId,
|
||||
newIdToContent.get(newContentId).getDataSource().getId(), analysisResultToCopy.getScore(),
|
||||
analysisResultToCopy.getConclusion(), analysisResultToCopy.getConfiguration(),
|
||||
analysisResultToCopy.getJustification(), newAttrs).getAnalysisResult();
|
||||
} else if (artifactToCopy instanceof DataArtifact) {
|
||||
DataArtifact dataArtifactToCopy = (DataArtifact) artifactToCopy;
|
||||
Long newOsAccountId = null;
|
||||
if (dataArtifactToCopy.getOsAccountObjectId().isPresent()) {
|
||||
copyOsAccount(dataArtifactToCopy.getOsAccountObjectId().get());
|
||||
newOsAccountId = oldOsAccountIdToNewOsAccountId.get((dataArtifactToCopy.getOsAccountObjectId().get()));
|
||||
}
|
||||
newArtifact = portableSkCase.getBlackboard().newDataArtifact(newArtifactType, newContentId,
|
||||
newIdToContent.get(newContentId).getDataSource().getId(),
|
||||
newAttrs, newOsAccountId);
|
||||
} else {
|
||||
if (newArtifactType.getCategory().equals(BlackboardArtifact.Category.ANALYSIS_RESULT)) {
|
||||
newArtifact = portableSkCase.getBlackboard().newAnalysisResult(newArtifactType, newContentId,
|
||||
newIdToContent.get(newContentId).getDataSource().getId(), Score.SCORE_NONE,
|
||||
null, null, null, newAttrs).getAnalysisResult();
|
||||
} else {
|
||||
newArtifact = portableSkCase.getBlackboard().newDataArtifact(newArtifactType, newContentId,
|
||||
newIdToContent.get(newContentId).getDataSource().getId(),
|
||||
newAttrs, null);
|
||||
}
|
||||
}
|
||||
} catch (BlackboardException ex) {
|
||||
throw new TskCoreException("Error copying artifact with ID: " + artifactToCopy.getId());
|
||||
}
|
||||
|
||||
oldArtifactIdToNewArtifact.put(artifactToCopy.getArtifactID(), newArtifact);
|
||||
return newArtifact;
|
||||
@ -1088,6 +1153,14 @@ public class PortableCaseReportModule implements ReportModule {
|
||||
newHost = portableSkCase.getHostManager().newHost(oldHost.getName());
|
||||
}
|
||||
|
||||
// Copy the associated OS account (if needed) before beginning transaction.
|
||||
if (content instanceof AbstractFile) {
|
||||
AbstractFile file = (AbstractFile) content;
|
||||
if (file.getOsAccountObjectId().isPresent()) {
|
||||
copyOsAccount(file.getOsAccountObjectId().get());
|
||||
}
|
||||
}
|
||||
|
||||
CaseDbTransaction trans = portableSkCase.beginTransaction();
|
||||
try {
|
||||
if (content instanceof Image) {
|
||||
@ -1140,10 +1213,16 @@ public class PortableCaseReportModule implements ReportModule {
|
||||
// Construct the relative path to the copied file
|
||||
String relativePath = FILE_FOLDER_NAME + File.separator + exportSubFolder + File.separator + fileName;
|
||||
|
||||
Long newOsAccountId = null;
|
||||
if (abstractFile.getOsAccountObjectId().isPresent()) {
|
||||
newOsAccountId = oldOsAccountIdToNewOsAccountId.get(abstractFile.getOsAccountObjectId().get());
|
||||
}
|
||||
|
||||
newContent = portableSkCase.addLocalFile(abstractFile.getName(), relativePath, abstractFile.getSize(),
|
||||
abstractFile.getCtime(), abstractFile.getCrtime(), abstractFile.getAtime(), abstractFile.getMtime(),
|
||||
abstractFile.getMd5Hash(), abstractFile.getSha256Hash(), abstractFile.getKnown(), abstractFile.getMIMEType(),
|
||||
true, TskData.EncodingType.NONE,
|
||||
newOsAccountId, abstractFile.getOwnerUid().orElse(null),
|
||||
newParent, trans);
|
||||
} catch (IOException ex) {
|
||||
throw new TskCoreException("Error copying file " + abstractFile.getName() + " with original obj ID "
|
||||
@ -1167,6 +1246,72 @@ public class PortableCaseReportModule implements ReportModule {
|
||||
return oldIdToNewContent.get(content.getId()).getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy an OS Account to the new case and add it to the oldOsAccountIdToNewOsAccountId map.
|
||||
* Will also copy the associated realm.
|
||||
*
|
||||
* @param oldOsAccountId The OS account id in the current case.
|
||||
*/
|
||||
private void copyOsAccount(Long oldOsAccountId) throws TskCoreException {
|
||||
// If it has already been copied, we're done.
|
||||
if (oldOsAccountIdToNewOsAccountId.containsKey(oldOsAccountId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Load the OS account from the current case.
|
||||
OsAccountManager oldOsAcctManager = currentCase.getSleuthkitCase().getOsAccountManager();
|
||||
OsAccount oldOsAccount = oldOsAcctManager.getOsAccountByObjectId(oldOsAccountId);
|
||||
|
||||
// Load the realm associated with the OS account.
|
||||
OsAccountRealmManager oldRealmManager = currentCase.getSleuthkitCase().getOsAccountRealmManager();
|
||||
OsAccountRealm oldRealm = oldRealmManager.getRealmByRealmId(oldOsAccount.getRealmId());
|
||||
|
||||
// Copy the realm to the portable case if necessary.
|
||||
if (!oldRealmIdToNewRealm.containsKey(oldOsAccount.getRealmId())) {
|
||||
OsAccountRealmManager newRealmManager = portableSkCase.getOsAccountRealmManager();
|
||||
|
||||
Host host = null;
|
||||
if (oldRealm.getScopeHost().isPresent()) {
|
||||
host = oldRealm.getScopeHost().get();
|
||||
} else {
|
||||
if (oldRealm.getScope().equals(OsAccountRealm.RealmScope.DOMAIN)) {
|
||||
// This is a workaround to get around needing a new method for copying the realm.
|
||||
// The host won't be stored since it's a domain-scoped realm.
|
||||
List<Host> hosts = portableSkCase.getHostManager().getAllHosts();
|
||||
if (hosts.isEmpty()) {
|
||||
throw new TskCoreException("Failed to copy OsAccountRealm with ID=" + oldOsAccount.getRealmId() + " because there are no hosts in the case");
|
||||
}
|
||||
host = hosts.get(0);
|
||||
} else {
|
||||
throw new TskCoreException("Failed to copy OsAccountRealm with ID=" + oldOsAccount.getRealmId() + " because it is non-domain scoped but has no scope host");
|
||||
}
|
||||
}
|
||||
|
||||
// We currently only support one realm name.
|
||||
String realmName = null;
|
||||
List<String> names = oldRealm.getRealmNames();
|
||||
if (!names.isEmpty()) {
|
||||
realmName = names.get(0);
|
||||
}
|
||||
|
||||
try {
|
||||
OsAccountRealm newRealm = newRealmManager.newWindowsRealm(oldRealm.getRealmAddr().orElse(null), realmName, host, oldRealm.getScope());
|
||||
oldRealmIdToNewRealm.put(oldOsAccount.getRealmId(), newRealm);
|
||||
} catch (NotUserSIDException ex) {
|
||||
throw new TskCoreException("Failed to copy OsAccountRealm with ID=" + oldOsAccount.getRealmId(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
OsAccountManager newOsAcctManager = portableSkCase.getOsAccountManager();
|
||||
try {
|
||||
OsAccount newOsAccount = newOsAcctManager.newWindowsOsAccount(oldOsAccount.getAddr().orElse(null),
|
||||
oldOsAccount.getLoginName().orElse(null), oldRealmIdToNewRealm.get(oldOsAccount.getRealmId()));
|
||||
oldOsAccountIdToNewOsAccountId.put(oldOsAccountId, newOsAccount.getId());
|
||||
} catch (NotUserSIDException ex) {
|
||||
throw new TskCoreException("Failed to copy OsAccount with ID=" + oldOsAccount.getId(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy path ID attribute to new case along with the referenced file.
|
||||
*
|
||||
@ -1344,6 +1489,8 @@ public class PortableCaseReportModule implements ReportModule {
|
||||
oldArtTypeIdToNewArtTypeId.clear();
|
||||
oldAttrTypeIdToNewAttrType.clear();
|
||||
oldArtifactIdToNewArtifact.clear();
|
||||
oldOsAccountIdToNewOsAccountId.clear();
|
||||
oldRealmIdToNewRealm.clear();
|
||||
|
||||
closePortableCaseDatabase();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user