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 33ac7b64d3..266168e4ad 100755 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/osaccount/Bundle.properties-MERGED @@ -8,6 +8,7 @@ OsAccountDataPanel_basic_type=Type 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 e478cc27a3..f5f07d658b 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; @@ -25,15 +26,27 @@ 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 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.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.OsAccount; +import org.sleuthkit.datamodel.OsAccountAttribute; +import org.sleuthkit.datamodel.OsAccountInstance; +import org.sleuthkit.datamodel.OsAccountManager; import org.sleuthkit.datamodel.OsAccountRealm; /** @@ -42,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(); @@ -68,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(); } /** @@ -122,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. @@ -147,12 +162,11 @@ public class OsAccountDataPanel extends JPanel { account.getName() == null || account.getName().isEmpty() ? "" : account.getName()); 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(), ""); } @@ -184,16 +198,25 @@ 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) { + data.addData(attribute.getAttributeType().getDisplayName(), attribute.getDisplayString()); + } + + return data; + } + /** * Add a section title to the panel with the given title and location. * @@ -291,4 +314,166 @@ public class OsAccountDataPanel extends JPanel { return constraints; } + + /** + * A SwingWorker to gather the data for the content panel. + */ + private class PanelDataFetcher extends SwingWorker { + + private final 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<>(); + 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); + } + + // 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); + } + + // 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 { + 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) { + 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))); + } + + OsAccountRealm realm = account.getRealm(); + if (realm != null) { + 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 46504c1886..8d215ccf6e 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.LAUNCHED); 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.LAUNCHED); } else { osAccount = optional.get(); if (userName != null && !userName.isEmpty()) { @@ -2369,16 +2372,14 @@ class ExtractRegistry extends Extract { } } - String settingString = getSettingsFromMap(ACCOUNT_SETTINGS_FLAGS, userInfo); + String settingString = getSettingsFromMap(PASSWORD_SETTINGS_FLAGS, userInfo); if (!settingString.isEmpty()) { - settingString = settingString.substring(0, settingString.length() - 2); attributes.add(createOsAccountAttribute(ATTRIBUTE_TYPE.TSK_PASSWORD_SETTINGS, settingString, osAccount, host, regFile)); } settingString = getSettingsFromMap(ACCOUNT_SETTINGS_FLAGS, userInfo); if (!settingString.isEmpty()) { - settingString = settingString.substring(0, settingString.length() - 2); attributes.add(createOsAccountAttribute(ATTRIBUTE_TYPE.TSK_ACCOUNT_SETTINGS, settingString, osAccount, host, regFile)); }