Merge branch 'sleuthkit:develop' into develop

This commit is contained in:
Seb2lyon 2021-06-18 22:09:42 +02:00 committed by GitHub
commit 46a0713333
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 385 additions and 146 deletions

View File

@ -26,6 +26,7 @@ import java.util.Date;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import javax.swing.JOptionPane;
@ -167,6 +168,8 @@ public final class IngestJobInfoPanel extends javax.swing.JPanel {
}
} catch (InterruptedException | ExecutionException ex) {
logger.log(Level.WARNING, "Error getting results from Ingest Job Info Panel's refresh worker", ex);
} catch (CancellationException ignored){
logger.log(Level.INFO, "The refreshing of the IngestJobInfoPanel was cancelled");
}
}
};

View File

@ -90,17 +90,17 @@ public final class DataContentViewerOtherCases extends JPanel implements DataCon
public boolean isSupported(Node node) {
// Is supported if one of the following is true:
// - The central repo is enabled and the node has correlatable content
// (either through the MD5 hash of the associated file or through a BlackboardArtifact)
// - The central repo is enabled and the node is not null
// - The central repo is disabled and the backing file has a valid MD5 hash
if (CentralRepository.isEnabled() && node != null) {
return true;
} else if (node != null){
AbstractFile file = OtherOccurrences.getAbstractFileFromNode(node);
if (CentralRepository.isEnabled()) {
return !OtherOccurrences.getCorrelationAttributesFromNode(node, file).isEmpty();
} else {
return file != null
&& file.getSize() > 0
&& ((file.getMd5Hash() != null) && (!file.getMd5Hash().isEmpty()));
}
return false;
}
@Override

View File

@ -130,25 +130,7 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data
@Override
public boolean isSupported(Node node) {
BlackboardArtifact artifact = node.getLookup().lookup(BlackboardArtifact.class);
try {
if (artifact != null) {
if (artifact.getSleuthkitCase().getAbstractFileById(artifact.getObjectID()) != null) {
return true;
}
} else {
if (node.getLookup().lookup(AbstractFile.class) != null) {
return true;
}
}
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, String.format(
"Exception while trying to retrieve a Content instance from the BlackboardArtifact '%s' (id=%d).",
artifact.getDisplayName(), artifact.getArtifactID()), ex);
}
return false;
return node != null && node.getLookup().lookup(AbstractFile.class) != null;
}
@Override

View File

@ -150,7 +150,7 @@ public class Metadata extends javax.swing.JPanel implements DataContentViewer {
ContentViewerHtmlStyles.getTextClassName(),
EscapeUtil.escapeHtml(key),
ContentViewerHtmlStyles.getTextClassName(),
EscapeUtil.escapeHtml(key)
EscapeUtil.escapeHtml(value)
));
}

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2019 Basis Technology Corp.
* Copyright 2019-2021 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -79,9 +79,9 @@ public class TextContentViewerPanel extends javax.swing.JPanel implements DataCo
}
/**
* Determine whether the content viewer which displays this panel isSupported.
* This panel is supported if any of the TextViewer's displayed in it are
* supported.
* Determine whether the content viewer which displays this panel
* isSupported. This panel is supported if any of the TextViewer's displayed
* in it are supported.
*
* @param node
*
@ -213,7 +213,7 @@ public class TextContentViewerPanel extends javax.swing.JPanel implements DataCo
// Get and set current selected tab
int currentTab = pane.getSelectedIndex();
if (currentTab != -1) {
if (currentTab != -1 && pane.isEnabledAt(currentTab)) {
UpdateWrapper dcv = textViewers.get(currentTab);
if (dcv.isOutdated()) {
// change the cursor to "waiting cursor" for this operation

View File

@ -194,6 +194,8 @@ public class HostNode extends DisplayableItemNode {
}
};
private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(hostChangePcl, null);
/*
* Get the host name or 'unknown host' if null.
*
@ -251,8 +253,7 @@ public class HostNode extends DisplayableItemNode {
host == null ? Lookups.fixed(displayName) : Lookups.fixed(host, displayName));
hostId = host == null ? null : host.getHostId();
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.HOSTS_UPDATED),
WeakListeners.propertyChange(hostChangePcl, this));
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.HOSTS_UPDATED), weakPcl);
super.setName(displayName);
super.setDisplayName(displayName);
this.setIconBaseWithExtension(ICON_PATH);

View File

@ -178,6 +178,8 @@ public class PersonNode extends DisplayableItemNode {
}
};
private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(personChangePcl, null);
/**
* Gets the display name for this person or "Unknown Persons".
*
@ -214,8 +216,7 @@ public class PersonNode extends DisplayableItemNode {
this.setIconBaseWithExtension(ICON_PATH);
this.person = person;
this.personId = person == null ? null : person.getPersonId();
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.PERSONS_UPDATED),
WeakListeners.propertyChange(personChangePcl, this));
Case.addEventTypeSubscriber(EnumSet.of(Case.Events.PERSONS_UPDATED), weakPcl);
}
@Override

View File

@ -18,8 +18,12 @@
*/
package org.sleuthkit.autopsy.directorytree;
import java.util.Objects;
import org.openide.nodes.Node;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.casemodule.CasePreferences;
import org.sleuthkit.autopsy.datamodel.DataSourceFilesNode;
import org.sleuthkit.autopsy.datamodel.DataSourcesNode;
import static org.sleuthkit.autopsy.directorytree.Bundle.*;
@NbBundle.Messages({"SelectionContext.dataSources=Data Sources",
@ -62,6 +66,12 @@ enum SelectionContext {
if (n == null || n.getParentNode() == null) {
// Parent of root node or root node. Occurs during case open / close.
return SelectionContext.OTHER;
} else if ((!Objects.equals(CasePreferences.getGroupItemsInTreeByDataSource(), true) && DataSourcesNode.getNameIdentifier().equals(n.getParentNode().getName()))
|| (Objects.equals(CasePreferences.getGroupItemsInTreeByDataSource(), true) && DataSourceFilesNode.getNameIdentifier().equals(n.getParentNode().getName()))) {
// if group by data type and root is the DataSourcesNode or
// if group by persons/hosts and parent of DataSourceFilesNode
// then it is a data source node
return SelectionContext.DATA_SOURCES;
} else if (n.getParentNode().getParentNode() == null) {
// One level below root node. Should be one of DataSources, Views, or Results
return SelectionContext.getContextFromName(n.getDisplayName());

View File

@ -3,7 +3,7 @@
<Form version="1.5" maxVersion="1.8" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<Properties>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[650, 250]"/>
<Dimension value="[834, 374]"/>
</Property>
</Properties>
<AuxValues>
@ -24,13 +24,11 @@
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<Component id="reportModulesLabel" min="-2" max="-2" attributes="0"/>
<Component id="modulesScrollPane" min="-2" pref="190" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="configurationPanel" max="32767" attributes="0"/>
<Component id="descriptionScrollPane" max="32767" attributes="0"/>
<Component id="modulesSplitPane" alignment="0" max="32767" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
@ -42,14 +40,7 @@
<EmptySpace max="-2" attributes="0"/>
<Component id="reportModulesLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<Component id="descriptionScrollPane" min="-2" pref="32" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="configurationPanel" max="32767" attributes="0"/>
</Group>
<Component id="modulesScrollPane" pref="208" max="32767" attributes="0"/>
</Group>
<Component id="modulesSplitPane" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
@ -63,6 +54,59 @@
</Property>
</Properties>
</Component>
<Container class="javax.swing.JSplitPane" name="modulesSplitPane">
<Properties>
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
<Border info="null"/>
</Property>
<Property name="dividerSize" type="int" value="8"/>
<Property name="resizeWeight" type="double" value="0.5"/>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_InitCodePre" type="java.lang.String" value="//Make border on split pane invisible to maintain previous style&#xa;modulesSplitPane.setUI(new javax.swing.plaf.basic.BasicSplitPaneUI() {&#xa; @Override&#xa; public javax.swing.plaf.basic.BasicSplitPaneDivider createDefaultDivider() {&#xa; javax.swing.plaf.basic.BasicSplitPaneDivider divider = new javax.swing.plaf.basic.BasicSplitPaneDivider(this) {&#xa; @Override&#xa; public void setBorder(Border border){&#xa; //do nothing so border is not visible&#xa; }&#xa; };&#xa; return divider;&#xa;}&#xa;});"/>
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout"/>
<SubComponents>
<Container class="javax.swing.JPanel" name="detailsPanel">
<AuxValues>
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
</AuxValues>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
<JSplitPaneConstraints position="right"/>
</Constraint>
</Constraints>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="descriptionScrollPane" max="32767" attributes="0"/>
<Component id="configurationPanel" max="32767" attributes="0"/>
</Group>
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
<Component id="descriptionScrollPane" min="-2" pref="32" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="configurationPanel" max="32767" attributes="0"/>
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Container class="javax.swing.JPanel" name="configurationPanel">
<Properties>
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
@ -78,12 +122,12 @@
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<EmptySpace min="0" pref="432" max="32767" attributes="0"/>
<EmptySpace min="0" pref="546" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<EmptySpace min="0" pref="168" max="32767" attributes="0"/>
<EmptySpace min="0" pref="290" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
</Layout>
@ -113,10 +157,17 @@
</Component>
</SubComponents>
</Container>
</SubComponents>
</Container>
<Container class="javax.swing.JScrollPane" name="modulesScrollPane">
<AuxValues>
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
</AuxValues>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JSplitPaneSupportLayout$JSplitPaneConstraintsDescription">
<JSplitPaneConstraints position="left"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
@ -138,4 +189,6 @@
</SubComponents>
</Container>
</SubComponents>
</Container>
</SubComponents>
</Form>

View File

@ -36,6 +36,7 @@ import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.ListCellRenderer;
import javax.swing.ListSelectionModel;
import javax.swing.border.Border;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import org.openide.DialogDisplayer;
@ -271,16 +272,35 @@ final class ReportVisualPanel1 extends JPanel implements ListSelectionListener {
private void initComponents() {
reportModulesLabel = new javax.swing.JLabel();
javax.swing.JSplitPane modulesSplitPane = new javax.swing.JSplitPane();
javax.swing.JPanel detailsPanel = new javax.swing.JPanel();
configurationPanel = new javax.swing.JPanel();
descriptionScrollPane = new javax.swing.JScrollPane();
descriptionTextPane = new javax.swing.JTextPane();
modulesScrollPane = new javax.swing.JScrollPane();
modulesJList = new javax.swing.JList<>();
setPreferredSize(new java.awt.Dimension(650, 250));
setPreferredSize(new java.awt.Dimension(834, 374));
org.openide.awt.Mnemonics.setLocalizedText(reportModulesLabel, org.openide.util.NbBundle.getMessage(ReportVisualPanel1.class, "ReportVisualPanel1.reportModulesLabel.text")); // NOI18N
//Make border on split pane invisible to maintain previous style
modulesSplitPane.setUI(new javax.swing.plaf.basic.BasicSplitPaneUI() {
@Override
public javax.swing.plaf.basic.BasicSplitPaneDivider createDefaultDivider() {
javax.swing.plaf.basic.BasicSplitPaneDivider divider = new javax.swing.plaf.basic.BasicSplitPaneDivider(this) {
@Override
public void setBorder(Border border){
//do nothing so border is not visible
}
};
return divider;
}
});
modulesSplitPane.setBorder(null);
modulesSplitPane.setDividerSize(8);
modulesSplitPane.setResizeWeight(0.5);
configurationPanel.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(125, 125, 125)));
configurationPanel.setOpaque(false);
@ -288,11 +308,11 @@ final class ReportVisualPanel1 extends JPanel implements ListSelectionListener {
configurationPanel.setLayout(configurationPanelLayout);
configurationPanelLayout.setHorizontalGroup(
configurationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 432, Short.MAX_VALUE)
.addGap(0, 546, Short.MAX_VALUE)
);
configurationPanelLayout.setVerticalGroup(
configurationPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 168, Short.MAX_VALUE)
.addGap(0, 290, Short.MAX_VALUE)
);
descriptionScrollPane.setBorder(null);
@ -302,6 +322,29 @@ final class ReportVisualPanel1 extends JPanel implements ListSelectionListener {
descriptionTextPane.setOpaque(false);
descriptionScrollPane.setViewportView(descriptionTextPane);
javax.swing.GroupLayout detailsPanelLayout = new javax.swing.GroupLayout(detailsPanel);
detailsPanel.setLayout(detailsPanelLayout);
detailsPanelLayout.setHorizontalGroup(
detailsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(detailsPanelLayout.createSequentialGroup()
.addGap(0, 0, 0)
.addGroup(detailsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(descriptionScrollPane)
.addComponent(configurationPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addGap(0, 0, 0))
);
detailsPanelLayout.setVerticalGroup(
detailsPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(detailsPanelLayout.createSequentialGroup()
.addGap(0, 0, 0)
.addComponent(descriptionScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(configurationPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGap(0, 0, 0))
);
modulesSplitPane.setRightComponent(detailsPanel);
modulesJList.setBackground(new java.awt.Color(240, 240, 240));
modulesJList.setModel(new javax.swing.AbstractListModel<ReportModule>() {
ReportModule[] modules = {};
@ -311,6 +354,8 @@ final class ReportVisualPanel1 extends JPanel implements ListSelectionListener {
modulesJList.setOpaque(false);
modulesScrollPane.setViewportView(modulesJList);
modulesSplitPane.setLeftComponent(modulesScrollPane);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
@ -318,12 +363,10 @@ final class ReportVisualPanel1 extends JPanel implements ListSelectionListener {
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(reportModulesLabel)
.addComponent(modulesScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 190, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(configurationPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(descriptionScrollPane))
.addGap(0, 0, Short.MAX_VALUE))
.addComponent(modulesSplitPane))
.addContainerGap())
);
layout.setVerticalGroup(
@ -332,12 +375,7 @@ final class ReportVisualPanel1 extends JPanel implements ListSelectionListener {
.addContainerGap()
.addComponent(reportModulesLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(descriptionScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 32, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(configurationPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addComponent(modulesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 208, Short.MAX_VALUE))
.addComponent(modulesSplitPane)
.addContainerGap())
);
}// </editor-fold>//GEN-END:initComponents

View File

@ -7,7 +7,7 @@
</NonVisualComponents>
<Properties>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[650, 275]"/>
<Dimension value="[834, 374]"/>
</Property>
</Properties>
<AuxValues>

View File

@ -311,7 +311,7 @@ final class ReportVisualPanel2 extends JPanel {
advancedButton = new javax.swing.JButton();
allTaggedResultsRadioButton = new javax.swing.JRadioButton();
setPreferredSize(new java.awt.Dimension(650, 275));
setPreferredSize(new java.awt.Dimension(834, 374));
optionsButtonGroup.add(specificTaggedResultsRadioButton);
org.openide.awt.Mnemonics.setLocalizedText(specificTaggedResultsRadioButton, org.openide.util.NbBundle.getMessage(ReportVisualPanel2.class, "ReportVisualPanel2.specificTaggedResultsRadioButton.text")); // NOI18N

View File

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

View File

@ -113,10 +113,14 @@
</subant>
</target>
<target name="set-release-build">
<property name="build.type" value="RELEASE"/>
</target>
<!-- This target will create a custom ZIP file for us. It first uses the general
ZIP target and then opens it up and adds in any files that we want. This is where we customize the
version number. -->
<target name="build-zip" depends="doxygen, suite.build-zip"> <!--,findJRE" -->
<target name="build-zip" depends="set-release-build, doxygen, suite.build-zip"> <!--,findJRE" -->
<property name="release.dir" value="${nbdist.dir}/${app.name}"/>
@ -343,7 +347,7 @@
<target name="versioning-script" depends="check-release, versioning-script-if-release, versioning-script-if-not-release"/>
<target name="build-installer" depends="getProps, doxygen, build-zip" description="Builds Autopsy installer.">
<target name="build-installer" depends="set-release-build, getProps, doxygen, build-zip" description="Builds Autopsy installer.">
<!-- Unzip file -->
<delete dir="${nbdist.dir}/${app.name}-tmp-installer" quiet="true"/>
<unzip src="${nbdist.dir}/${app.name}-${app.version}.zip" dest="${nbdist.dir}/${app.name}-tmp-installer"/>