mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-06 21:00:22 +00:00
Merge branch 'new_table_load' of github.com:sleuthkit/autopsy into 8160b-throttleEvents
This commit is contained in:
commit
24a15a2969
@ -135,14 +135,18 @@ public class CorrelationAttributeUtil {
|
||||
*
|
||||
* @return A list, possibly empty, of correlation attribute instances for
|
||||
* the AnalysisResult.
|
||||
*
|
||||
* @SuppressWarnings("deprecation") - we need to support already existing
|
||||
* interesting file and artifact hits.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public static List<CorrelationAttributeInstance> makeCorrAttrsForSearch(AnalysisResult analysisResult) {
|
||||
List<CorrelationAttributeInstance> correlationAttrs = new ArrayList<>();
|
||||
|
||||
if (CentralRepository.isEnabled()) {
|
||||
try {
|
||||
int artifactTypeID = analysisResult.getArtifactTypeID();
|
||||
if (artifactTypeID == ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID()) {
|
||||
if (artifactTypeID == ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID() || artifactTypeID == ARTIFACT_TYPE.TSK_INTERESTING_ITEM.getTypeID()) {
|
||||
//because this attribute retrieval is only occuring when the analysis result is an interesting artifact hit
|
||||
//and only one attribute is being retrieved the analysis result's own get attribute method can be used efficently
|
||||
BlackboardAttribute assocArtifactAttr = analysisResult.getAttribute(BlackboardAttribute.Type.TSK_ASSOCIATED_ARTIFACT);
|
||||
|
@ -73,6 +73,7 @@ public class AnnotationUtils {
|
||||
"AnnotationUtils.fileHitEntry.artifactCommentTitle=Artifact Comment",
|
||||
"AnnotationUtils.fileHitEntry.hashSetHitTitle=Hash Set Hit Comments",
|
||||
"AnnotationUtils.fileHitEntry.interestingFileHitTitle=Interesting File Hit Comments",
|
||||
"AnnotationUtils.fileHitEntry.interestingItemTitle=Interesting Item Comments",
|
||||
"AnnotationUtils.fileHitEntry.setName=Set Name:",
|
||||
"AnnotationUtils.fileHitEntry.comment=Comment:",
|
||||
"AnnotationUtils.sourceFile.title=Source File",
|
||||
@ -94,8 +95,8 @@ public class AnnotationUtils {
|
||||
private static final SectionConfig<Tag> TAG_CONFIG
|
||||
= new SectionConfig<>(Bundle.AnnotationUtils_tagEntry_title(), TAG_ENTRIES);
|
||||
|
||||
// file set attributes and table configurations
|
||||
private static final List<ItemEntry<BlackboardArtifact>> FILESET_HIT_ENTRIES = Arrays.asList(
|
||||
// Item set attributes and table configurations
|
||||
private static final List<ItemEntry<BlackboardArtifact>> ITEMSET_HIT_ENTRIES = Arrays.asList(
|
||||
new ItemEntry<>(Bundle.AnnotationUtils_fileHitEntry_setName(),
|
||||
(bba) -> tryGetAttribute(bba, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME)),
|
||||
new ItemEntry<>(Bundle.AnnotationUtils_fileHitEntry_comment(),
|
||||
@ -103,13 +104,16 @@ public class AnnotationUtils {
|
||||
);
|
||||
|
||||
private static final SectionConfig<BlackboardArtifact> INTERESTING_FILE_CONFIG
|
||||
= new SectionConfig<>(Bundle.AnnotationUtils_fileHitEntry_interestingFileHitTitle(), FILESET_HIT_ENTRIES);
|
||||
= new SectionConfig<>(Bundle.AnnotationUtils_fileHitEntry_interestingFileHitTitle(), ITEMSET_HIT_ENTRIES);
|
||||
|
||||
private static final SectionConfig<BlackboardArtifact> INTERESTING_ITEM_CONFIG
|
||||
= new SectionConfig<>(Bundle.AnnotationUtils_fileHitEntry_interestingItemTitle(), ITEMSET_HIT_ENTRIES);
|
||||
|
||||
private static final SectionConfig<BlackboardArtifact> HASHSET_CONFIG
|
||||
= new SectionConfig<>(Bundle.AnnotationUtils_fileHitEntry_hashSetHitTitle(), FILESET_HIT_ENTRIES);
|
||||
= new SectionConfig<>(Bundle.AnnotationUtils_fileHitEntry_hashSetHitTitle(), ITEMSET_HIT_ENTRIES);
|
||||
|
||||
private static final SectionConfig<BlackboardArtifact> ARTIFACT_COMMENT_CONFIG
|
||||
= new SectionConfig<>(Bundle.AnnotationUtils_fileHitEntry_artifactCommentTitle(), FILESET_HIT_ENTRIES);
|
||||
= new SectionConfig<>(Bundle.AnnotationUtils_fileHitEntry_artifactCommentTitle(), ITEMSET_HIT_ENTRIES);
|
||||
|
||||
// central repository attributes and table configuration
|
||||
private static final List<ItemEntry<CorrelationAttributeInstance>> CR_COMMENTS_ENTRIES = Arrays.asList(
|
||||
@ -199,7 +203,11 @@ public class AnnotationUtils {
|
||||
* comes.
|
||||
*
|
||||
* @return If any content was actually rendered.
|
||||
*
|
||||
* @SuppressWarnings("deprecation") - we need to support already existing
|
||||
* interesting file and artifact hits.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
private static boolean renderArtifact(Element parent, BlackboardArtifact bba, Content sourceContent) {
|
||||
boolean contentRendered = appendEntries(parent, TAG_CONFIG, getTags(bba), false, true);
|
||||
|
||||
@ -211,7 +219,7 @@ public class AnnotationUtils {
|
||||
|
||||
// if artifact is a hashset hit or interesting file and has a non-blank comment
|
||||
if ((BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID() == bba.getArtifactTypeID()
|
||||
|| BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID() == bba.getArtifactTypeID())
|
||||
|| BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID() == bba.getArtifactTypeID() || BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ITEM.getTypeID() == bba.getArtifactTypeID())
|
||||
&& (hasTskComment(bba))) {
|
||||
|
||||
boolean filesetRendered = appendEntries(parent, ARTIFACT_COMMENT_CONFIG, Arrays.asList(bba), false, !contentRendered);
|
||||
@ -242,7 +250,11 @@ public class AnnotationUtils {
|
||||
* subheader as opposed to a top-level header.
|
||||
*
|
||||
* @return If any content was actually rendered.
|
||||
*
|
||||
* @SuppressWarnings("deprecation") - we need to support already existing
|
||||
* interesting file and artifact hits.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
private static boolean renderContent(Element parent, Content sourceContent, boolean isSubheader) {
|
||||
boolean contentRendered = appendEntries(parent, TAG_CONFIG, getTags(sourceContent), isSubheader, true);
|
||||
|
||||
@ -266,7 +278,12 @@ public class AnnotationUtils {
|
||||
isSubheader,
|
||||
!contentRendered);
|
||||
|
||||
contentRendered = contentRendered || hashsetRendered || interestingFileRendered;
|
||||
boolean interestingItemRendered = appendEntries(parent, INTERESTING_ITEM_CONFIG,
|
||||
getFileSetHits(sourceFile, BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ITEM),
|
||||
isSubheader,
|
||||
!contentRendered);
|
||||
|
||||
contentRendered = contentRendered || hashsetRendered || interestingFileRendered || interestingItemRendered;
|
||||
}
|
||||
return contentRendered;
|
||||
}
|
||||
|
@ -73,9 +73,15 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data
|
||||
|
||||
private static final Set<IngestManager.IngestModuleEvent> INGEST_MODULE_EVENTS_OF_INTEREST = EnumSet.of(IngestManager.IngestModuleEvent.DATA_ADDED);
|
||||
|
||||
/**
|
||||
* @SuppressWarnings("deprecation") - we need to support already existing
|
||||
* interesting file and artifact hits.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
private static final Set<BlackboardArtifact.Type> ARTIFACT_TYPES_OF_INTEREST = ImmutableSet.of(
|
||||
BlackboardArtifact.Type.TSK_HASHSET_HIT,
|
||||
BlackboardArtifact.Type.TSK_INTERESTING_FILE_HIT
|
||||
BlackboardArtifact.Type.TSK_INTERESTING_FILE_HIT,
|
||||
BlackboardArtifact.Type.TSK_INTERESTING_ITEM
|
||||
);
|
||||
|
||||
private final PropertyChangeListener ingestEventListener = (evt) -> {
|
||||
|
@ -10,6 +10,7 @@ AnnotationUtils.fileHitEntry.artifactCommentTitle=Artifact Comment
|
||||
AnnotationUtils.fileHitEntry.comment=Comment:
|
||||
AnnotationUtils.fileHitEntry.hashSetHitTitle=Hash Set Hit Comments
|
||||
AnnotationUtils.fileHitEntry.interestingFileHitTitle=Interesting File Hit Comments
|
||||
AnnotationUtils.fileHitEntry.interestingItemTitle=Interesting Item Comments
|
||||
AnnotationUtils.fileHitEntry.setName=Set Name:
|
||||
AnnotationUtils.onEmpty=No annotations were found for this particular item.
|
||||
AnnotationUtils.sourceFile.title=Source File
|
||||
|
@ -64,6 +64,7 @@ import static org.sleuthkit.datamodel.BlackboardArtifact.Type.TSK_INTERESTING_AR
|
||||
import static org.sleuthkit.datamodel.BlackboardArtifact.Type.TSK_INTERESTING_FILE_HIT;
|
||||
import static org.sleuthkit.datamodel.BlackboardArtifact.Type.TSK_GEN_INFO;
|
||||
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_DOWNLOAD_SOURCE;
|
||||
import static org.sleuthkit.datamodel.BlackboardArtifact.Type.TSK_INTERESTING_ITEM;
|
||||
import static org.sleuthkit.datamodel.BlackboardArtifact.Type.TSK_TL_EVENT;
|
||||
import static org.sleuthkit.datamodel.BlackboardArtifact.Type.TSK_ASSOCIATED_OBJECT;
|
||||
import static org.sleuthkit.datamodel.BlackboardArtifact.Type.TSK_KEYWORD_HIT;
|
||||
@ -239,7 +240,11 @@ public class Artifacts {
|
||||
* is less than or equal to 0, no filtering will occur.
|
||||
*
|
||||
* @return The generated key.
|
||||
*
|
||||
* @SuppressWarnings("deprecation") - we need to support already
|
||||
* existing interesting file and artifact hits.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
private static TypeNodeKey getTypeKey(BlackboardArtifact.Type type, SleuthkitCase skCase, long dsObjId) {
|
||||
int typeId = type.getTypeID();
|
||||
if (TSK_EMAIL_MSG.getTypeID() == typeId) {
|
||||
@ -254,6 +259,9 @@ public class Artifacts {
|
||||
KeywordHits.RootNode keywordsNode = new KeywordHits(skCase, dsObjId).new RootNode();
|
||||
return new TypeNodeKey(keywordsNode, TSK_KEYWORD_HIT);
|
||||
|
||||
} else if (TSK_INTERESTING_ITEM.getTypeID() == typeId) {
|
||||
InterestingHits.RootNode interestingHitsNode = new InterestingHits(skCase, TSK_INTERESTING_ITEM, dsObjId).new RootNode();
|
||||
return new TypeNodeKey(interestingHitsNode, TSK_INTERESTING_ITEM);
|
||||
} else if (TSK_INTERESTING_ARTIFACT_HIT.getTypeID() == typeId) {
|
||||
InterestingHits.RootNode interestingHitsNode = new InterestingHits(skCase, TSK_INTERESTING_ARTIFACT_HIT, dsObjId).new RootNode();
|
||||
return new TypeNodeKey(interestingHitsNode, TSK_INTERESTING_ARTIFACT_HIT);
|
||||
|
@ -149,7 +149,7 @@ public final class AutopsyTreeChildFactory extends ChildFactory.Detachable<Objec
|
||||
new Views(Case.getCurrentCaseThrows().getSleuthkitCase()),
|
||||
new DataArtifacts(),
|
||||
new AnalysisResults(),
|
||||
new OsAccounts(Case.getCurrentCaseThrows().getSleuthkitCase()),
|
||||
new OsAccounts(),
|
||||
new Tags(),
|
||||
new Reports()
|
||||
);
|
||||
|
@ -149,9 +149,14 @@ public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifa
|
||||
/*
|
||||
* Artifact types for which the file metadata of the artifact's source file
|
||||
* should be displayed in the node's property sheet.
|
||||
*
|
||||
* @SuppressWarnings("deprecation") - we need to support already existing
|
||||
* interesting file and artifact hits.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
private static final Integer[] SHOW_FILE_METADATA = new Integer[]{
|
||||
BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID()
|
||||
BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID(),
|
||||
BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ITEM.getTypeID()
|
||||
};
|
||||
|
||||
private final BlackboardArtifact artifact;
|
||||
@ -868,6 +873,11 @@ public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifa
|
||||
"BlackboardArtifactNode.createSheet.path.displayName=Path",
|
||||
"BlackboardArtifactNode.createSheet.path.name=Path"
|
||||
})
|
||||
/*
|
||||
* @SuppressWarnings("deprecation") - we need to support already existing
|
||||
* interesting file and artifact hits.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
protected Sheet createSheet() {
|
||||
/*
|
||||
@ -925,7 +935,7 @@ public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifa
|
||||
* hit, add the type and description of the interesting artifact to the
|
||||
* sheet.
|
||||
*/
|
||||
if (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID()) {
|
||||
if (artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID() || artifact.getArtifactTypeID() == ARTIFACT_TYPE.TSK_INTERESTING_ITEM.getTypeID()) {
|
||||
try {
|
||||
BlackboardAttribute attribute = artifact.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT));
|
||||
if (attribute != null) {
|
||||
@ -946,7 +956,7 @@ public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifa
|
||||
associatedArtifact.getShortDescription()));
|
||||
}
|
||||
} catch (TskCoreException | NoCurrentCaseException ex) {
|
||||
logger.log(Level.SEVERE, MessageFormat.format("Error getting associated artifact of TSK_INTERESTING_ARTIFACT_HIT artifact (objID={0}))", artifact.getId()), ex); //NON-NLS
|
||||
logger.log(Level.SEVERE, MessageFormat.format("Error getting associated artifact with type " + artifact.getArtifactTypeName() + " artifact (objID={0}))", artifact.getId()), ex); //NON-NLS
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -300,10 +300,10 @@ ImageNode.getActions.viewInNewWin.text=View in New Window
|
||||
ImageNode.createSheet.name.name=Name
|
||||
ImageNode.createSheet.name.displayName=Name
|
||||
ImageNode.createSheet.name.desc=no description
|
||||
Installer.exception.tskVerStringNull.msg=Sleuth Kit JNI test call returned without error, but version string was null\!
|
||||
Installer.exception.taskVerStringBang.msg=Sleuth Kit JNI test call returned without error, but version string was ""\!
|
||||
Installer.tskLibErr.msg=Problem with Sleuth Kit JNI. Test call failed\!\n\nDetails: {0}
|
||||
Installer.tskLibErr.err=Fatal Error\!
|
||||
Installer.exception.tskVerStringNull.msg=Sleuth Kit JNI test call returned without error, but version string was null!
|
||||
Installer.exception.taskVerStringBang.msg=Sleuth Kit JNI test call returned without error, but version string was ""!
|
||||
Installer.tskLibErr.msg=Problem with Sleuth Kit JNI. Test call failed!\n\nDetails: {0}
|
||||
Installer.tskLibErr.err=Fatal Error!
|
||||
InterestingHits.interestingItems.text=INTERESTING ITEMS
|
||||
InterestingHits.displayName.text=Interesting Items
|
||||
InterestingHits.createSheet.name.name=Name
|
||||
@ -334,33 +334,6 @@ OpenReportAction.actionPerformed.NoOpenInEditorSupportMessage=This platform (ope
|
||||
OpenReportAction.actionPerformed.MissingReportFileMessage=The report file no longer exists.
|
||||
OpenReportAction.actionPerformed.ReportFileOpenPermissionDeniedMessage=Permission to open the report file was denied.
|
||||
OsAccount_listNode_name=OS Accounts
|
||||
OsAccounts.createSheet.comment.displayName=C
|
||||
OsAccounts.createSheet.comment.name=C
|
||||
# {0} - occurrenceCount
|
||||
OsAccounts.createSheet.count.description=There were {0} datasource(s) found with occurrences of the OS Account correlation value
|
||||
OsAccounts.createSheet.count.displayName=O
|
||||
OsAccounts.createSheet.count.hashLookupNotRun.description=Hash lookup had not been run on this file when the column was populated
|
||||
OsAccounts.createSheet.count.name=O
|
||||
OsAccounts.createSheet.score.displayName=S
|
||||
OsAccounts.createSheet.score.name=S
|
||||
OsAccounts_accountHostNameProperty_desc=OS Account Host Name
|
||||
OsAccounts_accountHostNameProperty_displayName=Host
|
||||
OsAccounts_accountHostNameProperty_name=HostName
|
||||
OsAccounts_accountNameProperty_desc=Os Account name
|
||||
OsAccounts_accountNameProperty_displayName=Name
|
||||
OsAccounts_accountNameProperty_name=Name
|
||||
OsAccounts_accountRealmNameProperty_desc=OS Account Realm Name
|
||||
OsAccounts_accountRealmNameProperty_displayName=Realm Name
|
||||
OsAccounts_accountRealmNameProperty_name=RealmName
|
||||
OsAccounts_accountScopeNameProperty_desc=OS Account Scope Name
|
||||
OsAccounts_accountScopeNameProperty_displayName=Scope
|
||||
OsAccounts_accountScopeNameProperty_name=ScopeName
|
||||
OsAccounts_createdTimeProperty_desc=OS Account Creation Time
|
||||
OsAccounts_createdTimeProperty_displayName=Creation Time
|
||||
OsAccounts_createdTimeProperty_name=creationTime
|
||||
OsAccounts_loginNameProperty_desc=OS Account login name
|
||||
OsAccounts_loginNameProperty_displayName=Login Name
|
||||
OsAccounts_loginNameProperty_name=loginName
|
||||
PersonGroupingNode_actions_delete=Delete Person
|
||||
PersonGroupingNode_actions_rename=Rename Person...
|
||||
PersonGroupingNode_createSheet_nameProperty=Name
|
||||
|
@ -18,8 +18,6 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.datamodel;
|
||||
|
||||
import org.sleuthkit.autopsy.datamodel.OsAccounts.OsAccountNode;
|
||||
|
||||
/**
|
||||
* Visitor Pattern interface that goes over Content nodes in the data source
|
||||
* area of the tree.
|
||||
@ -53,8 +51,6 @@ interface ContentNodeVisitor<T> {
|
||||
T visit(BlackboardArtifactNode bban);
|
||||
|
||||
T visit(UnsupportedContentNode ucn);
|
||||
|
||||
T visit(OsAccountNode bban);
|
||||
|
||||
T visit(LocalFilesDataSourceNode lfdsn);
|
||||
|
||||
@ -135,11 +131,6 @@ interface ContentNodeVisitor<T> {
|
||||
return defaultVisit(ucn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visit(OsAccountNode bban) {
|
||||
return defaultVisit(bban);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visit(LocalFilesDataSourceNode lfdsn) {
|
||||
return defaultVisit(lfdsn);
|
||||
|
@ -25,18 +25,12 @@ import java.util.List;
|
||||
import javax.swing.Action;
|
||||
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.openide.util.Utilities;
|
||||
import org.sleuthkit.autopsy.actions.AddBlackboardArtifactTagAction;
|
||||
import org.sleuthkit.autopsy.actions.AddContentTagAction;
|
||||
import org.sleuthkit.autopsy.actions.DeleteBlackboardArtifactTagAction;
|
||||
import org.sleuthkit.autopsy.actions.DeleteContentTagAction;
|
||||
import org.sleuthkit.autopsy.actions.DeleteFileBlackboardArtifactTagAction;
|
||||
import org.sleuthkit.autopsy.actions.DeleteFileContentTagAction;
|
||||
import org.sleuthkit.autopsy.actions.ReplaceBlackboardArtifactTagAction;
|
||||
import org.sleuthkit.autopsy.actions.ReplaceContentTagAction;
|
||||
import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint;
|
||||
import org.sleuthkit.autopsy.datamodel.OsAccounts.OsAccountNode;
|
||||
import org.sleuthkit.autopsy.datamodel.Reports.ReportNode;
|
||||
import org.sleuthkit.autopsy.directorytree.ExportCSVAction;
|
||||
import org.sleuthkit.autopsy.directorytree.ExternalViewerAction;
|
||||
@ -44,11 +38,10 @@ import org.sleuthkit.autopsy.directorytree.ExternalViewerShortcutAction;
|
||||
import org.sleuthkit.autopsy.directorytree.ExtractAction;
|
||||
import org.sleuthkit.autopsy.directorytree.NewWindowViewAction;
|
||||
import org.sleuthkit.autopsy.directorytree.ViewContextAction;
|
||||
import org.sleuthkit.autopsy.mainui.nodes.OsAccountNode;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifactTag;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.datamodel.ContentTag;
|
||||
import org.sleuthkit.datamodel.DerivedFile;
|
||||
import org.sleuthkit.datamodel.Directory;
|
||||
import org.sleuthkit.datamodel.File;
|
||||
@ -375,18 +368,6 @@ public class DataModelActionsFactory {
|
||||
actionsList.addAll(ContextMenuExtensionPoint.getActions());
|
||||
return actionsList;
|
||||
}
|
||||
|
||||
public static List<Action> getActions(OsAccount osAccount) {
|
||||
List<Action> actionsList = new ArrayList<>();
|
||||
|
||||
OsAccountNode node = new OsAccountNode(osAccount);
|
||||
actionsList.add(null); // creates a menu separator
|
||||
actionsList.add(new NewWindowViewAction(VIEW_IN_NEW_WINDOW, node));
|
||||
actionsList.add(null);
|
||||
actionsList.add(ExportCSVAction.getInstance());
|
||||
actionsList.addAll(ContextMenuExtensionPoint.getActions());
|
||||
return actionsList;
|
||||
}
|
||||
|
||||
public static List<Action> getActions(Content content, boolean isArtifactSource) {
|
||||
if (content instanceof File) {
|
||||
|
@ -79,7 +79,7 @@ class DataSourceGroupingNode extends DisplayableItemNode {
|
||||
new Views(Case.getCurrentCaseThrows().getSleuthkitCase(), dsObjId),
|
||||
new DataArtifacts(dsObjId),
|
||||
new AnalysisResults(dsObjId),
|
||||
new OsAccounts(Case.getCurrentCaseThrows().getSleuthkitCase(), dsObjId),
|
||||
new OsAccounts(dsObjId),
|
||||
new Tags(dsObjId)
|
||||
));
|
||||
|
||||
|
@ -175,8 +175,6 @@ public interface DisplayableItemNodeVisitor<T> {
|
||||
*/
|
||||
T visit(AttachmentNode node);
|
||||
|
||||
T visit(OsAccounts.OsAccountNode node);
|
||||
|
||||
T visit(OsAccounts.OsAccountListNode node);
|
||||
|
||||
T visit(PersonNode node);
|
||||
@ -499,11 +497,6 @@ public interface DisplayableItemNodeVisitor<T> {
|
||||
return defaultVisit(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visit(OsAccounts.OsAccountNode node) {
|
||||
return defaultVisit(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visit(OsAccounts.OsAccountListNode node) {
|
||||
return defaultVisit(node);
|
||||
|
@ -18,65 +18,21 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.datamodel;
|
||||
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.logging.Level;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.swing.Action;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import javax.swing.SwingUtilities;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.openide.nodes.ChildFactory;
|
||||
import org.openide.nodes.Children;
|
||||
import org.openide.nodes.Node;
|
||||
import org.openide.nodes.Sheet;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.openide.util.WeakListeners;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.events.OsAccountsUpdatedEvent;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoDbUtil;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoException;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance;
|
||||
import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeNormalizationException;
|
||||
import org.sleuthkit.autopsy.core.UserPreferences;
|
||||
import org.sleuthkit.autopsy.corecomponents.DataResultTopComponent;
|
||||
import org.sleuthkit.autopsy.corecomponents.DataResultViewerTable;
|
||||
import org.sleuthkit.autopsy.corecomponents.SelectionResponder;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.coreutils.TimeZoneUtils;
|
||||
import static org.sleuthkit.autopsy.datamodel.AbstractContentNode.NO_DESCR;
|
||||
import static org.sleuthkit.autopsy.datamodel.AbstractContentNode.VALUE_LOADING;
|
||||
import static org.sleuthkit.autopsy.datamodel.AbstractContentNode.backgroundTasksPool;
|
||||
import org.sleuthkit.autopsy.events.AutopsyEvent;
|
||||
import org.sleuthkit.autopsy.mainui.datamodel.OsAccountsSearchParams;
|
||||
import org.sleuthkit.datamodel.Host;
|
||||
import org.sleuthkit.datamodel.OsAccount;
|
||||
import org.sleuthkit.datamodel.OsAccountRealm;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
import org.sleuthkit.datamodel.Tag;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
/**
|
||||
* Implements the OS Accounts subnode of Results in the Autopsy tree.
|
||||
*/
|
||||
public final class OsAccounts implements AutopsyVisitableItem {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(OsAccounts.class.getName());
|
||||
private static final String ICON_PATH = "org/sleuthkit/autopsy/images/os-account.png";
|
||||
private static final String OS_ACCOUNT_DATA_AVAILABLE_EVENT = "OS_ACCOUNT_DATA_AVAILABLE_EVENT";
|
||||
|
||||
private static final String LIST_NAME = Bundle.OsAccount_listNode_name();
|
||||
|
||||
private SleuthkitCase skCase;
|
||||
private final long filteringDSObjId;
|
||||
|
||||
/**
|
||||
@ -88,12 +44,11 @@ public final class OsAccounts implements AutopsyVisitableItem {
|
||||
return LIST_NAME;
|
||||
}
|
||||
|
||||
public OsAccounts(SleuthkitCase skCase) {
|
||||
this(skCase, 0);
|
||||
public OsAccounts() {
|
||||
this(0);
|
||||
}
|
||||
|
||||
public OsAccounts(SleuthkitCase skCase, long objId) {
|
||||
this.skCase = skCase;
|
||||
public OsAccounts(long objId) {
|
||||
this.filteringDSObjId = objId;
|
||||
}
|
||||
|
||||
@ -114,7 +69,7 @@ public final class OsAccounts implements AutopsyVisitableItem {
|
||||
* Construct a new OsAccountListNode.
|
||||
*/
|
||||
public OsAccountListNode() {
|
||||
super(Children.create(new OsAccountNodeFactory(), true));
|
||||
super(Children.LEAF);
|
||||
setName(LIST_NAME);
|
||||
setDisplayName(LIST_NAME);
|
||||
setIconBaseWithExtension("org/sleuthkit/autopsy/images/os-account.png");
|
||||
@ -140,497 +95,4 @@ public final class OsAccounts implements AutopsyVisitableItem {
|
||||
dataResultPanel.displayOsAccounts(new OsAccountsSearchParams(filteringDSObjId == 0 ? null : filteringDSObjId));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The child node factory that creates the OsAccountNode children for a
|
||||
* OsAccountListNode.
|
||||
*/
|
||||
private final class OsAccountNodeFactory extends ChildFactory.Detachable<OsAccount> {
|
||||
|
||||
private final PropertyChangeListener listener = new PropertyChangeListener() {
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
String eventType = evt.getPropertyName();
|
||||
if (eventType.equals(Case.Events.OS_ACCOUNTS_ADDED.toString())
|
||||
|| eventType.equals(Case.Events.OS_ACCOUNTS_DELETED.toString())) {
|
||||
refresh(true);
|
||||
} else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
|
||||
// case was closed. Remove listeners so that we don't get called with a stale case handle
|
||||
if (evt.getNewValue() == null) {
|
||||
removeNotify();
|
||||
skCase = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(listener, null);
|
||||
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
super.finalize();
|
||||
Case.removeEventTypeSubscriber(Collections.singleton(Case.Events.OS_ACCOUNTS_ADDED), weakPcl);
|
||||
Case.removeEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), weakPcl);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addNotify() {
|
||||
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.OS_ACCOUNTS_ADDED, Case.Events.OS_ACCOUNTS_DELETED), listener);
|
||||
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.CURRENT_CASE), listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean createKeys(List<OsAccount> list) {
|
||||
if (skCase != null) {
|
||||
try {
|
||||
if (filteringDSObjId == 0) {
|
||||
list.addAll(skCase.getOsAccountManager().getOsAccounts());
|
||||
} else {
|
||||
list.addAll(skCase.getOsAccountManager().getOsAccountsByDataSourceObjId(filteringDSObjId));
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Unable to retrieve list of OsAccounts for case", ex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Node createNodeForKey(OsAccount key) {
|
||||
return new OsAccountNode(key);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An OsAccount leaf Node.
|
||||
*/
|
||||
public static final class OsAccountNode extends AbstractContentNode<OsAccount> {
|
||||
|
||||
private OsAccount account;
|
||||
|
||||
@Messages({
|
||||
"OsAccounts_accountNameProperty_name=Name",
|
||||
"OsAccounts_accountNameProperty_displayName=Name",
|
||||
"OsAccounts_accountNameProperty_desc=Os Account name",
|
||||
"OsAccounts_accountRealmNameProperty_name=RealmName",
|
||||
"OsAccounts_accountRealmNameProperty_displayName=Realm Name",
|
||||
"OsAccounts_accountRealmNameProperty_desc=OS Account Realm Name",
|
||||
"OsAccounts_accountHostNameProperty_name=HostName",
|
||||
"OsAccounts_accountHostNameProperty_displayName=Host",
|
||||
"OsAccounts_accountHostNameProperty_desc=OS Account Host Name",
|
||||
"OsAccounts_accountScopeNameProperty_name=ScopeName",
|
||||
"OsAccounts_accountScopeNameProperty_displayName=Scope",
|
||||
"OsAccounts_accountScopeNameProperty_desc=OS Account Scope Name",
|
||||
"OsAccounts_createdTimeProperty_name=creationTime",
|
||||
"OsAccounts_createdTimeProperty_displayName=Creation Time",
|
||||
"OsAccounts_createdTimeProperty_desc=OS Account Creation Time",
|
||||
"OsAccounts_loginNameProperty_name=loginName",
|
||||
"OsAccounts_loginNameProperty_displayName=Login Name",
|
||||
"OsAccounts_loginNameProperty_desc=OS Account login name",
|
||||
"OsAccounts.createSheet.score.name=S",
|
||||
"OsAccounts.createSheet.score.displayName=S",
|
||||
"OsAccounts.createSheet.count.name=O",
|
||||
"OsAccounts.createSheet.count.displayName=O",
|
||||
"OsAccounts.createSheet.comment.name=C",
|
||||
"OsAccounts.createSheet.comment.displayName=C"
|
||||
})
|
||||
private final PropertyChangeListener listener = new PropertyChangeListener() {
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
if (evt.getPropertyName().equals(Case.Events.OS_ACCOUNTS_UPDATED.name())) {
|
||||
OsAccountsUpdatedEvent updateEvent = (OsAccountsUpdatedEvent) evt;
|
||||
for (OsAccount acct : updateEvent.getOsAccounts()) {
|
||||
if (acct.getId() == account.getId()) {
|
||||
account = acct;
|
||||
updateSheet();
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (evt.getPropertyName().equals(OS_ACCOUNT_DATA_AVAILABLE_EVENT)
|
||||
&& evt.getNewValue() instanceof AsynchOsAcctData
|
||||
&& ((AsynchOsAcctData) evt.getNewValue()).getOsAccountId() == account.getId()) {
|
||||
|
||||
List<NodeProperty<?>> propertiesToUpdate = new ArrayList<>();
|
||||
|
||||
AsynchOsAcctData osAcctData = (AsynchOsAcctData) evt.getNewValue();
|
||||
|
||||
List<String> realmNames = osAcctData.getOsAcctRealm().getRealmNames();
|
||||
if (!realmNames.isEmpty()) {
|
||||
String realmNamesStr = realmNames.stream()
|
||||
.map(String::trim)
|
||||
.distinct()
|
||||
.sorted((a, b) -> a.compareToIgnoreCase(b))
|
||||
.collect(Collectors.joining(", "));
|
||||
|
||||
propertiesToUpdate.add(new NodeProperty<>(
|
||||
Bundle.OsAccounts_accountRealmNameProperty_name(),
|
||||
Bundle.OsAccounts_accountRealmNameProperty_displayName(),
|
||||
Bundle.OsAccounts_accountRealmNameProperty_desc(),
|
||||
realmNamesStr));
|
||||
}
|
||||
|
||||
String scopeName = osAcctData.getOsAcctRealm().getScope().getName();
|
||||
if (StringUtils.isNotBlank(scopeName)) {
|
||||
propertiesToUpdate.add(new NodeProperty<>(
|
||||
Bundle.OsAccounts_accountScopeNameProperty_name(),
|
||||
Bundle.OsAccounts_accountScopeNameProperty_displayName(),
|
||||
Bundle.OsAccounts_accountScopeNameProperty_desc(),
|
||||
scopeName));
|
||||
}
|
||||
|
||||
List<Host> hosts = osAcctData.getHosts();
|
||||
if (!hosts.isEmpty()) {
|
||||
String hostsString = hosts.stream()
|
||||
.map(h -> h.getName().trim())
|
||||
.distinct()
|
||||
.sorted((a, b) -> a.compareToIgnoreCase(b))
|
||||
.collect(Collectors.joining(", "));
|
||||
|
||||
propertiesToUpdate.add(new NodeProperty<>(
|
||||
Bundle.OsAccounts_accountHostNameProperty_name(),
|
||||
Bundle.OsAccounts_accountHostNameProperty_displayName(),
|
||||
Bundle.OsAccounts_accountHostNameProperty_desc(),
|
||||
hostsString));
|
||||
}
|
||||
updateSheet(propertiesToUpdate.toArray(new NodeProperty<?>[propertiesToUpdate.size()]));
|
||||
} else if (evt.getPropertyName().equals(NodeSpecificEvents.SCO_AVAILABLE.toString()) && !UserPreferences.getHideSCOColumns()) {
|
||||
SCOData scoData = (SCOData) evt.getNewValue();
|
||||
if (scoData.getScoreAndDescription() != null) {
|
||||
updateSheet(new NodeProperty<>(
|
||||
Bundle.OsAccounts_createSheet_score_name(),
|
||||
Bundle.OsAccounts_createSheet_score_displayName(),
|
||||
scoData.getScoreAndDescription().getRight(),
|
||||
scoData.getScoreAndDescription().getLeft()));
|
||||
}
|
||||
if (scoData.getComment() != null) {
|
||||
updateSheet(new NodeProperty<>(
|
||||
Bundle.OsAccounts_createSheet_comment_name(),
|
||||
Bundle.OsAccounts_createSheet_comment_displayName(),
|
||||
NO_DESCR, scoData.getComment()));
|
||||
}
|
||||
if (scoData.getCountAndDescription() != null) {
|
||||
updateSheet(new NodeProperty<>(
|
||||
Bundle.OsAccounts_createSheet_count_name(),
|
||||
Bundle.OsAccounts_createSheet_count_displayName(),
|
||||
scoData.getCountAndDescription().getRight(),
|
||||
scoData.getCountAndDescription().getLeft()));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final PropertyChangeListener weakListener = WeakListeners.propertyChange(listener, null);
|
||||
|
||||
/**
|
||||
* Constructs a new OsAccountNode.
|
||||
*
|
||||
* @param account Node object.
|
||||
*/
|
||||
OsAccountNode(OsAccount account) {
|
||||
super(account);
|
||||
this.account = account;
|
||||
|
||||
setName(account.getName());
|
||||
setDisplayName(account.getName());
|
||||
setIconBaseWithExtension(ICON_PATH);
|
||||
|
||||
Case.addEventTypeSubscriber(Collections.singleton(Case.Events.OS_ACCOUNTS_UPDATED), weakListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
|
||||
return visitor.visit(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLeafTypeNode() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getItemType() {
|
||||
return getClass().getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the OsAccount associated with this node.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
OsAccount getOsAccount() {
|
||||
return account;
|
||||
}
|
||||
|
||||
/**
|
||||
* Refreshes this node's property sheet.
|
||||
*/
|
||||
void updateSheet() {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
this.setSheet(createSheet());
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Sheet createSheet() {
|
||||
Sheet sheet = super.createSheet();
|
||||
Sheet.Set propertiesSet = sheet.get(Sheet.PROPERTIES);
|
||||
if (propertiesSet == null) {
|
||||
propertiesSet = Sheet.createPropertiesSet();
|
||||
sheet.put(propertiesSet);
|
||||
}
|
||||
propertiesSet.put(new NodeProperty<>(
|
||||
Bundle.OsAccounts_accountNameProperty_name(),
|
||||
Bundle.OsAccounts_accountNameProperty_displayName(),
|
||||
Bundle.OsAccounts_accountNameProperty_desc(),
|
||||
account.getName() != null ? account.getName() : ""));
|
||||
addSCOColumns(propertiesSet);
|
||||
Optional<String> optional = account.getLoginName();
|
||||
propertiesSet.put(new NodeProperty<>(
|
||||
Bundle.OsAccounts_loginNameProperty_name(),
|
||||
Bundle.OsAccounts_loginNameProperty_displayName(),
|
||||
Bundle.OsAccounts_loginNameProperty_desc(),
|
||||
optional.isPresent() ? optional.get() : ""));
|
||||
|
||||
// Fill with empty string, fetch on background task.
|
||||
propertiesSet.put(new NodeProperty<>(
|
||||
Bundle.OsAccounts_accountHostNameProperty_name(),
|
||||
Bundle.OsAccounts_accountHostNameProperty_displayName(),
|
||||
Bundle.OsAccounts_accountHostNameProperty_desc(),
|
||||
""));
|
||||
|
||||
propertiesSet.put(new NodeProperty<>(
|
||||
Bundle.OsAccounts_accountScopeNameProperty_name(),
|
||||
Bundle.OsAccounts_accountScopeNameProperty_displayName(),
|
||||
Bundle.OsAccounts_accountScopeNameProperty_desc(),
|
||||
""));
|
||||
|
||||
propertiesSet.put(new NodeProperty<>(
|
||||
Bundle.OsAccounts_accountRealmNameProperty_name(),
|
||||
Bundle.OsAccounts_accountRealmNameProperty_displayName(),
|
||||
Bundle.OsAccounts_accountRealmNameProperty_desc(),
|
||||
""));
|
||||
|
||||
Optional<Long> creationTimeValue = account.getCreationTime();
|
||||
String timeDisplayStr
|
||||
= creationTimeValue.isPresent() ? TimeZoneUtils.getFormattedTime(creationTimeValue.get()) : "";
|
||||
|
||||
propertiesSet.put(new NodeProperty<>(
|
||||
Bundle.OsAccounts_createdTimeProperty_name(),
|
||||
Bundle.OsAccounts_createdTimeProperty_displayName(),
|
||||
Bundle.OsAccounts_createdTimeProperty_desc(),
|
||||
timeDisplayStr));
|
||||
|
||||
backgroundTasksPool.submit(new GetOsAccountRealmTask(new WeakReference<>(this), weakListener));
|
||||
return sheet;
|
||||
}
|
||||
|
||||
private void addSCOColumns(Sheet.Set sheetSet) {
|
||||
if (!UserPreferences.getHideSCOColumns()) {
|
||||
/*
|
||||
* Add S(core), C(omments), and O(ther occurences) columns to
|
||||
* the sheet and start a background task to compute the value of
|
||||
* these properties for the artifact represented by this node.
|
||||
* The task will fire a PropertyChangeEvent when the computation
|
||||
* is completed and this node's PropertyChangeListener will
|
||||
* update the sheet.
|
||||
*/
|
||||
sheetSet.put(new NodeProperty<>(
|
||||
Bundle.OsAccounts_createSheet_score_name(),
|
||||
Bundle.OsAccounts_createSheet_score_displayName(),
|
||||
VALUE_LOADING,
|
||||
""));
|
||||
sheetSet.put(new NodeProperty<>(
|
||||
Bundle.OsAccounts_createSheet_comment_name(),
|
||||
Bundle.OsAccounts_createSheet_comment_displayName(),
|
||||
VALUE_LOADING,
|
||||
""));
|
||||
if (CentralRepository.isEnabled()) {
|
||||
sheetSet.put(new NodeProperty<>(
|
||||
Bundle.OsAccounts_createSheet_count_name(),
|
||||
Bundle.OsAccounts_createSheet_count_displayName(),
|
||||
VALUE_LOADING,
|
||||
""));
|
||||
}
|
||||
backgroundTasksPool.submit(new GetSCOTask(new WeakReference<>(this), weakListener));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Action[] getActions(boolean popup) {
|
||||
List<Action> actionsList = new ArrayList<>();
|
||||
actionsList.addAll(DataModelActionsFactory.getActions(account));
|
||||
actionsList.add(null);
|
||||
actionsList.addAll(Arrays.asList(super.getActions(popup)));
|
||||
return actionsList.toArray(new Action[actionsList.size()]);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Tag> getAllTagsFromDatabase() {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(ContentNodeVisitor<T> visitor) {
|
||||
return visitor.visit(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Task for grabbing the osAccount realm.
|
||||
*/
|
||||
static class GetOsAccountRealmTask implements Runnable {
|
||||
|
||||
private final WeakReference<OsAccountNode> weakNodeRef;
|
||||
private final PropertyChangeListener listener;
|
||||
|
||||
/**
|
||||
* Construct a new task.
|
||||
*
|
||||
* @param weakContentRef
|
||||
* @param listener
|
||||
*/
|
||||
GetOsAccountRealmTask(WeakReference<OsAccountNode> weakContentRef, PropertyChangeListener listener) {
|
||||
this.weakNodeRef = weakContentRef;
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
OsAccountNode node = weakNodeRef.get();
|
||||
if (node == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
SleuthkitCase skCase = Case.getCurrentCase().getSleuthkitCase();
|
||||
OsAccount osAcct = node.getOsAccount();
|
||||
long realmId = osAcct.getRealmId();
|
||||
OsAccountRealm realm = skCase.getOsAccountRealmManager().getRealmByRealmId(realmId);
|
||||
|
||||
List<Host> hosts = skCase.getOsAccountManager().getHosts(osAcct);
|
||||
|
||||
AsynchOsAcctData evtData = new AsynchOsAcctData(osAcct.getId(), realm, hosts);
|
||||
|
||||
if (listener != null && realm != null) {
|
||||
listener.propertyChange(new PropertyChangeEvent(
|
||||
AutopsyEvent.SourceType.LOCAL.toString(),
|
||||
OS_ACCOUNT_DATA_AVAILABLE_EVENT,
|
||||
null, evtData));
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.WARNING, "Error occurred getting realm information for Os Account Node from case db, for account: " + node.getOsAccount().getName(), ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@NbBundle.Messages({
|
||||
"OsAccounts.createSheet.count.hashLookupNotRun.description=Hash lookup had not been run on this file when the column was populated",
|
||||
"# {0} - occurrenceCount",
|
||||
"OsAccounts.createSheet.count.description=There were {0} datasource(s) found with occurrences of the OS Account correlation value"})
|
||||
@Override
|
||||
|
||||
protected Pair<Long, String> getCountPropertyAndDescription(CorrelationAttributeInstance attributeInstance, String defaultDescription) {
|
||||
Long count = -1L; //The column renderer will not display negative values, negative value used when count unavailble to preserve sorting
|
||||
String description = defaultDescription;
|
||||
try {
|
||||
//don't perform the query if there is no correlation value
|
||||
if (attributeInstance != null && StringUtils.isNotBlank(attributeInstance.getCorrelationValue())) {
|
||||
count = CentralRepository.getInstance().getCountCasesWithOtherInstances(attributeInstance);
|
||||
description = Bundle.OsAccounts_createSheet_count_description(count);
|
||||
} else if (attributeInstance != null) {
|
||||
description = Bundle.OsAccounts_createSheet_count_hashLookupNotRun_description();
|
||||
}
|
||||
} catch (CentralRepoException ex) {
|
||||
logger.log(Level.SEVERE, String.format("Error getting count of data sources with %s correlation attribute %s", attributeInstance.getCorrelationType().getDisplayName(), attributeInstance.getCorrelationValue()), ex);
|
||||
} catch (CorrelationAttributeNormalizationException ex) {
|
||||
logger.log(Level.WARNING, String.format("Unable to normalize %s correlation attribute %s", attributeInstance.getCorrelationType().getDisplayName(), attributeInstance.getCorrelationValue()), ex);
|
||||
}
|
||||
return Pair.of(count, description);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns comment property for the node.
|
||||
*
|
||||
* @param tags The list of tags.
|
||||
* @param attributes The list of correlation attribute instances.
|
||||
*
|
||||
* @return Comment property for the underlying content of the node.
|
||||
*/
|
||||
@Override
|
||||
protected DataResultViewerTable.HasCommentStatus getCommentProperty(List<Tag> tags, List<CorrelationAttributeInstance> attributes) {
|
||||
/*
|
||||
* Has a tag with a comment been applied to the OsAccount or its
|
||||
* source content?
|
||||
*/
|
||||
DataResultViewerTable.HasCommentStatus status = tags.size() > 0 ? DataResultViewerTable.HasCommentStatus.TAG_NO_COMMENT : DataResultViewerTable.HasCommentStatus.NO_COMMENT;
|
||||
for (Tag tag : tags) {
|
||||
if (!StringUtils.isBlank(tag.getComment())) {
|
||||
status = DataResultViewerTable.HasCommentStatus.TAG_COMMENT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Is there a comment in the CR for anything that matches the value
|
||||
* and type of the specified attributes.
|
||||
*/
|
||||
try {
|
||||
if (CentralRepoDbUtil.commentExistsOnAttributes(attributes)) {
|
||||
if (status == DataResultViewerTable.HasCommentStatus.TAG_COMMENT) {
|
||||
status = DataResultViewerTable.HasCommentStatus.CR_AND_TAG_COMMENTS;
|
||||
} else {
|
||||
status = DataResultViewerTable.HasCommentStatus.CR_COMMENT;
|
||||
}
|
||||
}
|
||||
} catch (CentralRepoException ex) {
|
||||
logger.log(Level.SEVERE, "Attempted to Query CR for presence of comments in an OS Account node and was unable to perform query, comment column will only reflect caseDB", ex);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Data concerning an OS Account loaded asynchronously (and not at sheet
|
||||
* creation).
|
||||
*/
|
||||
private static class AsynchOsAcctData {
|
||||
|
||||
private final long osAccountId;
|
||||
private final OsAccountRealm osAcctRealm;
|
||||
private final List<Host> hosts;
|
||||
|
||||
/**
|
||||
* Main constructor.
|
||||
*
|
||||
* @param osAccountId The id of the os account.
|
||||
* @param osAcctRealm The realm of the os account.
|
||||
* @param hosts The hosts that the os account belongs to.
|
||||
*/
|
||||
AsynchOsAcctData(long osAccountId, OsAccountRealm osAcctRealm, List<Host> hosts) {
|
||||
this.osAccountId = osAccountId;
|
||||
this.osAcctRealm = osAcctRealm;
|
||||
this.hosts = hosts;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The id of the os account.
|
||||
*/
|
||||
long getOsAccountId() {
|
||||
return osAccountId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The realm of the os account.
|
||||
*/
|
||||
OsAccountRealm getOsAcctRealm() {
|
||||
return osAcctRealm;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The hosts that the os account belongs to.
|
||||
*/
|
||||
List<Host> getHosts() {
|
||||
return hosts;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -106,9 +106,13 @@ public class AnalysisSummary {
|
||||
*
|
||||
* @throws SleuthkitCaseProviderException
|
||||
* @throws TskCoreException
|
||||
*
|
||||
* @SuppressWarnings("deprecation") - we need to support already existing
|
||||
* interesting file and artifact hits.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public List<Pair<String, Long>> getInterestingItemCounts(DataSource dataSource) throws SleuthkitCaseProviderException, TskCoreException {
|
||||
return getCountsData(dataSource, TYPE_SET_NAME, ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT, ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT);
|
||||
return getCountsData(dataSource, TYPE_SET_NAME, ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT, ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT, ARTIFACT_TYPE.TSK_INTERESTING_ITEM);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -38,9 +38,15 @@ import org.sleuthkit.datamodel.TskCoreException;
|
||||
*/
|
||||
public class AnalysisSummaryGetter implements DefaultArtifactUpdateGovernor {
|
||||
|
||||
/**
|
||||
* @SuppressWarnings("deprecation") - we need to support already existing
|
||||
* interesting file and artifact hits.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
private static final Set<Integer> ARTIFACT_UPDATE_TYPE_IDS = new HashSet<>(Arrays.asList(
|
||||
ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID(),
|
||||
ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID(),
|
||||
ARTIFACT_TYPE.TSK_INTERESTING_ITEM.getTypeID(),
|
||||
ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID(),
|
||||
ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()
|
||||
));
|
||||
|
@ -38,9 +38,15 @@ import org.sleuthkit.datamodel.TskCoreException;
|
||||
*/
|
||||
public class PastCasesSummaryGetter implements DefaultArtifactUpdateGovernor {
|
||||
|
||||
/**
|
||||
* @SuppressWarnings("deprecation") - we need to support already existing
|
||||
* interesting file and artifact hits.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
private static final Set<Integer> ARTIFACT_UPDATE_TYPE_IDS = new HashSet<>(Arrays.asList(
|
||||
ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID(),
|
||||
ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID()
|
||||
ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID(),
|
||||
ARTIFACT_TYPE.TSK_INTERESTING_ITEM.getTypeID()
|
||||
));
|
||||
|
||||
private final PastCasesSummary pastSummary;
|
||||
|
@ -1340,7 +1340,11 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
||||
* DirectoryTreeTopComponent.viewArtifact, ViewContextAction
|
||||
*
|
||||
* @param art The artifact.
|
||||
*
|
||||
* @SuppressWarnings("deprecation") - we need to support already existing
|
||||
* interesting file and artifact hits.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public void viewArtifact(final BlackboardArtifact art) {
|
||||
int typeID = art.getArtifactTypeID();
|
||||
String typeName = art.getArtifactTypeName();
|
||||
@ -1367,6 +1371,8 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
|
||||
treeNode = getInterestingItemNode(typesChildren, BlackboardArtifact.Type.TSK_INTERESTING_FILE_HIT, art);
|
||||
} else if (typeID == BlackboardArtifact.Type.TSK_INTERESTING_ARTIFACT_HIT.getTypeID()) {
|
||||
treeNode = getInterestingItemNode(typesChildren, BlackboardArtifact.Type.TSK_INTERESTING_ARTIFACT_HIT, art);
|
||||
} else if (typeID == BlackboardArtifact.Type.TSK_INTERESTING_ITEM.getTypeID()) {
|
||||
treeNode = getInterestingItemNode(typesChildren, BlackboardArtifact.Type.TSK_INTERESTING_ITEM, art);
|
||||
} else if (typeID == BlackboardArtifact.Type.TSK_EMAIL_MSG.getTypeID()) {
|
||||
treeNode = getEmailNode(typesChildren, art);
|
||||
} else if (typeID == BlackboardArtifact.Type.TSK_ACCOUNT.getTypeID()) {
|
||||
|
@ -791,8 +791,8 @@ public class DiscoveryAttributes {
|
||||
CentralRepository centralRepoDb, SearchContext context) throws DiscoveryException, SearchCancellationException {
|
||||
|
||||
// Get pairs of (object ID, interesting item set name) for all files in the list of files that have
|
||||
// interesting file set hits.
|
||||
String selectQuery = createSetNameClause(results, BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID(),
|
||||
// interesting item set hits.
|
||||
String selectQuery = createSetNameClause(results, BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ITEM.getTypeID(),
|
||||
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID());
|
||||
|
||||
InterestingFileSetNamesCallback callback = new InterestingFileSetNamesCallback(results);
|
||||
|
@ -870,13 +870,19 @@ public class SearchFiltering {
|
||||
this.setNames = setNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* @SuppressWarnings("deprecation") - we need to support already
|
||||
* existing interesting file and artifact hits.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public String getWhereClause() {
|
||||
String intItemSetPart = concatenateNamesForSQL(setNames);
|
||||
|
||||
String queryStr = "(obj_id IN (SELECT obj_id from blackboard_artifacts WHERE artifact_id IN "
|
||||
+ "(SELECT artifact_id FROM blackboard_attributes WHERE artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID()
|
||||
+ " AND attribute_type_ID = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID() + " "
|
||||
+ "(SELECT artifact_id FROM blackboard_attributes WHERE (artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID()
|
||||
+ " OR artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ITEM.getTypeID()
|
||||
+ ") AND attribute_type_ID = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID() + " "
|
||||
+ "AND (" + intItemSetPart + "))))"; // NON-NLS
|
||||
|
||||
return queryStr;
|
||||
@ -946,6 +952,11 @@ public class SearchFiltering {
|
||||
this.scores = scores;
|
||||
}
|
||||
|
||||
/**
|
||||
* @SuppressWarnings("deprecation") - we need to support already
|
||||
* existing interesting file and artifact hits.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public String getWhereClause() {
|
||||
|
||||
@ -964,6 +975,7 @@ public class SearchFiltering {
|
||||
if (scores.contains(Score.INTERESTING)) {
|
||||
// Matches interesting item artifact
|
||||
intItemQueryPart = " (obj_id IN (SELECT obj_id from blackboard_artifacts WHERE artifact_type_id = "
|
||||
+ BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ITEM.getTypeID() + " OR artifact_type_id = "
|
||||
+ BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID() + ")) ";
|
||||
}
|
||||
|
||||
|
@ -720,8 +720,12 @@ final class DiscoveryDialog extends javax.swing.JDialog {
|
||||
*/
|
||||
private class ModuleChangeListener implements PropertyChangeListener {
|
||||
|
||||
/**
|
||||
* @SuppressWarnings("deprecation") - we need to support already
|
||||
* existing interesting file and artifact hits.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
@SuppressWarnings("fallthrough")
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
if (!shouldUpdate) {
|
||||
String eventType = evt.getPropertyName();
|
||||
@ -746,7 +750,8 @@ final class DiscoveryDialog extends javax.swing.JDialog {
|
||||
shouldUpdate = shouldUpdateFilters(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DESCRIPTION.getTypeID(), eventData, objectsDetected);
|
||||
} else if (eventData.getBlackboardArtifactType().getTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID()) {
|
||||
shouldUpdate = shouldUpdateFilters(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID(), eventData, hashSets);
|
||||
} else if (eventData.getBlackboardArtifactType().getTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID()
|
||||
} else if (eventData.getBlackboardArtifactType().getTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ITEM.getTypeID()
|
||||
|| eventData.getBlackboardArtifactType().getTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID()
|
||||
|| eventData.getBlackboardArtifactType().getTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID()) {
|
||||
shouldUpdate = shouldUpdateFilters(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID(), eventData, interestingItems);
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ final class InterestingItemsFilterPanel extends AbstractDiscoveryFilterPanel {
|
||||
private void setUpInterestingItemsFilter() {
|
||||
try {
|
||||
interestingItemsList.clearList();
|
||||
List<String> setNames = DiscoveryUiUtils.getSetNames(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT,
|
||||
List<String> setNames = DiscoveryUiUtils.getSetNames(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ITEM,
|
||||
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME);
|
||||
for (String name : setNames) {
|
||||
interestingItemsList.addElement(name, null, name);
|
||||
|
@ -443,7 +443,7 @@ final class AddLogicalImageTask implements Runnable {
|
||||
BlackboardArtifact artifact;
|
||||
try {
|
||||
artifact = this.blackboard.newAnalysisResult(
|
||||
BlackboardArtifact.Type.TSK_INTERESTING_FILE_HIT, fileId, dataSourceId,
|
||||
BlackboardArtifact.Type.TSK_INTERESTING_ITEM, fileId, dataSourceId,
|
||||
Score.SCORE_LIKELY_NOTABLE,
|
||||
null, ruleSetName, null,
|
||||
Arrays.asList(
|
||||
|
@ -18,9 +18,13 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.mainui.nodes;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.List;
|
||||
import org.openide.nodes.AbstractNode;
|
||||
import java.util.Optional;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import org.openide.nodes.Children;
|
||||
import org.openide.nodes.Node;
|
||||
import org.openide.nodes.Sheet;
|
||||
import org.openide.util.Lookup;
|
||||
import org.openide.util.lookup.Lookups;
|
||||
@ -30,23 +34,28 @@ import org.sleuthkit.autopsy.datamodel.DataArtifactItem;
|
||||
import org.sleuthkit.autopsy.mainui.datamodel.BlackboardArtifactTagsRowDTO;
|
||||
import org.sleuthkit.autopsy.mainui.datamodel.ColumnKey;
|
||||
import org.sleuthkit.autopsy.mainui.datamodel.SearchResultsDTO;
|
||||
import org.sleuthkit.autopsy.timeline.actions.ViewArtifactInTimelineAction;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.AnalysisResult;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifactTag;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.datamodel.DataArtifact;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
/**
|
||||
* A node representing a BlackboardArtifactTag.
|
||||
*/
|
||||
public final class BlackboardArtifactTagNode extends AbstractNode {
|
||||
public final class BlackboardArtifactTagNode extends BaseNode<SearchResultsDTO, BlackboardArtifactTagsRowDTO> {
|
||||
|
||||
private static final String ICON_PATH = "org/sleuthkit/autopsy/images/green-tag-icon-16.png"; //NON-NLS
|
||||
private final BlackboardArtifactTagsRowDTO rowData;
|
||||
private final List<ColumnKey> columns;
|
||||
|
||||
private static final Logger logger = Logger.getLogger(BlackboardArtifactTagNode.class.getName());
|
||||
|
||||
public BlackboardArtifactTagNode(SearchResultsDTO results, BlackboardArtifactTagsRowDTO rowData) {
|
||||
super(Children.LEAF, createLookup(rowData.getTag()));
|
||||
super(Children.LEAF, createLookup(rowData.getTag()), results, rowData);
|
||||
this.rowData = rowData;
|
||||
this.columns = results.getColumns();
|
||||
setDisplayName(rowData.getDisplayName());
|
||||
@ -89,77 +98,62 @@ public final class BlackboardArtifactTagNode extends AbstractNode {
|
||||
return Lookups.fixed(tag, artifactItem, artifact, sourceContent);
|
||||
}
|
||||
|
||||
// Actions are not a part of the first story, however I am deleting the original
|
||||
// node which will make finding this info a little more difficult.
|
||||
// public Action[] getActions(boolean context) {
|
||||
// List<Action> actions = new ArrayList<>();
|
||||
// BlackboardArtifact artifact = getLookup().lookup(BlackboardArtifact.class);
|
||||
// //if this artifact has a time stamp add the action to view it in the timeline
|
||||
// try {
|
||||
// if (ViewArtifactInTimelineAction.hasSupportedTimeStamp(artifact)) {
|
||||
// actions.add(new ViewArtifactInTimelineAction(artifact));
|
||||
// }
|
||||
// } catch (TskCoreException ex) {
|
||||
// LOGGER.log(Level.SEVERE, MessageFormat.format("Error getting arttribute(s) from blackboard artifact{0}.", artifact.getArtifactID()), ex); //NON-NLS
|
||||
// }
|
||||
//
|
||||
// actions.add(new ViewTaggedArtifactAction(Bundle.BlackboardArtifactTagNode_viewSourceArtifact_text(), artifact));
|
||||
// actions.add(null);
|
||||
// // if the artifact links to another file, add an action to go to that file
|
||||
// try {
|
||||
// AbstractFile c = findLinked(artifact);
|
||||
// if (c != null) {
|
||||
// actions.add(ViewFileInTimelineAction.createViewFileAction(c));
|
||||
// }
|
||||
// } catch (TskCoreException ex) {
|
||||
// LOGGER.log(Level.SEVERE, MessageFormat.format("Error getting linked file from blackboard artifact{0}.", artifact.getArtifactID()), ex); //NON-NLS
|
||||
// }
|
||||
// //if this artifact has associated content, add the action to view the content in the timeline
|
||||
// AbstractFile file = getLookup().lookup(AbstractFile.class);
|
||||
// if (null != file) {
|
||||
// actions.add(ViewFileInTimelineAction.createViewSourceFileAction(file));
|
||||
// }
|
||||
// actions.addAll(DataModelActionsFactory.getActions(tag, true));
|
||||
// actions.add(null);
|
||||
// actions.addAll(Arrays.asList(super.getActions(context)));
|
||||
// return actions.toArray(new Action[0]);
|
||||
// }
|
||||
//
|
||||
// From DataModelActionsFactory
|
||||
// public static List<Action> getActions(BlackboardArtifactTag artifactTag, boolean isArtifactSource) {
|
||||
// List<Action> actionsList = new ArrayList<>();
|
||||
// actionsList.add(new ViewContextAction((isArtifactSource ? VIEW_SOURCE_FILE_IN_DIR : VIEW_FILE_IN_DIR), artifactTag.getContent()));
|
||||
// final BlackboardArtifactTagNode tagNode = new BlackboardArtifactTagNode(artifactTag);
|
||||
// actionsList.add(null); // creates a menu separator
|
||||
// actionsList.add(new NewWindowViewAction(VIEW_IN_NEW_WINDOW, tagNode));
|
||||
// final Collection<AbstractFile> selectedFilesList
|
||||
// = new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class));
|
||||
// if (selectedFilesList.size() == 1) {
|
||||
// actionsList.add(new ExternalViewerAction(OPEN_IN_EXTERNAL_VIEWER, tagNode));
|
||||
// } else {
|
||||
// actionsList.add(ExternalViewerShortcutAction.getInstance());
|
||||
// }
|
||||
// actionsList.add(null); // creates a menu separator
|
||||
// actionsList.add(ExtractAction.getInstance());
|
||||
// actionsList.add(ExportCSVAction.getInstance());
|
||||
// actionsList.add(null); // creates a menu separator
|
||||
// actionsList.add(AddContentTagAction.getInstance());
|
||||
// if (isArtifactSource) {
|
||||
// actionsList.add(AddBlackboardArtifactTagAction.getInstance());
|
||||
// }
|
||||
// if (selectedFilesList.size() == 1) {
|
||||
// actionsList.add(DeleteFileContentTagAction.getInstance());
|
||||
// }
|
||||
// if (isArtifactSource) {
|
||||
// final Collection<BlackboardArtifact> selectedArtifactsList
|
||||
// = new HashSet<>(Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class));
|
||||
// if (selectedArtifactsList.size() == 1) {
|
||||
// actionsList.add(DeleteFileBlackboardArtifactTagAction.getInstance());
|
||||
// }
|
||||
// }
|
||||
// actionsList.add(DeleteBlackboardArtifactTagAction.getInstance());
|
||||
// actionsList.add(ReplaceBlackboardArtifactTagAction.getInstance());
|
||||
// actionsList.addAll(ContextMenuExtensionPoint.getActions());
|
||||
// return actionsList;
|
||||
// }
|
||||
@Override
|
||||
public Optional<Content> getSourceContent() {
|
||||
return Optional.ofNullable(rowData.getTag().getContent());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<BlackboardArtifact> getArtifact() {
|
||||
return Optional.ofNullable(rowData.getTag().getArtifact());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsViewInTimeline() {
|
||||
BlackboardArtifact artifact = rowData.getTag().getArtifact();
|
||||
if (artifact != null) {
|
||||
try {
|
||||
return ViewArtifactInTimelineAction.hasSupportedTimeStamp(artifact);
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, MessageFormat.format("Error getting arttribute(s) from blackboard artifact{0}.", artifact.getArtifactID()), ex); //NON-NLS
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsSourceContentViewerActions() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Node> getNewWindowActionNode() {
|
||||
return Optional.of(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Node> getExternalViewerActionNode() {
|
||||
return Optional.of(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsExtractActions() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsArtifactTagAction() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsReplaceTagAction() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsContentTagAction() {
|
||||
return rowData.getTag().getContent() instanceof AbstractFile;
|
||||
}
|
||||
}
|
||||
|
@ -19,20 +19,23 @@
|
||||
package org.sleuthkit.autopsy.mainui.nodes;
|
||||
|
||||
import java.util.List;
|
||||
import org.openide.nodes.AbstractNode;
|
||||
import java.util.Optional;
|
||||
import org.openide.nodes.Children;
|
||||
import org.openide.nodes.Node;
|
||||
import org.openide.nodes.Sheet;
|
||||
import org.openide.util.Lookup;
|
||||
import org.openide.util.lookup.Lookups;
|
||||
import org.sleuthkit.autopsy.mainui.datamodel.ColumnKey;
|
||||
import org.sleuthkit.autopsy.mainui.datamodel.ContentTagsRowDTO;
|
||||
import org.sleuthkit.autopsy.mainui.datamodel.SearchResultsDTO;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.datamodel.ContentTag;
|
||||
|
||||
/**
|
||||
* A node representing a ContentTag.
|
||||
*/
|
||||
public final class ContentTagNode extends AbstractNode {
|
||||
public final class ContentTagNode extends BaseNode<SearchResultsDTO, ContentTagsRowDTO> {
|
||||
|
||||
private static final String CONTENT_ICON_PATH = "org/sleuthkit/autopsy/images/blue-tag-icon-16.png"; //NON-NLS
|
||||
|
||||
@ -45,8 +48,8 @@ public final class ContentTagNode extends AbstractNode {
|
||||
* @param results Search results.
|
||||
* @param rowData Row data.
|
||||
*/
|
||||
public ContentTagNode(SearchResultsDTO results, ContentTagsRowDTO rowData) {
|
||||
super(Children.LEAF, createLookup(rowData.getTag()));
|
||||
public ContentTagNode(SearchResultsDTO results, ContentTagsRowDTO rowData) {
|
||||
super(Children.LEAF, createLookup(rowData.getTag()), results, rowData);
|
||||
this.rowData = rowData;
|
||||
this.columns = results.getColumns();
|
||||
setDisplayName(rowData.getDisplayName());
|
||||
@ -70,57 +73,63 @@ public ContentTagNode(SearchResultsDTO results, ContentTagsRowDTO rowData) {
|
||||
return Lookups.fixed(tag, tag.getContent());
|
||||
}
|
||||
|
||||
// Not adding support for actions at this time, but am deleting the original node
|
||||
// classes in dataModel. This is the action code from the original ContentTagNode
|
||||
// public Action[] getActions(boolean context) {
|
||||
// List<Action> actions = new ArrayList<>();
|
||||
//
|
||||
//
|
||||
// AbstractFile file = getLookup().lookup(AbstractFile.class);
|
||||
// if (file != null) {
|
||||
// actions.add(ViewFileInTimelineAction.createViewFileAction(file));
|
||||
// }
|
||||
//
|
||||
// actions.addAll(DataModelActionsFactory.getActions(tag, false));
|
||||
// actions.add(null);
|
||||
// actions.addAll(Arrays.asList(super.getActions(context)));
|
||||
// return actions.toArray(new Action[actions.size()]);
|
||||
// }
|
||||
// From DataModelActionsFactory
|
||||
// public static List<Action> getActions(ContentTag contentTag, boolean isArtifactSource) {
|
||||
// List<Action> actionsList = new ArrayList<>();
|
||||
// actionsList.add(new ViewContextAction((isArtifactSource ? VIEW_SOURCE_FILE_IN_DIR : VIEW_FILE_IN_DIR), contentTag.getContent()));
|
||||
// final ContentTagNode tagNode = new ContentTagNode(contentTag);
|
||||
// actionsList.add(null); // creates a menu separator
|
||||
// actionsList.add(new NewWindowViewAction(VIEW_IN_NEW_WINDOW, tagNode));
|
||||
// final Collection<AbstractFile> selectedFilesList
|
||||
// = new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class));
|
||||
// if (selectedFilesList.size() == 1) {
|
||||
// actionsList.add(new ExternalViewerAction(OPEN_IN_EXTERNAL_VIEWER, tagNode));
|
||||
// } else {
|
||||
// actionsList.add(ExternalViewerShortcutAction.getInstance());
|
||||
// }
|
||||
// actionsList.add(null); // creates a menu separator
|
||||
// actionsList.add(ExtractAction.getInstance());
|
||||
// actionsList.add(ExportCSVAction.getInstance());
|
||||
// actionsList.add(null); // creates a menu separator
|
||||
// actionsList.add(AddContentTagAction.getInstance());
|
||||
// if (isArtifactSource) {
|
||||
// actionsList.add(AddBlackboardArtifactTagAction.getInstance());
|
||||
// }
|
||||
// if (selectedFilesList.size() == 1) {
|
||||
// actionsList.add(DeleteFileContentTagAction.getInstance());
|
||||
// }
|
||||
// if (isArtifactSource) {
|
||||
// final Collection<BlackboardArtifact> selectedArtifactsList
|
||||
// = new HashSet<>(Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class));
|
||||
// if (selectedArtifactsList.size() == 1) {
|
||||
// actionsList.add(DeleteFileBlackboardArtifactTagAction.getInstance());
|
||||
// }
|
||||
// }
|
||||
// actionsList.add(DeleteContentTagAction.getInstance());
|
||||
// actionsList.add(ReplaceContentTagAction.getInstance());
|
||||
// actionsList.addAll(ContextMenuExtensionPoint.getActions());
|
||||
// return actionsList;
|
||||
// }
|
||||
@Override
|
||||
public Optional<AbstractFile> getFileForViewInTimelineAction() {
|
||||
Content tagContent = rowData.getTag().getContent();
|
||||
if (tagContent instanceof AbstractFile) {
|
||||
return Optional.of((AbstractFile) tagContent);
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsViewInTimeline() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsAssociatedFileActions() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<AbstractFile> getLinkedFile() {
|
||||
Content content = rowData.getTag().getContent();
|
||||
if (content instanceof AbstractFile) {
|
||||
return Optional.of((AbstractFile) content);
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsSourceContentViewerActions() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Node> getNewWindowActionNode() {
|
||||
return Optional.of(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Node> getExternalViewerActionNode() {
|
||||
return Optional.of(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsExtractActions() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsContentTagAction() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsReplaceTagAction() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -183,6 +183,10 @@ public interface ActionContext {
|
||||
default boolean supportsArtifactTagAction() {
|
||||
return false;
|
||||
}
|
||||
|
||||
default boolean supportsReplaceTagAction() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the file to be extracted.
|
||||
|
@ -37,8 +37,12 @@ import org.openide.util.Utilities;
|
||||
import org.openide.util.actions.SystemAction;
|
||||
import org.sleuthkit.autopsy.actions.AddBlackboardArtifactTagAction;
|
||||
import org.sleuthkit.autopsy.actions.AddContentTagAction;
|
||||
import org.sleuthkit.autopsy.actions.DeleteBlackboardArtifactTagAction;
|
||||
import org.sleuthkit.autopsy.actions.DeleteContentTagAction;
|
||||
import org.sleuthkit.autopsy.actions.DeleteFileBlackboardArtifactTagAction;
|
||||
import org.sleuthkit.autopsy.actions.DeleteFileContentTagAction;
|
||||
import org.sleuthkit.autopsy.actions.ReplaceBlackboardArtifactTagAction;
|
||||
import org.sleuthkit.autopsy.actions.ReplaceContentTagAction;
|
||||
import org.sleuthkit.autopsy.actions.ViewArtifactAction;
|
||||
import org.sleuthkit.autopsy.actions.ViewOsAccountAction;
|
||||
import org.sleuthkit.autopsy.casemodule.DeleteDataSourceAction;
|
||||
@ -106,7 +110,10 @@ public final class ActionsFactory {
|
||||
|
||||
group = new ActionGroup();
|
||||
if (actionContext.supportsAssociatedFileActions()) {
|
||||
group.addAll(getAssociatedFileActions(actionContext).get());
|
||||
Optional<ActionGroup> subGroup = getAssociatedFileActions(actionContext);
|
||||
if(subGroup.isPresent()) {
|
||||
group.addAll(subGroup.get());
|
||||
}
|
||||
}
|
||||
|
||||
if (actionContext.getSourceContent().isPresent()) {
|
||||
@ -315,7 +322,12 @@ public final class ActionsFactory {
|
||||
if (context.supportsArtifactTagAction() && selectedArtifactCount == 1) {
|
||||
actionGroup.add(DeleteFileBlackboardArtifactTagAction.getInstance());
|
||||
}
|
||||
|
||||
|
||||
if((context.supportsArtifactTagAction() || context.supportsContentTagAction()) && context.supportsReplaceTagAction()) {
|
||||
actionGroup.add(DeleteContentTagAction.getInstance());
|
||||
actionGroup.add(ReplaceContentTagAction.getInstance());
|
||||
}
|
||||
|
||||
return actionGroup;
|
||||
}
|
||||
|
||||
|
@ -69,7 +69,7 @@ import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.Blackboard;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT;
|
||||
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ITEM;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT;
|
||||
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DESCRIPTION;
|
||||
@ -327,10 +327,10 @@ class SevenZipExtractor {
|
||||
TSK_COMMENT, MODULE_NAME,
|
||||
details));
|
||||
|
||||
if (!blackboard.artifactExists(archiveFile, TSK_INTERESTING_FILE_HIT, attributes)) {
|
||||
if (!blackboard.artifactExists(archiveFile, TSK_INTERESTING_ITEM, attributes)) {
|
||||
|
||||
BlackboardArtifact artifact = rootArchive.getArchiveFile().newAnalysisResult(
|
||||
BlackboardArtifact.Type.TSK_INTERESTING_FILE_HIT, Score.SCORE_LIKELY_NOTABLE,
|
||||
BlackboardArtifact.Type.TSK_INTERESTING_ITEM, Score.SCORE_LIKELY_NOTABLE,
|
||||
null, setName, null,
|
||||
attributes)
|
||||
.getAnalysisResult();
|
||||
|
@ -36,7 +36,7 @@ import org.sleuthkit.autopsy.modules.filetypeid.CustomFileTypesManager.CustomFil
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.Blackboard;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT;
|
||||
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ITEM;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CATEGORY;
|
||||
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME;
|
||||
@ -194,9 +194,9 @@ public class FileTypeIdIngestModule implements FileIngestModule {
|
||||
|
||||
Blackboard tskBlackboard = currentCase.getSleuthkitCase().getBlackboard();
|
||||
// Create artifact if it doesn't already exist.
|
||||
if (!tskBlackboard.artifactExists(file, TSK_INTERESTING_FILE_HIT, attributes)) {
|
||||
if (!tskBlackboard.artifactExists(file, TSK_INTERESTING_ITEM, attributes)) {
|
||||
BlackboardArtifact artifact = file.newAnalysisResult(
|
||||
BlackboardArtifact.Type.TSK_INTERESTING_FILE_HIT, Score.SCORE_LIKELY_NOTABLE,
|
||||
BlackboardArtifact.Type.TSK_INTERESTING_ITEM, Score.SCORE_LIKELY_NOTABLE,
|
||||
null, fileType.getInterestingFilesSetName(), null,
|
||||
attributes)
|
||||
.getAnalysisResult();
|
||||
@ -208,12 +208,12 @@ public class FileTypeIdIngestModule implements FileIngestModule {
|
||||
*/
|
||||
tskBlackboard.postArtifact(artifact, FileTypeIdModuleFactory.getModuleName(), jobId);
|
||||
} catch (Blackboard.BlackboardException ex) {
|
||||
logger.log(Level.SEVERE, String.format("Unable to index TSK_INTERESTING_FILE_HIT blackboard artifact %d (file obj_id=%d)", artifact.getArtifactID(), file.getId()), ex); //NON-NLS
|
||||
logger.log(Level.SEVERE, String.format("Unable to index TSK_INTERESTING_ITEM blackboard artifact %d (file obj_id=%d)", artifact.getArtifactID(), file.getId()), ex); //NON-NLS
|
||||
}
|
||||
}
|
||||
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, String.format("Unable to create TSK_INTERESTING_FILE_HIT artifact for file (obj_id=%d)", file.getId()), ex); //NON-NLS
|
||||
logger.log(Level.SEVERE, String.format("Unable to create TSK_INTERESTING_ITEM artifact for file (obj_id=%d)", file.getId()), ex); //NON-NLS
|
||||
} catch (NoCurrentCaseException ex) {
|
||||
logger.log(Level.SEVERE, "Exception while getting open case.", ex); //NON-NLS
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ import org.sleuthkit.autopsy.ingest.IngestServices;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.Blackboard;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT;
|
||||
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ITEM;
|
||||
import org.sleuthkit.datamodel.BlackboardAttribute;
|
||||
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CATEGORY;
|
||||
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME;
|
||||
@ -142,9 +142,9 @@ final class FilesIdentifierIngestModule implements FileIngestModule {
|
||||
);
|
||||
|
||||
// Create artifact if it doesn't already exist.
|
||||
if (!blackboard.artifactExists(file, TSK_INTERESTING_FILE_HIT, attributes)) {
|
||||
if (!blackboard.artifactExists(file, TSK_INTERESTING_ITEM, attributes)) {
|
||||
BlackboardArtifact artifact = file.newAnalysisResult(
|
||||
BlackboardArtifact.Type.TSK_INTERESTING_FILE_HIT, Score.SCORE_LIKELY_NOTABLE,
|
||||
BlackboardArtifact.Type.TSK_INTERESTING_ITEM, Score.SCORE_LIKELY_NOTABLE,
|
||||
null, filesSet.getName(), null,
|
||||
attributes)
|
||||
.getAnalysisResult();
|
||||
|
@ -57,11 +57,11 @@ class PortableCaseInterestingItemsListPanel extends javax.swing.JPanel {
|
||||
private final SetNamesListModel setNamesListModel = new SetNamesListModel();
|
||||
private final SetNamesListCellRenderer setNamesRenderer = new SetNamesListCellRenderer();
|
||||
private Map<String, Long> setCounts;
|
||||
|
||||
|
||||
private final ReportWizardPortableCaseOptionsPanel wizPanel;
|
||||
private final PortableCaseReportModuleSettings settings;
|
||||
private final boolean useCaseSpecificData;
|
||||
|
||||
|
||||
/**
|
||||
* Creates new form PortableCaseListPanel
|
||||
*/
|
||||
@ -71,14 +71,14 @@ class PortableCaseInterestingItemsListPanel extends javax.swing.JPanel {
|
||||
this.settings = options;
|
||||
initComponents();
|
||||
customizeComponents();
|
||||
|
||||
|
||||
// update tag selection
|
||||
jAllSetsCheckBox.setSelected(settings.areAllSetsSelected());
|
||||
setNamesListBox.setEnabled(!jAllSetsCheckBox.isSelected());
|
||||
selectButton.setEnabled(!jAllSetsCheckBox.isSelected());
|
||||
deselectButton.setEnabled(!jAllSetsCheckBox.isSelected());
|
||||
selectAllSets(jAllSetsCheckBox.isSelected());
|
||||
|
||||
|
||||
this.jAllSetsCheckBox.addItemListener(new ItemListener() {
|
||||
@Override
|
||||
public void itemStateChanged(ItemEvent e) {
|
||||
@ -93,14 +93,18 @@ class PortableCaseInterestingItemsListPanel extends javax.swing.JPanel {
|
||||
@NbBundle.Messages({
|
||||
"PortableCaseInterestingItemsListPanel.error.errorTitle=Error getting intesting item set names for case",
|
||||
"PortableCaseInterestingItemsListPanel.error.noOpenCase=There is no case open",
|
||||
"PortableCaseInterestingItemsListPanel.error.errorLoadingTags=Error loading interesting item set names",
|
||||
})
|
||||
"PortableCaseInterestingItemsListPanel.error.errorLoadingTags=Error loading interesting item set names",})
|
||||
/**
|
||||
* @SuppressWarnings("deprecation") - we need to support already existing
|
||||
* interesting file and artifact hits.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
private void customizeComponents() {
|
||||
|
||||
|
||||
// Get the set names in use for the current case.
|
||||
setNames = new ArrayList<>();
|
||||
setCounts = new HashMap<>();
|
||||
|
||||
|
||||
// only try to load tag names if we are displaying case specific data, otherwise
|
||||
// we will be displaying case specific data in command line wizard if there is
|
||||
// a case open in the background
|
||||
@ -108,6 +112,7 @@ class PortableCaseInterestingItemsListPanel extends javax.swing.JPanel {
|
||||
try {
|
||||
// Get all SET_NAMEs from interesting item artifacts
|
||||
String innerSelect = "SELECT (value_text) AS set_name FROM blackboard_attributes WHERE (artifact_type_id = '"
|
||||
+ BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ITEM.getTypeID() + "' OR artifact_type_id = '"
|
||||
+ BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID() + "' OR artifact_type_id = '"
|
||||
+ BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID() + "') AND attribute_type_id = '"
|
||||
+ BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID() + "'"; // NON-NLS
|
||||
@ -157,15 +162,16 @@ class PortableCaseInterestingItemsListPanel extends javax.swing.JPanel {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Save the current selections and enabled/disable the finish button as needed.
|
||||
* Save the current selections and enabled/disable the finish button as
|
||||
* needed.
|
||||
*/
|
||||
private void updateSetNameList() {
|
||||
settings.updateSetNames(getSelectedSetNames());
|
||||
settings.setAllSetsSelected(jAllSetsCheckBox.isSelected());
|
||||
wizPanel.setFinish(settings.isValid());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This class is a list model for the set names JList component.
|
||||
@ -194,9 +200,11 @@ class PortableCaseInterestingItemsListPanel extends javax.swing.JPanel {
|
||||
}
|
||||
|
||||
/**
|
||||
* This class renders the items in the set names JList component as JCheckbox components.
|
||||
* This class renders the items in the set names JList component as
|
||||
* JCheckbox components.
|
||||
*/
|
||||
private class SetNamesListCellRenderer extends JCheckBox implements ListCellRenderer<String> {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Override
|
||||
@ -214,10 +222,11 @@ class PortableCaseInterestingItemsListPanel extends javax.swing.JPanel {
|
||||
}
|
||||
return new JLabel();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the subset of the interesting item set names in use selected by the user.
|
||||
* Gets the subset of the interesting item set names in use selected by the
|
||||
* user.
|
||||
*
|
||||
* @return A list, possibly empty, of String data transfer objects (DTOs).
|
||||
*/
|
||||
@ -342,7 +351,7 @@ class PortableCaseInterestingItemsListPanel extends javax.swing.JPanel {
|
||||
setNameSelections.put(setName, state);
|
||||
}
|
||||
updateSetNameList();
|
||||
setNamesListBox.repaint();
|
||||
setNamesListBox.repaint();
|
||||
}
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
|
@ -1135,7 +1135,11 @@ class TableReportGenerator {
|
||||
* not defined in artifact
|
||||
*
|
||||
* @throws TskCoreException
|
||||
*
|
||||
* @SuppressWarnings("deprecation") - we need to support already
|
||||
* existing interesting file and artifact hits.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
private List<String> getOrderedRowDataAsStrings() throws TskCoreException {
|
||||
|
||||
List<String> orderedRowData = new ArrayList<>();
|
||||
@ -1160,8 +1164,9 @@ class TableReportGenerator {
|
||||
}
|
||||
orderedRowData.add(makeCommaSeparatedList(getTags()));
|
||||
|
||||
} else if (BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID() == getArtifact().getArtifactTypeID()) {
|
||||
String[] attributeDataArray = new String[5];
|
||||
} else if (BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID() == getArtifact().getArtifactTypeID()
|
||||
|| BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ITEM.getTypeID() == getArtifact().getArtifactTypeID()) {
|
||||
String[] attributeDataArray = new String[7];
|
||||
// Array is used so that order of the attributes is maintained.
|
||||
for (BlackboardAttribute attr : attributes) {
|
||||
if (attr.getAttributeType().equals(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME))) {
|
||||
@ -1172,6 +1177,10 @@ class TableReportGenerator {
|
||||
attributeDataArray[3] = attr.getDisplayString();
|
||||
} else if (attr.getAttributeType().equals(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DESCRIPTION))) {
|
||||
attributeDataArray[4] = attr.getDisplayString();
|
||||
} else if (attr.getAttributeType().equals(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT))) {
|
||||
attributeDataArray[5] = attr.getDisplayString();
|
||||
} else if (attr.getAttributeType().equals(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME))) {
|
||||
attributeDataArray[6] = attr.getDisplayString();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1707,6 +1716,28 @@ class TableReportGenerator {
|
||||
columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.program"),
|
||||
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME)));
|
||||
|
||||
} else if (BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ITEM.getTypeID() == artifactTypeId) {
|
||||
columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tskSetName"),
|
||||
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME)));
|
||||
|
||||
columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.associatedArtifact"),
|
||||
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT)));
|
||||
|
||||
columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.program"),
|
||||
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME)));
|
||||
|
||||
columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tskInterestingFilesCategory"),
|
||||
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CATEGORY)));
|
||||
|
||||
columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.tskPath"),
|
||||
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH)));
|
||||
|
||||
columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.comment"),
|
||||
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT)));
|
||||
|
||||
columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.description"),
|
||||
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DESCRIPTION)));
|
||||
|
||||
} else if (BlackboardArtifact.ARTIFACT_TYPE.TSK_PROG_RUN.getTypeID() == artifactTypeId) {
|
||||
columns.add(new AttributeColumn(NbBundle.getMessage(this.getClass(), "ReportGenerator.artTableColHdr.program"),
|
||||
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME)));
|
||||
|
@ -213,7 +213,7 @@ public class HTMLReport implements TableReportModule {
|
||||
* Copies a suitable icon for the given data type in the output directory
|
||||
* and returns the icon file name to use for the given data type.
|
||||
*/
|
||||
@SuppressWarnings( "deprecation" )
|
||||
@SuppressWarnings("deprecation")
|
||||
private String useDataTypeIcon(String dataType) {
|
||||
String iconFilePath;
|
||||
String iconFileName;
|
||||
@ -326,9 +326,10 @@ public class HTMLReport implements TableReportModule {
|
||||
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/images/mismatch-16.png"); //NON-NLS
|
||||
break;
|
||||
case TSK_INTERESTING_ARTIFACT_HIT:
|
||||
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/images/interesting_item.png"); //NON-NLS
|
||||
break;
|
||||
//fall through deprecated type to TSK_INTERESTING_ITEM
|
||||
case TSK_INTERESTING_FILE_HIT:
|
||||
//fall through deprecated type to TSK_INTERESTING_ITEM
|
||||
case TSK_INTERESTING_ITEM:
|
||||
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/images/interesting_item.png"); //NON-NLS
|
||||
break;
|
||||
case TSK_PROG_RUN:
|
||||
@ -339,25 +340,25 @@ public class HTMLReport implements TableReportModule {
|
||||
break;
|
||||
case TSK_OS_ACCOUNT:
|
||||
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/images/os-account.png"); //NON-NLS
|
||||
break;
|
||||
break;
|
||||
case TSK_OBJECT_DETECTED:
|
||||
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/images/objects.png"); //NON-NLS
|
||||
break;
|
||||
break;
|
||||
case TSK_WEB_FORM_AUTOFILL:
|
||||
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/images/web-form.png"); //NON-NLS
|
||||
break;
|
||||
break;
|
||||
case TSK_WEB_CACHE:
|
||||
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/images/cache.png"); //NON-NLS
|
||||
break;
|
||||
break;
|
||||
case TSK_USER_CONTENT_SUSPECTED:
|
||||
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/images/user-content.png"); //NON-NLS
|
||||
break;
|
||||
break;
|
||||
case TSK_METADATA:
|
||||
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/images/metadata.png"); //NON-NLS
|
||||
break;
|
||||
break;
|
||||
case TSK_CLIPBOARD_CONTENT:
|
||||
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/images/clipboard.png"); //NON-NLS
|
||||
break;
|
||||
break;
|
||||
case TSK_ACCOUNT:
|
||||
in = getClass().getResourceAsStream("/org/sleuthkit/autopsy/report/images/accounts.png"); //NON-NLS
|
||||
break;
|
||||
@ -506,7 +507,7 @@ public class HTMLReport implements TableReportModule {
|
||||
* to this page, and setup the web page header. Note: This method is a
|
||||
* temporary workaround to avoid modifying the TableReportModule interface.
|
||||
*
|
||||
* @param name Name of the data type
|
||||
* @param name Name of the data type
|
||||
* @param description Comment on the data type, may be the empty string
|
||||
*/
|
||||
@Override
|
||||
@ -738,9 +739,9 @@ public class HTMLReport implements TableReportModule {
|
||||
/**
|
||||
* Add a row to the current table.
|
||||
*
|
||||
* @param row values for each cell in the row
|
||||
* @param row values for each cell in the row
|
||||
* @param escapeText whether or not the text of the row should be escaped,
|
||||
* true for escaped, false for not escaped
|
||||
* true for escaped, false for not escaped
|
||||
*/
|
||||
private void addRow(List<String> row, boolean escapeText) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
@ -763,9 +764,9 @@ public class HTMLReport implements TableReportModule {
|
||||
|
||||
/**
|
||||
* Saves a local copy of a tagged file and adds a row with a hyper link to
|
||||
* the file.
|
||||
* the file.
|
||||
*
|
||||
* @param row Values for each data cell in the row
|
||||
* @param row Values for each data cell in the row
|
||||
* @param contentTag The tag
|
||||
*/
|
||||
public void addRowWithTaggedContentHyperlink(List<String> row, ContentTag contentTag) {
|
||||
@ -825,6 +826,7 @@ public class HTMLReport implements TableReportModule {
|
||||
* Finds all associated image tags.
|
||||
*
|
||||
* @param contentTags
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private List<ImageTagRegion> getTaggedRegions(List<ContentTag> contentTags) {
|
||||
@ -1029,9 +1031,9 @@ public class HTMLReport implements TableReportModule {
|
||||
/**
|
||||
* Save a local copy of the given file in the reports folder.
|
||||
*
|
||||
* @param file File to save
|
||||
* @param file File to save
|
||||
* @param dirName Custom top-level folder to use to store the files in (tag
|
||||
* name, etc.)
|
||||
* name, etc.)
|
||||
*
|
||||
* @return Path to where file was stored (relative to root of HTML folder)
|
||||
*/
|
||||
@ -1574,7 +1576,7 @@ public class HTMLReport implements TableReportModule {
|
||||
* @param file The file from which to create the thumbnail.
|
||||
*
|
||||
* @return The path to the thumbnail file, or null if a thumbnail couldn't
|
||||
* be created.
|
||||
* be created.
|
||||
*/
|
||||
private String prepareThumbnail(AbstractFile file) {
|
||||
BufferedImage bufferedThumb = ImageUtils.getThumbnail(file, ImageUtils.ICON_SIZE_MEDIUM);
|
||||
|
@ -111,7 +111,7 @@ public class PortableCaseReportModule implements ReportModule {
|
||||
// These are the types for the exported file subfolders
|
||||
private static final List<FileTypeCategory> FILE_TYPE_CATEGORIES = Arrays.asList(FileTypeCategory.AUDIO, FileTypeCategory.DOCUMENTS,
|
||||
FileTypeCategory.EXECUTABLE, FileTypeCategory.IMAGE, FileTypeCategory.VIDEO);
|
||||
|
||||
|
||||
// These are attribute types that have special handling and should not be copied
|
||||
// into the new artifact directly.
|
||||
private static final List<Integer> SPECIALLY_HANDLED_ATTRS = Arrays.asList(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT.getTypeID(),
|
||||
@ -140,13 +140,13 @@ 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
|
||||
private final Map<Long, OsAccount> oldOsAccountIdToNewOsAccount = new HashMap<>();
|
||||
|
||||
// Map of old OS account realm id to new OS account ream id
|
||||
private final Map<Long, OsAccountRealm> oldRealmIdToNewRealm = new HashMap<>();
|
||||
|
||||
|
||||
// Map of old OS account realm id to new OS account ream id
|
||||
private final Map<Long, OsAccountRealm> oldRealmIdToNewRealm = new HashMap<>();
|
||||
|
||||
// Map of the old host id to the new host
|
||||
private final Map<Long, Host> oldHostIdToNewHost = new HashMap<>();
|
||||
|
||||
@ -242,7 +242,11 @@ public class PortableCaseReportModule implements ReportModule {
|
||||
"PortableCaseReportModule.generateReport.compressingCase=Compressing case...",
|
||||
"PortableCaseReportModule_generateReport_copyingAutopsy=Copying application..."
|
||||
})
|
||||
|
||||
/**
|
||||
* @SuppressWarnings("deprecation") - we need to support already existing
|
||||
* interesting file and artifact hits.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public void generateReport(String reportPath, PortableCaseReportModuleSettings options, ReportProgressPanel progressPanel) {
|
||||
this.settings = options;
|
||||
progressPanel.setIndeterminate(true);
|
||||
@ -444,6 +448,24 @@ public class PortableCaseReportModule implements ReportModule {
|
||||
handleError("Error copying interesting results", Bundle.PortableCaseReportModule_generateReport_errorCopyingInterestingResults(), ex, progressPanel); // NON-NLS
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
List<AnalysisResult> interestingResults = currentCase.getSleuthkitCase().getBlackboard().getAnalysisResultsByType(BlackboardArtifact.Type.TSK_INTERESTING_ITEM.getTypeID());
|
||||
for (AnalysisResult art : interestingResults) {
|
||||
// Check for cancellation
|
||||
if (progressPanel.getStatus() == ReportProgressPanel.ReportStatus.CANCELED) {
|
||||
handleCancellation(progressPanel);
|
||||
return;
|
||||
}
|
||||
BlackboardAttribute setAttr = art.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME));
|
||||
if (setNames.contains(setAttr.getValueString())) {
|
||||
copyContentToPortableCase(art, progressPanel);
|
||||
}
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
handleError("Error copying interesting items", Bundle.PortableCaseReportModule_generateReport_errorCopyingInterestingResults(), ex, progressPanel); // NON-NLS
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for cancellation
|
||||
@ -469,7 +491,7 @@ public class PortableCaseReportModule implements ReportModule {
|
||||
if (options.shouldCompress()) {
|
||||
progressPanel.updateStatusLabel(Bundle.PortableCaseReportModule_generateReport_compressingCase());
|
||||
|
||||
if(!compressCase(progressPanel, options.includeApplication() ? outputDir.getAbsolutePath() : caseFolder.getAbsolutePath())){
|
||||
if (!compressCase(progressPanel, options.includeApplication() ? outputDir.getAbsolutePath() : caseFolder.getAbsolutePath())) {
|
||||
// Errors have been handled already
|
||||
return;
|
||||
}
|
||||
@ -586,7 +608,11 @@ public class PortableCaseReportModule implements ReportModule {
|
||||
* Load all interesting BlackboardArtifacts that belong to the selected
|
||||
* SET_NAME. This operation would be duplicated for every data source, since
|
||||
* the Sleuthkit API does not have a notion of searching by data source id.
|
||||
*
|
||||
* @SuppressWarnings("deprecation") - we need to support already existing
|
||||
* interesting file and artifact hits.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
private Multimap<Long, BlackboardArtifact> getInterestingArtifactsBySetName(SleuthkitCase skCase, List<String> setNames) throws TskCoreException {
|
||||
Multimap<Long, BlackboardArtifact> artifactsWithSetName = ArrayListMultimap.create();
|
||||
if (!setNames.isEmpty()) {
|
||||
@ -594,6 +620,8 @@ public class PortableCaseReportModule implements ReportModule {
|
||||
BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT);
|
||||
allArtifacts.addAll(skCase.getBlackboardArtifacts(
|
||||
BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT));
|
||||
allArtifacts.addAll(skCase.getBlackboardArtifacts(
|
||||
BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ITEM));
|
||||
|
||||
for (BlackboardArtifact bArt : allArtifacts) {
|
||||
BlackboardAttribute setAttr = bArt.getAttribute(
|
||||
@ -650,6 +678,11 @@ public class PortableCaseReportModule implements ReportModule {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @SuppressWarnings("deprecation") - we need to support already existing
|
||||
* interesting file and artifact hits.
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
private List<String> getAllInterestingItemsSets() throws NoCurrentCaseException, TskCoreException {
|
||||
|
||||
// Get the set names in use for the current case.
|
||||
@ -660,6 +693,7 @@ public class PortableCaseReportModule implements ReportModule {
|
||||
// Get all SET_NAMEs from interesting item artifacts
|
||||
String innerSelect = "SELECT (value_text) AS set_name FROM blackboard_attributes WHERE (artifact_type_id = '"
|
||||
+ BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID() + "' OR artifact_type_id = '"
|
||||
+ BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ITEM.getTypeID() + "' OR artifact_type_id = '"
|
||||
+ BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID() + "') AND attribute_type_id = '"
|
||||
+ BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID() + "'"; // NON-NLS
|
||||
|
||||
@ -910,10 +944,10 @@ public class PortableCaseReportModule implements ReportModule {
|
||||
|
||||
// Copy the artifact
|
||||
BlackboardArtifact newArtifact = copyArtifact(newContentId, tag.getArtifact());
|
||||
|
||||
|
||||
// Copy any attachments
|
||||
copyAttachments(newArtifact, tag.getArtifact(), portableSkCase.getAbstractFileById(newContentId));
|
||||
|
||||
|
||||
// Copy any files associated with this artifact through the TSK_PATH_ID attribute
|
||||
copyPathID(newArtifact, tag.getArtifact());
|
||||
|
||||
@ -991,7 +1025,7 @@ public class PortableCaseReportModule implements ReportModule {
|
||||
throw new TskCoreException("Unexpected attribute value type found: " + oldAttr.getValueType().getLabel()); // NON-NLS
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Figure out the data source ID. We can't always get it from newContent because it could be null
|
||||
// for OS accounts, which means we also can't assume it's been added to the case already.
|
||||
Long newDataSourceId;
|
||||
@ -1007,13 +1041,12 @@ public class PortableCaseReportModule implements ReportModule {
|
||||
}
|
||||
newDataSourceId = copyContent(artifactToCopy.getDataSource());
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Create the new artifact
|
||||
int newArtifactTypeId = getNewArtifactTypeId(artifactToCopy);
|
||||
BlackboardArtifact.Type newArtifactType = portableSkCase.getBlackboard().getArtifactType(newArtifactTypeId);
|
||||
BlackboardArtifact newArtifact;
|
||||
|
||||
|
||||
// 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))) {
|
||||
@ -1033,13 +1066,13 @@ public class PortableCaseReportModule implements ReportModule {
|
||||
// If the lookup failed, just use the orginal BlackboardArtifact
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
if (artifactToCopy instanceof AnalysisResult) {
|
||||
AnalysisResult analysisResultToCopy = (AnalysisResult) artifactToCopy;
|
||||
newArtifact = portableSkCase.getBlackboard().newAnalysisResult(newArtifactType, newContentId,
|
||||
newDataSourceId, analysisResultToCopy.getScore(),
|
||||
analysisResultToCopy.getConclusion(), analysisResultToCopy.getConfiguration(),
|
||||
newDataSourceId, analysisResultToCopy.getScore(),
|
||||
analysisResultToCopy.getConclusion(), analysisResultToCopy.getConfiguration(),
|
||||
analysisResultToCopy.getJustification(), newAttrs).getAnalysisResult();
|
||||
} else if (artifactToCopy instanceof DataArtifact) {
|
||||
DataArtifact dataArtifactToCopy = (DataArtifact) artifactToCopy;
|
||||
@ -1048,20 +1081,20 @@ public class PortableCaseReportModule implements ReportModule {
|
||||
copyOsAccount(dataArtifactToCopy.getOsAccountObjectId().get());
|
||||
newOsAccountId = oldOsAccountIdToNewOsAccount.get((dataArtifactToCopy.getOsAccountObjectId().get())).getId();
|
||||
}
|
||||
newArtifact = portableSkCase.getBlackboard().newDataArtifact(newArtifactType, newContentId,
|
||||
newDataSourceId,
|
||||
newArtifact = portableSkCase.getBlackboard().newDataArtifact(newArtifactType, newContentId,
|
||||
newDataSourceId,
|
||||
newAttrs, newOsAccountId);
|
||||
} else {
|
||||
if (newArtifactType.getCategory().equals(BlackboardArtifact.Category.ANALYSIS_RESULT)) {
|
||||
newArtifact = portableSkCase.getBlackboard().newAnalysisResult(newArtifactType, newContentId,
|
||||
newDataSourceId, Score.SCORE_NONE,
|
||||
null, null, null, newAttrs).getAnalysisResult();
|
||||
newDataSourceId, Score.SCORE_NONE,
|
||||
null, null, null, newAttrs).getAnalysisResult();
|
||||
} else {
|
||||
newArtifact = portableSkCase.getBlackboard().newDataArtifact(newArtifactType, newContentId,
|
||||
newDataSourceId,
|
||||
newAttrs, null);
|
||||
newArtifact = portableSkCase.getBlackboard().newDataArtifact(newArtifactType, newContentId,
|
||||
newDataSourceId,
|
||||
newAttrs, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (BlackboardException ex) {
|
||||
throw new TskCoreException("Error copying artifact with ID: " + artifactToCopy.getId());
|
||||
}
|
||||
@ -1171,17 +1204,17 @@ public class PortableCaseReportModule implements ReportModule {
|
||||
// Get or create the host (if needed) before beginning transaction.
|
||||
Host newHost = null;
|
||||
if (content instanceof DataSource) {
|
||||
newHost = copyHost(((DataSource)content).getHost());
|
||||
newHost = copyHost(((DataSource) content).getHost());
|
||||
}
|
||||
|
||||
|
||||
// Copy the associated OS account (if needed) before beginning transaction.
|
||||
if (content instanceof AbstractFile) {
|
||||
AbstractFile file = (AbstractFile) content;
|
||||
if (file.getOsAccountObjectId().isPresent()) {
|
||||
if (file.getOsAccountObjectId().isPresent()) {
|
||||
copyOsAccount(file.getOsAccountObjectId().get());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Load the hashes if we have an image to avoid getting new connections with an open transaction.
|
||||
String md5 = "";
|
||||
String sha1 = "";
|
||||
@ -1191,7 +1224,7 @@ public class PortableCaseReportModule implements ReportModule {
|
||||
sha1 = ((Image) content).getSha1();
|
||||
sha256 = ((Image) content).getSha256();
|
||||
}
|
||||
|
||||
|
||||
CaseDbTransaction trans = portableSkCase.beginTransaction();
|
||||
try {
|
||||
if (content instanceof Image) {
|
||||
@ -1248,11 +1281,11 @@ public class PortableCaseReportModule implements ReportModule {
|
||||
if (abstractFile.getOsAccountObjectId().isPresent()) {
|
||||
newOsAccountId = oldOsAccountIdToNewOsAccount.get(abstractFile.getOsAccountObjectId().get()).getId();
|
||||
}
|
||||
|
||||
|
||||
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,
|
||||
true, TskData.EncodingType.NONE,
|
||||
newOsAccountId, abstractFile.getOwnerUid().orElse(null),
|
||||
newParent, trans);
|
||||
} catch (IOException ex) {
|
||||
@ -1276,14 +1309,16 @@ public class PortableCaseReportModule implements ReportModule {
|
||||
newIdToContent.put(newContent.getId(), newContent);
|
||||
return oldIdToNewContent.get(content.getId()).getId();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Copy a host into the portable case and add it to the oldHostIdToNewHost map.
|
||||
*
|
||||
* Copy a host into the portable case and add it to the oldHostIdToNewHost
|
||||
* map.
|
||||
*
|
||||
* @param oldHost The host to copy
|
||||
*
|
||||
*
|
||||
* @return The new host
|
||||
* @throws TskCoreException
|
||||
*
|
||||
* @throws TskCoreException
|
||||
*/
|
||||
private Host copyHost(Host oldHost) throws TskCoreException {
|
||||
Host newHost;
|
||||
@ -1295,11 +1330,11 @@ public class PortableCaseReportModule implements ReportModule {
|
||||
}
|
||||
return newHost;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Copy an OS Account to the new case and add it to the oldOsAccountIdToNewOsAccountId map.
|
||||
* Will also copy the associated realm.
|
||||
*
|
||||
* 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 OsAccount copyOsAccount(Long oldOsAccountId) throws TskCoreException {
|
||||
@ -1307,19 +1342,19 @@ public class PortableCaseReportModule implements ReportModule {
|
||||
if (oldOsAccountIdToNewOsAccount.containsKey(oldOsAccountId)) {
|
||||
return oldOsAccountIdToNewOsAccount.get(oldOsAccountId);
|
||||
}
|
||||
|
||||
|
||||
// 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 newHost = null;
|
||||
if (oldRealm.getScopeHost().isPresent()) {
|
||||
Host host = oldRealm.getScopeHost().get();
|
||||
@ -1334,7 +1369,7 @@ public class PortableCaseReportModule implements ReportModule {
|
||||
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();
|
||||
@ -1349,11 +1384,11 @@ public class PortableCaseReportModule implements ReportModule {
|
||||
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()));
|
||||
OsAccount newOsAccount = newOsAcctManager.newWindowsOsAccount(oldOsAccount.getAddr().orElse(null),
|
||||
oldOsAccount.getLoginName().orElse(null), oldRealmIdToNewRealm.get(oldOsAccount.getRealmId()));
|
||||
oldOsAccountIdToNewOsAccount.put(oldOsAccountId, newOsAccount);
|
||||
return newOsAccount;
|
||||
} catch (NotUserSIDException ex) {
|
||||
@ -1363,12 +1398,13 @@ public class PortableCaseReportModule implements ReportModule {
|
||||
|
||||
/**
|
||||
* Copy path ID attribute to new case along with the referenced file.
|
||||
*
|
||||
* @param newArtifact The new artifact in the portable case. Should not have a TSK_PATH_ID attribute.
|
||||
*
|
||||
* @param newArtifact The new artifact in the portable case. Should not have
|
||||
* a TSK_PATH_ID attribute.
|
||||
* @param oldArtifact The old artifact.
|
||||
*
|
||||
* @throws TskCoreException
|
||||
*/
|
||||
*
|
||||
* @throws TskCoreException
|
||||
*/
|
||||
private void copyPathID(BlackboardArtifact newArtifact, BlackboardArtifact oldArtifact) throws TskCoreException {
|
||||
// Get the path ID attribute
|
||||
BlackboardAttribute oldPathIdAttr = oldArtifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID));
|
||||
@ -1383,15 +1419,17 @@ public class PortableCaseReportModule implements ReportModule {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Copy attachments to the portable case.
|
||||
*
|
||||
* @param newArtifact The new artifact in the portable case. Should not have a TSK_ATTACHMENTS attribute.
|
||||
*
|
||||
* @param newArtifact The new artifact in the portable case. Should not have
|
||||
* a TSK_ATTACHMENTS attribute.
|
||||
* @param oldArtifact The old artifact.
|
||||
* @param newFile The new file in the portable case associated with the artifact.
|
||||
*
|
||||
* @throws TskCoreException
|
||||
* @param newFile The new file in the portable case associated with the
|
||||
* artifact.
|
||||
*
|
||||
* @throws TskCoreException
|
||||
*/
|
||||
private void copyAttachments(BlackboardArtifact newArtifact, BlackboardArtifact oldArtifact, AbstractFile newFile) throws TskCoreException {
|
||||
// Get the attachments from TSK_ATTACHMENTS attribute.
|
||||
@ -1414,20 +1452,19 @@ public class PortableCaseReportModule implements ReportModule {
|
||||
newFileAttachments.add(new MessageAttachments.FileAttachment(portableSkCase.getAbstractFileById(newFileID)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Get the name of the module(s) that created the attachment
|
||||
String newSourceStr = "";
|
||||
List<String> oldSources = attachmentsAttr.getSources();
|
||||
if (! oldSources.isEmpty()) {
|
||||
if (!oldSources.isEmpty()) {
|
||||
newSourceStr = String.join(",", oldSources);
|
||||
}
|
||||
|
||||
|
||||
// Add the attachment. The account type specified in the constructor will not be used.
|
||||
CommunicationArtifactsHelper communicationArtifactsHelper = new CommunicationArtifactsHelper(currentCase.getSleuthkitCase(),
|
||||
newSourceStr, newFile, Account.Type.EMAIL, null);
|
||||
communicationArtifactsHelper.addAttachments(newArtifact, new MessageAttachments(newFileAttachments, msgAttachments.getUrlAttachments()));
|
||||
}
|
||||
catch (BlackboardJsonAttrUtil.InvalidJsonException ex) {
|
||||
} catch (BlackboardJsonAttrUtil.InvalidJsonException ex) {
|
||||
throw new TskCoreException(String.format("Unable to parse json for MessageAttachments object in artifact: %s", oldArtifact.getName()), ex);
|
||||
}
|
||||
} else { // backward compatibility - email message attachments are derived files, children of the message.
|
||||
@ -1601,7 +1638,7 @@ public class PortableCaseReportModule implements ReportModule {
|
||||
"PortableCaseReportModule.compressCase.errorCompressingCase=Error compressing case",
|
||||
"PortableCaseReportModule.compressCase.canceled=Compression canceled by user",})
|
||||
private boolean compressCase(ReportProgressPanel progressPanel, String folderToCompress) {
|
||||
|
||||
|
||||
closePortableCaseDatabase();
|
||||
|
||||
// Make a temporary folder for the compressed case
|
||||
|
@ -48,8 +48,8 @@ final class InterestingArtifactCreatorIngestModule extends FileIngestModuleAdapt
|
||||
private static final String MODULE_NAME = InterestingArtifactCreatorIngestModuleFactory.getModuleName();
|
||||
private static final String[] ARTIFACT_TYPE_NAMES = {"TSK_WEB_BOOKMARK", "TSK_KEYWORD_HIT", "TSK_CALLLOG"};
|
||||
private static final String[] ARTIFACT_DISPLAY_NAMES = {"Web Bookmarks", "Keyword Hits", "Call Logs"};
|
||||
private static final String INT_ARTIFACT_TYPE_NAME = BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getLabel();
|
||||
private static final String INT_ARTIFACT_DISPLAY_NAME = BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getDisplayName();
|
||||
private static final String INT_ARTIFACT_TYPE_NAME = BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ITEM.getLabel();
|
||||
private static final String INT_ARTIFACT_DISPLAY_NAME = BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ITEM.getDisplayName();
|
||||
private BlackboardArtifact.Type artifactType;
|
||||
|
||||
@Override
|
||||
|
@ -134,7 +134,7 @@ public class EmbeddedFileTest extends NbTestCase {
|
||||
ArrayList<BlackboardArtifact> artifacts = file.getAllArtifacts();
|
||||
assertEquals("Zip bomb " + file.getName() + " has incorrect number of artifacts", 1, artifacts.size());
|
||||
for (BlackboardArtifact artifact : artifacts) {
|
||||
assertEquals("Artifact for Zip bomb " + file.getName() + " has incorrect type ID", artifact.getArtifactTypeID(), BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID());
|
||||
assertEquals("Artifact for Zip bomb " + file.getName() + " has incorrect type ID", artifact.getArtifactTypeID(), BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ITEM.getTypeID());
|
||||
BlackboardAttribute attribute = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME));
|
||||
assertNotNull("No attribute found for artifact on zip bomb " + file.getName(), attribute);
|
||||
assertEquals("Interesting artifact on file, " + file.getName() + ", does not reflect it being a zip bomb", zipBombSetName, attribute.getDisplayString());
|
||||
|
@ -381,9 +381,9 @@ class VolatilityProcessor {
|
||||
Collection<BlackboardAttribute> attributes = singleton(new BlackboardAttribute(TSK_SET_NAME, VOLATILITY, setName));
|
||||
|
||||
// Create artifact if it doesn't already exist.
|
||||
if (!blackboard.artifactExists(resolvedFile, BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT, attributes)) {
|
||||
if (!blackboard.artifactExists(resolvedFile, BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ITEM, attributes)) {
|
||||
BlackboardArtifact volArtifact = resolvedFile.newAnalysisResult(
|
||||
BlackboardArtifact.Type.TSK_INTERESTING_FILE_HIT, Score.SCORE_LIKELY_NOTABLE,
|
||||
BlackboardArtifact.Type.TSK_INTERESTING_ITEM, Score.SCORE_LIKELY_NOTABLE,
|
||||
null, setName, null,
|
||||
attributes)
|
||||
.getAnalysisResult();
|
||||
|
@ -82,9 +82,9 @@ Now that we have found the files, we want to do something with them. In our situ
|
||||
|
||||
A list of standard artifact types can be found in the <a href="http://sleuthkit.org/sleuthkit/docs/jni-docs/latest/artifact_catalog_page.html">artifact catalog</a>. It is important to note the catagory for the artifact you want to since this affects which method you will use to create the artifact.
|
||||
|
||||
For our example, we are going to make an artifact of type "TSK_INTERESTING_FILE", which is an analysis result, whenever we find a big and round file. These are one of the most generic artifact types and are simply a way of alerting the user that a file is interesting for some reason. Once you make the artifact, it will be shown in the UI. The below code makes an artifact for the file and puts it into the set of "Big and Round Files". You can create whatever set names you want. The Autopsy GUI organizes Interesting Files by their set name.
|
||||
For our example, we are going to make an artifact of type "TSK_INTERESTING_ITEM", which is an analysis result, whenever we find a big and round file. These are one of the most generic artifact types and are simply a way of alerting the user that a file is interesting for some reason. Once you make the artifact, it will be shown in the UI. The below code makes an artifact for the file and puts it into the set of "Big and Round Files". You can create whatever set names you want. The Autopsy GUI organizes Interesting Files by their set name.
|
||||
\verbatim
|
||||
art = file.newAnalysisResult(BlackboardArtifact.Type.TSK_INTERESTING_FILE_HIT, Score.SCORE_LIKELY_NOTABLE,
|
||||
art = file.newAnalysisResult(BlackboardArtifact.Type.TSK_INTERESTING_ITEM, Score.SCORE_LIKELY_NOTABLE,
|
||||
None, "Big and Round Files", None,
|
||||
Arrays.asList(
|
||||
BlackboardAttribute(BlackboardAttribute.Type.TSK_SET_NAME,
|
||||
@ -111,9 +111,9 @@ That's it. Your process() method should look something like this:
|
||||
# Look for files bigger than 10MB that are a multiple of 4096
|
||||
if ((file.getSize() > 10485760) and ((file.getSize() % 4096) == 0)):
|
||||
|
||||
# Make an artifact on the blackboard. TSK_INTERESTING_FILE_HIT is a generic type of
|
||||
# Make an artifact on the blackboard. TSK_INTERESTING_ITEM is a generic type of
|
||||
# artifact. Refer to the developer docs for other examples.
|
||||
art = file.newAnalysisResult(BlackboardArtifact.Type.TSK_INTERESTING_FILE_HIT, Score.SCORE_LIKELY_NOTABLE,
|
||||
art = file.newAnalysisResult(BlackboardArtifact.Type.TSK_INTERESTING_ITEM, Score.SCORE_LIKELY_NOTABLE,
|
||||
None, "Big and Round Files", None,
|
||||
Arrays.asList(
|
||||
BlackboardAttribute(BlackboardAttribute.Type.TSK_SET_NAME,
|
||||
|
@ -124,9 +124,9 @@ class FindBigRoundFilesIngestModule(FileIngestModule):
|
||||
# Look for files bigger than 10MB that are a multiple of 4096
|
||||
if ((file.getSize() > 10485760) and ((file.getSize() % 4096) == 0)):
|
||||
|
||||
# Make an artifact on the blackboard. TSK_INTERESTING_FILE_HIT is a generic type of
|
||||
# Make an artifact on the blackboard. TSK_INTERESTING_ITEM is a generic type of
|
||||
# artifact. Refer to the developer docs for other examples.
|
||||
art = file.newAnalysisResult(BlackboardArtifact.Type.TSK_INTERESTING_FILE_HIT, Score.SCORE_LIKELY_NOTABLE,
|
||||
art = file.newAnalysisResult(BlackboardArtifact.Type.TSK_INTERESTING_ITEM, Score.SCORE_LIKELY_NOTABLE,
|
||||
None, "Big and Round Files", None,
|
||||
Arrays.asList(
|
||||
BlackboardAttribute(BlackboardAttribute.Type.TSK_SET_NAME,
|
||||
|
@ -137,12 +137,12 @@ class SampleJythonDataSourceIngestModule(DataSourceIngestModule):
|
||||
self.log(Level.INFO, "Processing file: " + file.getName())
|
||||
fileCount += 1
|
||||
|
||||
# Make an artifact on the blackboard. TSK_INTERESTING_FILE_HIT is a generic type of
|
||||
# artfiact. Refer to the developer docs for other examples.
|
||||
# Make an artifact on the blackboard. TSK_INTERESTING_ITEM is a generic type of
|
||||
# artifact. Refer to the developer docs for other examples.
|
||||
attrs = Arrays.asList(BlackboardAttribute(BlackboardAttribute.Type.TSK_SET_NAME,
|
||||
SampleJythonDataSourceIngestModuleFactory.moduleName,
|
||||
"Test file"))
|
||||
art = file.newAnalysisResult(BlackboardArtifact.Type.TSK_INTERESTING_FILE_HIT, Score.SCORE_LIKELY_NOTABLE,
|
||||
art = file.newAnalysisResult(BlackboardArtifact.Type.TSK_INTERESTING_ITEM, Score.SCORE_LIKELY_NOTABLE,
|
||||
None, "Test file", None, attrs).getAnalysisResult()
|
||||
|
||||
try:
|
||||
|
@ -129,12 +129,12 @@ class SampleJythonFileIngestModule(FileIngestModule):
|
||||
self.log(Level.INFO, "Found a text file: " + file.getName())
|
||||
self.filesFound+=1
|
||||
|
||||
# Make an artifact on the blackboard. TSK_INTERESTING_FILE_HIT is a generic type of
|
||||
# Make an artifact on the blackboard. TSK_INTERESTING_ITEM is a generic type of
|
||||
# artifact. Refer to the developer docs for other examples.
|
||||
attrs = Arrays.asList(BlackboardAttribute(BlackboardAttribute.Type.TSK_SET_NAME,
|
||||
SampleJythonFileIngestModuleFactory.moduleName, "Text Files"))
|
||||
|
||||
art = file.newAnalysisResult(BlackboardArtifact.Type.TSK_INTERESTING_FILE_HIT, Score.SCORE_LIKELY_NOTABLE,
|
||||
art = file.newAnalysisResult(BlackboardArtifact.Type.TSK_INTERESTING_ITEM, Score.SCORE_LIKELY_NOTABLE,
|
||||
None, "Text Files", None, attrs).getAnalysisResult()
|
||||
|
||||
try:
|
||||
@ -145,7 +145,7 @@ class SampleJythonFileIngestModule(FileIngestModule):
|
||||
# For the example (this wouldn't be needed normally), we'll query the blackboard for data that was added
|
||||
# by other modules. We then iterate over its attributes. We'll just print them, but you would probably
|
||||
# want to do something with them.
|
||||
artifactList = file.getArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT)
|
||||
artifactList = file.getArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ITEM)
|
||||
for artifact in artifactList:
|
||||
attributeList = artifact.getAttributes()
|
||||
for attrib in attributeList:
|
||||
|
Loading…
x
Reference in New Issue
Block a user