From 170f8144160b290388e27b1d6752fa2d03db7295 Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Thu, 25 Feb 2021 17:42:29 -0500 Subject: [PATCH 1/7] Added OsAccount content viewer --- .../osaccount/Bundle.properties | 1 + .../osaccount/Bundle.properties-MERGED | 18 + .../osaccount/OsAccountDataPanel.java | 316 ++++++++++++++++++ .../osaccount/OsAccountViewer.form | 28 ++ .../osaccount/OsAccountViewer.java | 162 +++++++++ .../contentviewers/osaccount/SectionData.java | 108 ++++++ 6 files changed, 633 insertions(+) create mode 100755 Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/Bundle.properties create mode 100755 Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/Bundle.properties-MERGED create mode 100755 Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/OsAccountDataPanel.java create mode 100755 Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/OsAccountViewer.form create mode 100755 Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/OsAccountViewer.java create mode 100755 Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/SectionData.java diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/Bundle.properties b/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/Bundle.properties new file mode 100755 index 0000000000..3cf6f4a75a --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/Bundle.properties @@ -0,0 +1 @@ +TableDataPanel.titleLabel.text=Title diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/Bundle.properties-MERGED new file mode 100755 index 0000000000..c313958fd5 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/Bundle.properties-MERGED @@ -0,0 +1,18 @@ +OsAccountDataPanel_basic_address=Address +OsAccountDataPanel_basic_admin=Administrator +OsAccountDataPanel_basic_creationDate=Creation Date +OsAccountDataPanel_basic_fullname=Full Name +OsAccountDataPanel_basic_login=Login +OsAccountDataPanel_basic_no=No +OsAccountDataPanel_basic_title=Basic Properties +OsAccountDataPanel_basic_type=Type +OsAccountDataPanel_basic_unknown=Unknown +OsAccountDataPanel_basic_yes=Yes +OsAccountDataPanel_realm_address=Address +OsAccountDataPanel_realm_confidence=Confidence +OsAccountDataPanel_realm_name=Name +OsAccountDataPanel_realm_title=Realm Properties +OsAccountDataPanel_realm_unknown=Unknown +OsAccountViewer_title=Os Account +OsAccountViewer_tooltip=Viewer for OS accounts related to the selected node. +TableDataPanel.titleLabel.text=Title diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/OsAccountDataPanel.java b/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/OsAccountDataPanel.java new file mode 100755 index 0000000000..91884dfc30 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/OsAccountDataPanel.java @@ -0,0 +1,316 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2021 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.contentviewers.osaccount; + +import java.awt.Font; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import static java.util.Locale.US; +import java.util.Optional; +import javax.swing.Box; +import javax.swing.JLabel; +import javax.swing.JPanel; +import org.openide.util.NbBundle.Messages; +import org.sleuthkit.autopsy.contentviewers.osaccount.SectionData.RowData; +import org.sleuthkit.datamodel.OsAccount; +import org.sleuthkit.datamodel.OsAccountRealm; + +/** + * Panel for displaying the properties of an OsAccount. + */ +public class OsAccountDataPanel extends JPanel { + + private static final long serialVersionUID = 1L; + + private static final int KEY_COLUMN = 0; + private static final int VALUE_COLUMN = 1; + + private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("MMM dd yyyy", US); + + // Panel constructor. + OsAccountDataPanel() { + initialize(); + } + + /** + * Initializes the panel layout. + */ + private void initialize() { + this.setLayout(new GridBagLayout()); + } + + /** + * Set the OsAccount to display in this panel. + * + * @param account OsAccount to display, if null is passed the panel will + * appear blank. + */ + void setOsAccount(OsAccount account) { + removeAll(); + + if (account != null) { + List data = new ArrayList<>(); + data.add(buildBasicProperties(account)); + + OsAccountRealm realm = account.getRealm(); + if (realm != null) { + data.add(buildRealmProperties(realm)); + } + + addDataComponents(data); + } + revalidate(); + } + + /** + * Give all of the data to display, create the swing components and add to + * the panel. + * + * @param panelData Data to be displayed. + */ + private void addDataComponents(List panelData) { + int rowCnt = 0; + for (SectionData section : panelData) { + addTitle(section.getTitle(), rowCnt++); + + for (RowData rowData : section) { + String key = rowData.getKey(); + String value = rowData.getValue(); + + addPropertyName(key, rowCnt); + addPropertyValue(value, rowCnt++); + } + } + + // Generate the constraints for a Vertical Glue to fill the space, if + // any at the bottom of the panel. + GridBagConstraints constraints = new GridBagConstraints(); + constraints.gridx = 0; + constraints.gridy = rowCnt; + constraints.gridwidth = 2; + constraints.fill = GridBagConstraints.BOTH; + constraints.weightx = 1; + constraints.weighty = 1; + add(Box.createVerticalGlue(), constraints); + } + + @Messages({ + "OsAccountDataPanel_basic_title=Basic Properties", + "OsAccountDataPanel_basic_login=Login", + "OsAccountDataPanel_basic_fullname=Full Name", + "OsAccountDataPanel_basic_address=Address", + "OsAccountDataPanel_basic_admin=Administrator", + "OsAccountDataPanel_basic_type=Type", + "OsAccountDataPanel_basic_creationDate=Creation Date", + }) + + /** + * Returns the data for the Basic Properties section of the panel. + * + * @param account Selected account + * + * @return The basic properties data for the given account. + */ + private SectionData buildBasicProperties(OsAccount account) { + SectionData data = new SectionData(Bundle.OsAccountDataPanel_basic_title()); + + Optional optional = account.getLoginName(); + data.addData(Bundle.OsAccountDataPanel_basic_login(), + optional.isPresent() ? optional.get() : ""); + + optional = account.getFullName(); + data.addData(Bundle.OsAccountDataPanel_basic_fullname(), + optional.isPresent() ? optional.get() : ""); + + data.addData(Bundle.OsAccountDataPanel_basic_address(), + account.getName() == null || account.getName().isEmpty() ? "" : account.getName()); + + data.addData(Bundle.OsAccountDataPanel_basic_admin(), getIsAdminValue(account.isAdmin())); + + data.addData(Bundle.OsAccountDataPanel_basic_type(), account.getOsAccountType().getName()); + + Optional crTime = account.getCreationTime(); + Date date = null; + if(crTime.isPresent()) { + date = new Date(crTime.get()); + } + + data.addData(Bundle.OsAccountDataPanel_basic_creationDate(), data != null ? DATE_FORMAT.format(date) : ""); + + return data; + } + + @Messages({ + "OsAccountDataPanel_realm_title=Realm Properties", + "OsAccountDataPanel_realm_name=Name", + "OsAccountDataPanel_realm_address=Address", + "OsAccountDataPanel_realm_confidence=Confidence", + "OsAccountDataPanel_realm_unknown=Unknown",}) + + /** + * Builds the Realm Properties. + * + * @param realm A valid OsAccountRealm. + * + * @return Data to be displayed for the given realm. + */ + private SectionData buildRealmProperties(OsAccountRealm realm) { + SectionData data = new SectionData(Bundle.OsAccountDataPanel_realm_title()); + + Optional optional = realm.getRealmName(); + data.addData(Bundle.OsAccountDataPanel_realm_name(), + optional.isPresent() ? optional.get() : Bundle.OsAccountDataPanel_realm_unknown()); + + optional = realm.getRealmAddr(); + data.addData(Bundle.OsAccountDataPanel_realm_address(), + optional.isPresent() ? optional.get() : ""); + + data.addData(Bundle.OsAccountDataPanel_realm_confidence(), + realm.getScopeConfidence().getName()); + + return data; + } + + /** + * Add a section title to the panel with the given title and location. + * + * @param title Section title. + * @param row Row in the layout the title will appear. + */ + private void addTitle(String title, int row) { + JLabel label = new JLabel(title); + // Make the title bold. + label.setFont(label.getFont().deriveFont(Font.BOLD)); + add(label, getTitleContraints(row)); + } + + /** + * Add the property name at the given row in the layout. + * + * @param key The property name. + * @param row The row in the layout. + */ + private void addPropertyName(String key, int row) { + JLabel label = new JLabel(key); + add(label, getPropertyNameContraints(row)); + } + + /** + * Add the property value at the given row in the layout. + * + * @param value The value to display. + * @param row The row in the layout. + */ + private void addPropertyValue(String value, int row) { + JLabel label = new JLabel(value); + add(label, getPropertyValueContraints(row)); + } + + /** + * Generate the constraints for a title at the given row. + * + * @param row The row to generate the title constraints for. + * + * @return Constraints for a title row. + */ + private GridBagConstraints getTitleContraints(int row) { + GridBagConstraints constraints = new GridBagConstraints(); + + constraints.gridx = 0; + constraints.gridy = row; + constraints.gridwidth = 2; // The title goes across the other columns + constraints.gridheight = 1; + constraints.anchor = GridBagConstraints.NORTHWEST; + constraints.fill = GridBagConstraints.HORIZONTAL; + constraints.weightx = 1; + constraints.insets = new Insets(5, 5, 5, 9); + + return constraints; + } + + /** + * Generate the constraints for a property name at the given row. + * + * @param row + * + * @return Constraints for the property name label. + */ + private GridBagConstraints getPropertyNameContraints(int row) { + GridBagConstraints constraints = new GridBagConstraints(); + + constraints.gridx = KEY_COLUMN; + constraints.gridy = row; + constraints.gridwidth = 1; // The title goes across the other columns + constraints.gridheight = 1; + constraints.anchor = GridBagConstraints.WEST; + constraints.insets = new Insets(0, 8, 5, 5); + + return constraints; + } + + /** + * Generate the constraints for a property value at the given row. + * + * @param row Row in the layout. + * + * @return The constraints for the property label. + */ + private GridBagConstraints getPropertyValueContraints(int row) { + GridBagConstraints constraints = new GridBagConstraints(); + + constraints.gridx = VALUE_COLUMN; + constraints.gridy = row; + constraints.gridwidth = 1; // The title goes across the other columns + constraints.gridheight = 1; + constraints.fill = GridBagConstraints.HORIZONTAL; + constraints.weightx = 1; + constraints.insets = new Insets(0, 5, 5, 5); + + return constraints; + } + + @Messages({ + "OsAccountDataPanel_basic_yes=Yes", + "OsAccountDataPanel_basic_no=No", + "OsAccountDataPanel_basic_unknown=Unknown",}) + /** + * Return a string representation of the isAdmin status for OsAccounts. + * + * @param isAdmin Admin state for the OsAccount + * + * @return String representation of the admin state. + */ + private String getIsAdminValue(Optional isAdmin) { + if (!isAdmin.isPresent()) { + return Bundle.OsAccountDataPanel_basic_unknown(); + } else { + if (isAdmin.get()) { + return Bundle.OsAccountDataPanel_basic_yes(); + } else { + return Bundle.OsAccountDataPanel_basic_no(); + } + } + } + +} diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/OsAccountViewer.form b/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/OsAccountViewer.form new file mode 100755 index 0000000000..910ba27b78 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/OsAccountViewer.form @@ -0,0 +1,28 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/OsAccountViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/OsAccountViewer.java new file mode 100755 index 0000000000..ccedd942bb --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/OsAccountViewer.java @@ -0,0 +1,162 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2021 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.contentviewers.osaccount; + +import java.awt.Component; +import java.util.Optional; +import java.util.logging.Level; +import org.openide.nodes.Node; +import org.openide.util.NbBundle.Messages; +import org.openide.util.lookup.ServiceProvider; +import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.datamodel.AbstractFile; +import org.sleuthkit.datamodel.DataArtifact; +import org.sleuthkit.datamodel.OsAccount; +import org.sleuthkit.datamodel.TskCoreException; + +/** + * DataContentViewer for OsAccounts. + */ +@ServiceProvider(service = DataContentViewer.class, position = 12) +public class OsAccountViewer extends javax.swing.JPanel implements DataContentViewer { + + private static final long serialVersionUID = 1L; + private final static Logger logger = Logger.getLogger(OsAccountViewer.class.getName()); + + private final OsAccountDataPanel dataPanel = new OsAccountDataPanel(); + + /** + * Creates new form OsAccountViewer + */ + public OsAccountViewer() { + initComponents(); + + mainScrollPane.setViewportView(dataPanel); + } + + @Override + public void setNode(Node node) { + OsAccount osAccount = null; + try { + osAccount = node.getLookup().lookup(OsAccount.class); + if (osAccount == null) { + Optional optional; + AbstractFile file = node.getLookup().lookup(AbstractFile.class); + if (file != null) { + optional = file.getOsAccount(); + if (optional.isPresent()) { + osAccount = optional.get(); + } + } + } + + if (osAccount == null) { + DataArtifact dataArtifact = node.getLookup().lookup(DataArtifact.class); + if (dataArtifact != null) { + Optional optional = dataArtifact.getOsAccount(); + if (optional.isPresent()) { + osAccount = optional.get(); + } + } + + } + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, String.format("Failed to get OsAccount for node %s", node.getDisplayName()), ex); + } + + if (osAccount != null) { + dataPanel.setOsAccount(osAccount); + } + } + + @Messages({ + "OsAccountViewer_title=Os Account" + }) + @Override + public String getTitle() { + return Bundle.OsAccountViewer_title(); + } + + @Messages({ + "OsAccountViewer_tooltip=Viewer for OS accounts related to the selected node." + }) + @Override + public String getToolTip() { + return Bundle.OsAccountViewer_tooltip(); + } + + @Override + public DataContentViewer createInstance() { + return new OsAccountViewer(); + } + + @Override + public Component getComponent() { + return this; + } + + @Override + public void resetComponent() { + dataPanel.setOsAccount(null); + } + + @Override + public boolean isSupported(Node node) { + AbstractFile file = node.getLookup().lookup(AbstractFile.class); + OsAccount osAccount = node.getLookup().lookup(OsAccount.class); + DataArtifact dataArtifact = node.getLookup().lookup(DataArtifact.class); + + try { + return osAccount != null + || (file != null && file.getOsAccount().isPresent()) + || (dataArtifact != null && dataArtifact.getOsAccount().isPresent()); + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, String.format("Failed to determine if node %s is Supported for OsAccountViewer", node.getDisplayName()), ex); + return false; + } + } + + @Override + public int isPreferred(Node node) { + return 5; + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + java.awt.GridBagConstraints gridBagConstraints; + + mainScrollPane = new javax.swing.JScrollPane(); + + setLayout(new java.awt.BorderLayout()); + add(mainScrollPane, java.awt.BorderLayout.CENTER); + }// //GEN-END:initComponents + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JScrollPane mainScrollPane; + // End of variables declaration//GEN-END:variables + +} diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/SectionData.java b/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/SectionData.java new file mode 100755 index 0000000000..4674ff0756 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/SectionData.java @@ -0,0 +1,108 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2021 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.contentviewers.osaccount; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/** + * Data model for OsAccount panels, but could be reused in other places. The + * model represents a titled section of key\value pairs. + */ +final class SectionData implements Iterable> { + + private final String title; + private final List> data; + + /** + * Construct a new SectionData object. + * + * @param title + */ + SectionData(String title) { + this.title = title; + this.data = new ArrayList<>(); + } + + /** + * Returns the title for this section. + * + * @return The section title. + */ + String getTitle() { + return title; + } + + /** + * Add a new property name\property value pair. + * + * @param key The property display name. + * @param value The property value. + */ + void addData(String properytName, String propertyValue) { + data.add(new RowData<>(properytName, propertyValue)); + } + + @Override + public Iterator> iterator() { + return data.iterator(); + } + + /** + * Represents a row of data. In this case it is just a key value pair. + * + * @param Property Name. + * @param Property Value. + */ + static class RowData { + + private final K key; + private final V value; + + /** + * Construct a new row of data for the model. + * + * @param key + * @param value + */ + RowData(K key, V value) { + this.key = key; + this.value = value; + } + + /** + * Returns the key. + * + * @return The key value. + */ + K getKey() { + return key; + } + + /** + * Returns the value. + * + * @return The value. + */ + V getValue() { + return value; + } + } +} From 08d027c5ade716d3062d6a47168a77f705d0bcb3 Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Fri, 26 Feb 2021 13:14:58 -0500 Subject: [PATCH 2/7] Fixed bug in the creation time display --- .../contentviewers/osaccount/OsAccountDataPanel.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/OsAccountDataPanel.java b/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/OsAccountDataPanel.java index 91884dfc30..dde7396040 100755 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/OsAccountDataPanel.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/OsAccountDataPanel.java @@ -151,12 +151,12 @@ public class OsAccountDataPanel extends JPanel { data.addData(Bundle.OsAccountDataPanel_basic_type(), account.getOsAccountType().getName()); Optional crTime = account.getCreationTime(); - Date date = null; if(crTime.isPresent()) { - date = new Date(crTime.get()); + data.addData(Bundle.OsAccountDataPanel_basic_creationDate(), DATE_FORMAT.format(new Date(crTime.get() * 1000))); + } + else { + data.addData(Bundle.OsAccountDataPanel_basic_creationDate(), ""); } - - data.addData(Bundle.OsAccountDataPanel_basic_creationDate(), data != null ? DATE_FORMAT.format(date) : ""); return data; } @@ -264,7 +264,7 @@ public class OsAccountDataPanel extends JPanel { constraints.gridwidth = 1; // The title goes across the other columns constraints.gridheight = 1; constraints.anchor = GridBagConstraints.WEST; - constraints.insets = new Insets(0, 8, 5, 5); + constraints.insets = new Insets(0, 13, 5, 5); return constraints; } From f725d9eb4c20e44e92ab2f7f3116389bd6efd113 Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Mon, 1 Mar 2021 16:53:57 -0500 Subject: [PATCH 3/7] Added realm scope to OsAccountContentViewer --- .../contentviewers/osaccount/OsAccountDataPanel.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/OsAccountDataPanel.java b/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/OsAccountDataPanel.java index dde7396040..a0e2ee7edf 100755 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/OsAccountDataPanel.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/OsAccountDataPanel.java @@ -166,7 +166,8 @@ public class OsAccountDataPanel extends JPanel { "OsAccountDataPanel_realm_name=Name", "OsAccountDataPanel_realm_address=Address", "OsAccountDataPanel_realm_confidence=Confidence", - "OsAccountDataPanel_realm_unknown=Unknown",}) + "OsAccountDataPanel_realm_unknown=Unknown", + "OsAccountDataPanel_realm_scope=Scope",}) /** * Builds the Realm Properties. @@ -185,7 +186,10 @@ public class OsAccountDataPanel extends JPanel { optional = realm.getRealmAddr(); data.addData(Bundle.OsAccountDataPanel_realm_address(), optional.isPresent() ? optional.get() : ""); - + + data.addData(Bundle.OsAccountDataPanel_realm_scope(), + realm.getScope().getName()); + data.addData(Bundle.OsAccountDataPanel_realm_confidence(), realm.getScopeConfidence().getName()); From 386e9e8cef77c1d86b19ab2fb3820f9c76371774 Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Wed, 3 Mar 2021 10:53:50 -0500 Subject: [PATCH 4/7] Inital commit of changes --- .../osaccount/Bundle.properties-MERGED | 1 + .../osaccount/OsAccountDataPanel.java | 127 ++++++++++++++++++ 2 files changed, 128 insertions(+) diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/Bundle.properties-MERGED index c313958fd5..b3b1f7816a 100755 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/Bundle.properties-MERGED @@ -11,6 +11,7 @@ OsAccountDataPanel_basic_yes=Yes OsAccountDataPanel_realm_address=Address OsAccountDataPanel_realm_confidence=Confidence OsAccountDataPanel_realm_name=Name +OsAccountDataPanel_realm_scope=Scope OsAccountDataPanel_realm_title=Realm Properties OsAccountDataPanel_realm_unknown=Unknown OsAccountViewer_title=Os Account diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/OsAccountDataPanel.java b/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/OsAccountDataPanel.java index a0e2ee7edf..0f564ea896 100755 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/OsAccountDataPanel.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/OsAccountDataPanel.java @@ -25,15 +25,26 @@ import java.awt.Insets; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; +import java.util.HashMap; import java.util.List; import static java.util.Locale.US; +import java.util.Map; import java.util.Optional; +import java.util.concurrent.ExecutionException; import javax.swing.Box; import javax.swing.JLabel; import javax.swing.JPanel; +import javax.swing.SwingWorker; +import org.openide.util.Exceptions; import org.openide.util.NbBundle.Messages; +import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.contentviewers.osaccount.SectionData.RowData; +import org.sleuthkit.datamodel.DataSource; +import org.sleuthkit.datamodel.Host; +import org.sleuthkit.datamodel.HostManager; import org.sleuthkit.datamodel.OsAccount; +import org.sleuthkit.datamodel.OsAccountAttribute; +import org.sleuthkit.datamodel.OsAccountManager; import org.sleuthkit.datamodel.OsAccountRealm; /** @@ -195,6 +206,15 @@ public class OsAccountDataPanel extends JPanel { return data; } + + private SectionData buildHostData(Host host, List attributeList) { + SectionData data = new SectionData(host.getName()); + for(OsAccountAttribute attribute: attributeList) { + data.addData(attribute.getAttributeType().getDisplayName(), attribute.getDisplayString()); + } + + return data; + } /** * Add a section title to the panel with the given title and location. @@ -316,5 +336,112 @@ public class OsAccountDataPanel extends JPanel { } } } + + private class HostFetcher extends SwingWorker { + + private final OsAccount account; + + HostFetcher(OsAccount account) { + this.account = account; + } + + @Override + protected WorkerResults doInBackground() throws Exception { + Map> hostMap = new HashMap<>(); + Map instanceMap = new HashMap<>(); + OsAccountManager osAccountManager = Case.getCurrentCase().getSleuthkitCase().getOsAccountManager(); + List hosts = osAccountManager.getHosts(account); + List attributeList = account.getOsAccountAttributes(); + + if(attributeList != null) { + if(hosts != null) { + // Organize the attributes by hostId + Map> idMap = new HashMap<>(); + for(OsAccountAttribute attribute: attributeList) { + List atList = null; + Optional optionalId = attribute.getHostId(); + Long key = null; + if(optionalId.isPresent()) { + key = optionalId.get(); + } + + atList = idMap.get(key); + + if(atList == null) { + atList = new ArrayList<>(); + idMap.put(key, atList); + } + + atList.add(attribute); + } + + HostManager hostManager = Case.getCurrentCase().getSleuthkitCase().getHostManager(); + // Add attribute lists to the hostMap + for(Host host: hosts) { + List atList = idMap.get(host.getId()); + if(atList != null) { + hostMap.put(host, atList); + } + + } + List atList = idMap.get(null); + if(atList != null) { + hostMap.put(null, atList); + } + } else { + hostMap.put(null, attributeList); + } + } + + return new WorkerResults(hostMap, instanceMap); + } + + @Override + protected void done() { + WorkerResults results = null; + + try { + results = get(); + } catch (InterruptedException ex) { + Exceptions.printStackTrace(ex); + } catch (ExecutionException ex) { + Exceptions.printStackTrace(ex); + } + + if(results != null) { + List data = new ArrayList<>(); + data.add(buildBasicProperties(account)); + Map> hostDataMap = results.getAttributeMap(); + if(hostDataMap != null && !hostDataMap.isEmpty()) { + hostDataMap.forEach((K,V)-> data.add(buildHostData(K,V))); + } + + OsAccountRealm realm = account.getRealm(); + if (realm != null) { + data.add(buildRealmProperties(realm)); + } + + addDataComponents(data); + } + } + } + + private final class WorkerResults { + private final Map> attributeMap; + private final Map instanceMap; + + WorkerResults(Map> attributeMap, Map instanceMap) { + this.attributeMap = attributeMap; + this.instanceMap = instanceMap; + } + + Map> getAttributeMap() { + return attributeMap; + } + + Map getDataSourceMap() { + return instanceMap; + } + } } From c0b9d5f49cc3a6fb68a52dcabb3fc9a65bba824e Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Fri, 5 Mar 2021 15:18:26 -0500 Subject: [PATCH 5/7] Finished OsAccountContentViewer changes --- .../osaccount/OsAccountDataPanel.java | 172 ++++++++++++------ .../recentactivity/ExtractRegistry.java | 3 + 2 files changed, 118 insertions(+), 57 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/OsAccountDataPanel.java b/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/OsAccountDataPanel.java index 0f564ea896..2ea3989b44 100755 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/OsAccountDataPanel.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/OsAccountDataPanel.java @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.contentviewers.osaccount; +import java.awt.BorderLayout; import java.awt.Font; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; @@ -31,19 +32,20 @@ import static java.util.Locale.US; import java.util.Map; import java.util.Optional; import java.util.concurrent.ExecutionException; +import java.util.logging.Level; +import java.util.logging.Logger; import javax.swing.Box; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.SwingWorker; -import org.openide.util.Exceptions; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.contentviewers.osaccount.SectionData.RowData; import org.sleuthkit.datamodel.DataSource; import org.sleuthkit.datamodel.Host; -import org.sleuthkit.datamodel.HostManager; import org.sleuthkit.datamodel.OsAccount; import org.sleuthkit.datamodel.OsAccountAttribute; +import org.sleuthkit.datamodel.OsAccountInstance; import org.sleuthkit.datamodel.OsAccountManager; import org.sleuthkit.datamodel.OsAccountRealm; @@ -53,12 +55,15 @@ import org.sleuthkit.datamodel.OsAccountRealm; public class OsAccountDataPanel extends JPanel { private static final long serialVersionUID = 1L; + final private static Logger logger = Logger.getLogger(OsAccountDataPanel.class.getName()); private static final int KEY_COLUMN = 0; private static final int VALUE_COLUMN = 1; - + private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("MMM dd yyyy", US); + private PanelDataFetcher dataFetcher = null; + // Panel constructor. OsAccountDataPanel() { initialize(); @@ -79,19 +84,19 @@ public class OsAccountDataPanel extends JPanel { */ void setOsAccount(OsAccount account) { removeAll(); + revalidate(); if (account != null) { - List data = new ArrayList<>(); - data.add(buildBasicProperties(account)); + setLayout(new BorderLayout()); + add(new JLabel("Loading OsAccount Data..."), BorderLayout.NORTH); - OsAccountRealm realm = account.getRealm(); - if (realm != null) { - data.add(buildRealmProperties(realm)); + if (dataFetcher != null && !dataFetcher.isDone()) { + dataFetcher.cancel(true); } - addDataComponents(data); + dataFetcher = new PanelDataFetcher(account); + dataFetcher.execute(); } - revalidate(); } /** @@ -133,8 +138,7 @@ public class OsAccountDataPanel extends JPanel { "OsAccountDataPanel_basic_address=Address", "OsAccountDataPanel_basic_admin=Administrator", "OsAccountDataPanel_basic_type=Type", - "OsAccountDataPanel_basic_creationDate=Creation Date", - }) + "OsAccountDataPanel_basic_creationDate=Creation Date",}) /** * Returns the data for the Basic Properties section of the panel. @@ -160,12 +164,11 @@ public class OsAccountDataPanel extends JPanel { data.addData(Bundle.OsAccountDataPanel_basic_admin(), getIsAdminValue(account.isAdmin())); data.addData(Bundle.OsAccountDataPanel_basic_type(), account.getOsAccountType().getName()); - + Optional crTime = account.getCreationTime(); - if(crTime.isPresent()) { + if (crTime.isPresent()) { data.addData(Bundle.OsAccountDataPanel_basic_creationDate(), DATE_FORMAT.format(new Date(crTime.get() * 1000))); - } - else { + } else { data.addData(Bundle.OsAccountDataPanel_basic_creationDate(), ""); } @@ -197,22 +200,22 @@ public class OsAccountDataPanel extends JPanel { optional = realm.getRealmAddr(); data.addData(Bundle.OsAccountDataPanel_realm_address(), optional.isPresent() ? optional.get() : ""); - + data.addData(Bundle.OsAccountDataPanel_realm_scope(), - realm.getScope().getName()); - + realm.getScope().getName()); + data.addData(Bundle.OsAccountDataPanel_realm_confidence(), realm.getScopeConfidence().getName()); return data; } - + private SectionData buildHostData(Host host, List attributeList) { SectionData data = new SectionData(host.getName()); - for(OsAccountAttribute attribute: attributeList) { + for (OsAccountAttribute attribute : attributeList) { data.addData(attribute.getAttributeType().getDisplayName(), attribute.getDisplayString()); } - + return data; } @@ -336,15 +339,23 @@ public class OsAccountDataPanel extends JPanel { } } } - - private class HostFetcher extends SwingWorker { + + /** + * A SwingWorker to gather the data for the content panel. + */ + private class PanelDataFetcher extends SwingWorker { private final OsAccount account; - - HostFetcher(OsAccount account) { + + /** + * Construct a new worker for the given account. + * + * @param account + */ + PanelDataFetcher(OsAccount account) { this.account = account; } - + @Override protected WorkerResults doInBackground() throws Exception { Map> hostMap = new HashMap<>(); @@ -352,68 +363,79 @@ public class OsAccountDataPanel extends JPanel { OsAccountManager osAccountManager = Case.getCurrentCase().getSleuthkitCase().getOsAccountManager(); List hosts = osAccountManager.getHosts(account); List attributeList = account.getOsAccountAttributes(); - - if(attributeList != null) { - if(hosts != null) { + + if (attributeList != null) { + if (hosts != null) { // Organize the attributes by hostId Map> idMap = new HashMap<>(); - for(OsAccountAttribute attribute: attributeList) { + for (OsAccountAttribute attribute : attributeList) { List atList = null; Optional optionalId = attribute.getHostId(); Long key = null; - if(optionalId.isPresent()) { - key = optionalId.get(); + if (optionalId.isPresent()) { + key = optionalId.get(); } atList = idMap.get(key); - if(atList == null) { + if (atList == null) { atList = new ArrayList<>(); idMap.put(key, atList); } atList.add(attribute); } - - HostManager hostManager = Case.getCurrentCase().getSleuthkitCase().getHostManager(); + // Add attribute lists to the hostMap - for(Host host: hosts) { + for (Host host : hosts) { List atList = idMap.get(host.getId()); - if(atList != null) { + if (atList != null) { hostMap.put(host, atList); } - + } List atList = idMap.get(null); - if(atList != null) { + if (atList != null) { hostMap.put(null, atList); } + + // Store both the host and the dataSource so that we get + // all of the calls to the db done in the thread. + for (OsAccountInstance instance : account.getOsAccountInstances()) { + instanceMap.put(instance.getDataSource().getHost(), instance.getDataSource()); + } + } else { hostMap.put(null, attributeList); } } - + return new WorkerResults(hostMap, instanceMap); } - + @Override protected void done() { WorkerResults results = null; - + try { - results = get(); - } catch (InterruptedException ex) { - Exceptions.printStackTrace(ex); - } catch (ExecutionException ex) { - Exceptions.printStackTrace(ex); + if (this.isCancelled()) { + return; + } else { + results = get(); + } + } catch (ExecutionException | InterruptedException ex) { + logger.log(Level.SEVERE, String.format("Failed to retrieve data for OsAccount (%d)", account.getId()), ex); } - - if(results != null) { + + if (results != null) { + removeAll(); + setLayout(new GridBagLayout()); + List data = new ArrayList<>(); data.add(buildBasicProperties(account)); Map> hostDataMap = results.getAttributeMap(); - if(hostDataMap != null && !hostDataMap.isEmpty()) { - hostDataMap.forEach((K,V)-> data.add(buildHostData(K,V))); + if (hostDataMap != null && !hostDataMap.isEmpty()) { + hostDataMap.forEach((K, V) -> data.add(buildHostData(K, V))); } OsAccountRealm realm = account.getRealm(); @@ -421,24 +443,60 @@ public class OsAccountDataPanel extends JPanel { data.add(buildRealmProperties(realm)); } + Map instanceMap = results.getDataSourceMap(); + if (!instanceMap.isEmpty()) { + SectionData instanceSection = new SectionData("Instances"); + instanceMap.forEach((K, V) -> instanceSection.addData(K.getName(), V.getName())); + + data.add(instanceSection); + } + addDataComponents(data); + + revalidate(); + repaint(); } - } + } } - + + /** + * Helper class for PanelDataFetcher that wraps the returned data needed for + * the panel. + */ private final class WorkerResults { + private final Map> attributeMap; private final Map instanceMap; - + + /** + * Construct a new WorkerResult object. + * + * @param attributeMap Maps the OsAccountAttributes to the host they + * belong with. + * @param instanceMap A map of data to display OsAccount instance + * information. + */ WorkerResults(Map> attributeMap, Map instanceMap) { this.attributeMap = attributeMap; this.instanceMap = instanceMap; } - + + /** + * Returns a map of OsAccountAttributes that belong to a specific Host. + * There maybe a null key in the map which represents properties that + * are not host specific. + * + * @return OsAccountAttribute map. + */ Map> getAttributeMap() { return attributeMap; } - + + /** + * A map of the instance data for the OsAccount. + * + * @return + */ Map getDataSourceMap() { return instanceMap; } diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java index 1b1661c82e..f464ed0b63 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java @@ -102,6 +102,7 @@ import org.sleuthkit.datamodel.Host; import org.sleuthkit.datamodel.HostManager; import org.sleuthkit.datamodel.OsAccount; import org.sleuthkit.datamodel.OsAccountAttribute; +import org.sleuthkit.datamodel.OsAccountInstance; import org.sleuthkit.datamodel.OsAccountManager; import org.sleuthkit.datamodel.OsAccountRealm; import org.sleuthkit.datamodel.ReadContentInputStream.ReadContentInputStreamException; @@ -1166,6 +1167,7 @@ class ExtractRegistry extends Extract { //add remaining userinfos as accounts; for (Map userInfo : userInfoMap.values()) { OsAccount osAccount = accountMgr.createWindowsAccount(userInfo.get(SID_KEY), null, null, host, OsAccountRealm.RealmScope.UNKNOWN); + accountMgr.createOsAccountInstance(osAccount, (DataSource)dataSource, OsAccountInstance.OsAccountInstanceType.PERFORMED_ACTION_ON); updateOsAccount(osAccount, userInfo, groupMap.get(userInfo.get(SID_KEY)), regAbstractFile); } @@ -2214,6 +2216,7 @@ class ExtractRegistry extends Extract { OsAccount osAccount; if (!optional.isPresent()) { osAccount = accountMgr.createWindowsAccount(sid, userName != null && userName.isEmpty() ? null : userName, null, host, OsAccountRealm.RealmScope.UNKNOWN); + accountMgr.createOsAccountInstance(osAccount, (DataSource)dataSource, OsAccountInstance.OsAccountInstanceType.PERFORMED_ACTION_ON); } else { osAccount = optional.get(); if (userName != null && !userName.isEmpty()) { From 166fda3ff3aa9dc8008eed3c8ce51e44e2a2e136 Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Mon, 8 Mar 2021 14:45:26 -0500 Subject: [PATCH 6/7] Removed the admin property from the content viewer --- .../osaccount/OsAccountDataPanel.java | 26 ------------------- 1 file changed, 26 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/OsAccountDataPanel.java b/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/OsAccountDataPanel.java index dde7396040..ab440995eb 100755 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/OsAccountDataPanel.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/OsAccountDataPanel.java @@ -146,8 +146,6 @@ public class OsAccountDataPanel extends JPanel { data.addData(Bundle.OsAccountDataPanel_basic_address(), account.getName() == null || account.getName().isEmpty() ? "" : account.getName()); - data.addData(Bundle.OsAccountDataPanel_basic_admin(), getIsAdminValue(account.isAdmin())); - data.addData(Bundle.OsAccountDataPanel_basic_type(), account.getOsAccountType().getName()); Optional crTime = account.getCreationTime(); @@ -289,28 +287,4 @@ public class OsAccountDataPanel extends JPanel { return constraints; } - - @Messages({ - "OsAccountDataPanel_basic_yes=Yes", - "OsAccountDataPanel_basic_no=No", - "OsAccountDataPanel_basic_unknown=Unknown",}) - /** - * Return a string representation of the isAdmin status for OsAccounts. - * - * @param isAdmin Admin state for the OsAccount - * - * @return String representation of the admin state. - */ - private String getIsAdminValue(Optional isAdmin) { - if (!isAdmin.isPresent()) { - return Bundle.OsAccountDataPanel_basic_unknown(); - } else { - if (isAdmin.get()) { - return Bundle.OsAccountDataPanel_basic_yes(); - } else { - return Bundle.OsAccountDataPanel_basic_no(); - } - } - } - } From 747a5e39b296927d74d597ae12301dab7e34e645 Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Mon, 8 Mar 2021 14:50:02 -0500 Subject: [PATCH 7/7] Updated OsAccount content viewer proeprties file --- .../autopsy/contentviewers/osaccount/Bundle.properties-MERGED | 3 --- 1 file changed, 3 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/Bundle.properties-MERGED index c313958fd5..33ac7b64d3 100755 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/Bundle.properties-MERGED @@ -3,11 +3,8 @@ OsAccountDataPanel_basic_admin=Administrator OsAccountDataPanel_basic_creationDate=Creation Date OsAccountDataPanel_basic_fullname=Full Name OsAccountDataPanel_basic_login=Login -OsAccountDataPanel_basic_no=No OsAccountDataPanel_basic_title=Basic Properties OsAccountDataPanel_basic_type=Type -OsAccountDataPanel_basic_unknown=Unknown -OsAccountDataPanel_basic_yes=Yes OsAccountDataPanel_realm_address=Address OsAccountDataPanel_realm_confidence=Confidence OsAccountDataPanel_realm_name=Name