Autopsy  4.21.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
OsAccountDataPanel.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2021 Basis Technology Corp.
5  * Contact: carrier <at> sleuthkit <dot> org
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 package org.sleuthkit.autopsy.contentviewers.osaccount;
20 
21 import java.awt.BorderLayout;
22 import java.awt.Font;
23 import java.awt.GridBagConstraints;
24 import java.awt.GridBagLayout;
25 import java.awt.Insets;
26 import java.text.SimpleDateFormat;
27 import java.util.ArrayList;
28 import java.util.Date;
29 import java.util.HashMap;
30 import java.util.List;
31 import static java.util.Locale.US;
32 import java.util.Map;
33 import java.util.Optional;
34 import java.util.concurrent.ExecutionException;
35 import java.util.logging.Level;
36 import java.util.logging.Logger;
37 import javax.swing.Box;
38 import javax.swing.JLabel;
39 import javax.swing.JPanel;
40 import javax.swing.SwingWorker;
41 import javax.swing.UIManager;
42 import javax.swing.border.EmptyBorder;
43 import org.openide.util.NbBundle.Messages;
49 import org.sleuthkit.datamodel.BlackboardAttribute;
50 import org.sleuthkit.datamodel.Content;
51 import org.sleuthkit.datamodel.DataSource;
52 import org.sleuthkit.datamodel.Host;
53 import org.sleuthkit.datamodel.OsAccount;
54 import org.sleuthkit.datamodel.OsAccount.OsAccountAttribute;
55 import org.sleuthkit.datamodel.OsAccountInstance;
56 import org.sleuthkit.datamodel.OsAccountManager;
57 import org.sleuthkit.datamodel.OsAccountRealm;
58 import org.sleuthkit.datamodel.SleuthkitCase;
59 
63 public class OsAccountDataPanel extends JPanel {
64 
65  private static final long serialVersionUID = 1L;
66  final private static Logger logger = Logger.getLogger(OsAccountDataPanel.class.getName());
67 
68  private static final int KEY_COLUMN = 0;
69  private static final int VALUE_COLUMN = 1;
70 
71  private final static Insets FIRST_HEADER_INSETS = new Insets(0, 0, 0, 0);
72  private final static Insets HEADER_INSETS = new Insets(ContentViewerDefaults.getSectionSpacing(), 0, ContentViewerDefaults.getLineSpacing(), 0);
76  private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("MMM dd yyyy", US);
77 
78  private PanelDataFetcher dataFetcher = null;
79 
80  // Panel constructor.
82  initialize();
83  }
84 
88  private void initialize() {
89  this.setLayout(new GridBagLayout());
90  this.setBorder(new EmptyBorder(ContentViewerDefaults.getPanelInsets()));
91  }
92 
99  void setOsAccountId(Long osAccountId) {
100  removeAll();
101  revalidate();
102 
103  if (osAccountId != null) {
104  setLayout(new BorderLayout());
105  add(new JLabel("Loading OsAccount Data..."), BorderLayout.NORTH);
106 
107  if (dataFetcher != null && !dataFetcher.isDone()) {
108  dataFetcher.cancel(true);
109  }
110 
111  dataFetcher = new PanelDataFetcher(osAccountId);
112  dataFetcher.execute();
113  }
114  }
115 
116  void setOsAccount(OsAccount account) {
117  removeAll();
118  revalidate();
119 
120  if (account != null) {
121  setLayout(new BorderLayout());
122  add(new JLabel("Loading OsAccount Data..."), BorderLayout.NORTH);
123 
124  if (dataFetcher != null && !dataFetcher.isDone()) {
125  dataFetcher.cancel(true);
126  }
127 
128  dataFetcher = new PanelDataFetcher(account);
129  dataFetcher.execute();
130  }
131  }
132 
139  private void addDataComponents(List<Section> panelData) {
140  int rowCnt = 0;
141 
142  for (Section section : panelData) {
143  addTitle(section.getTitle(), rowCnt++);
144  for (SectionData data : section) {
145  String subtitle = data.getTitle();
146  if (subtitle != null) {
147  addSubTitle(data.getTitle(), rowCnt++);
148  }
149 
150  for (RowData<String, String> rowData : data) {
151  String key = rowData.getKey();
152  String value = rowData.getValue();
153 
154  if (value != null) {
155  addPropertyName(key, rowCnt);
156  addPropertyValue(value, rowCnt++);
157  } else {
158  addLabel(key, rowCnt++);
159  }
160  }
161 
162  }
163  }
164 
165  // Generate the constraints for a Vertical Glue to fill the space, if
166  // any at the bottom of the panel.
167  GridBagConstraints constraints = new GridBagConstraints();
168  constraints.gridx = 0;
169  constraints.gridy = rowCnt;
170  constraints.gridwidth = 2;
171  constraints.fill = GridBagConstraints.BOTH;
172  constraints.weightx = 1;
173  constraints.weighty = 1;
174  add(Box.createVerticalGlue(), constraints);
175  }
176 
177  @Messages({
178  "OsAccountDataPanel_basic_title=Basic Properties",
179  "OsAccountDataPanel_basic_login=Login",
180  "OsAccountDataPanel_basic_fullname=Full Name",
181  "OsAccountDataPanel_basic_address=Address",
182  "OsAccountDataPanel_basic_admin=Administrator",
183  "OsAccountDataPanel_basic_type=Type",
184  "OsAccountDataPanel_basic_creationDate=Creation Date",
185  "OsAccountDataPanel_basic_objId=Object ID"})
186 
194  private Section buildBasicProperties(OsAccount account) {
195  Section section = new Section(Bundle.OsAccountDataPanel_basic_title());
196 
197  SectionData data = new SectionData();
198 
199  Optional<String> optional = account.getLoginName();
200  data.addData(Bundle.OsAccountDataPanel_basic_login(),
201  optional.isPresent() ? optional.get() : "");
202 
203  optional = account.getFullName();
204  data.addData(Bundle.OsAccountDataPanel_basic_fullname(),
205  optional.isPresent() ? optional.get() : "");
206 
207  data.addData(Bundle.OsAccountDataPanel_basic_address(),
208  account.getName() == null || account.getName().isEmpty() ? "" : account.getName());
209 
210  data.addData(Bundle.OsAccountDataPanel_basic_type(),
211  account.getOsAccountType().isPresent() ? account.getOsAccountType().get().getName() : "");
212 
213  Optional<Long> crTime = account.getCreationTime();
214  data.addData(Bundle.OsAccountDataPanel_basic_creationDate(), crTime.isPresent() ? TimeZoneUtils.getFormattedTime(crTime.get()) : "");
215 
216  data.addData(Bundle.OsAccountDataPanel_basic_objId(), Long.toString(account.getId()));
217 
218  section.addSectionData(data);
219  return section;
220  }
221 
222  @Messages({
223  "OsAccountDataPanel_realm_title=Realm Properties",
224  "OsAccountDataPanel_realm_name=Name",
225  "OsAccountDataPanel_realm_address=Address",
226  "OsAccountDataPanel_realm_confidence=Confidence",
227  "OsAccountDataPanel_realm_unknown=Unknown",
228  "OsAccountDataPanel_realm_scope=Scope",})
229 
237  private Section buildRealmProperties(OsAccountRealm realm) {
238  Section section = new Section(Bundle.OsAccountDataPanel_realm_title());
239  SectionData data = new SectionData();
240 
241  String realmName = realm.getRealmNames().isEmpty() ? Bundle.OsAccountDataPanel_realm_unknown() : realm.getRealmNames().get(0);
242  data.addData(Bundle.OsAccountDataPanel_realm_name(), realmName);
243 
244  Optional<String> optional = realm.getRealmAddr();
245  data.addData(Bundle.OsAccountDataPanel_realm_address(),
246  optional.isPresent() ? optional.get() : "");
247 
248  data.addData(Bundle.OsAccountDataPanel_realm_scope(),
249  realm.getScope().getName());
250 
251  data.addData(Bundle.OsAccountDataPanel_realm_confidence(),
252  realm.getScopeConfidence().getName());
253 
254  section.addSectionData(data);
255  return section;
256  }
257 
258  @Messages({
259  "# {0} - hostName",
260  "OsAccountDataPanel_host_section_title={0} Details",
261  "OsAccountDataPanel_host_count_title=Login Count",
262  "OsAccountDataPanel_data_accessed_title=Last Login",
263  "OsAccountDataPanel_administrator_title=Administrator"
264  })
265  private Section buildHostData(Host host, Map<DataSource, List<OsAccountAttribute>> attributeDataSourceMap) {
266  String sectionTitle = "Global Host Details";
267 
268  if (host != null) {
269  sectionTitle = Bundle.OsAccountDataPanel_host_section_title(host.getName());
270  }
271 
272  Section section = new Section(sectionTitle);
273 
274  for (DataSource dataSource : attributeDataSourceMap.keySet()) {
275  List<OsAccountAttribute> attributeList = attributeDataSourceMap.get(dataSource);
276  SectionData data = new SectionData((attributeDataSourceMap.size() > 1 && dataSource != null) ? dataSource.getName() : null);
277  if (attributeList != null) {
278  for (OsAccountAttribute attribute : attributeList) {
279  String displayName = attribute.getAttributeType().getDisplayName();
280  String value = attribute.getDisplayString();
281 
282  if (attribute.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COUNT.getTypeID()) {
283  displayName = Bundle.OsAccountDataPanel_host_count_title();
284  } else if (attribute.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_IS_ADMIN.getTypeID()) {
285  displayName = Bundle.OsAccountDataPanel_administrator_title();
286  if (attribute.getValueInt() == 0) {
287  value = "False";
288  } else {
289  value = "True";
290  }
291  } else if (attribute.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID()) {
292  displayName = Bundle.OsAccountDataPanel_data_accessed_title();
293  }
294 
295  data.addData(displayName, value);
296  }
297  } else {
298  data.addData("No details available", null);
299  }
300 
301  section.addSectionData(data);
302  }
303 
304  return section;
305  }
306 
313  private void addTitle(String title, int row) {
314  JLabel label = new JLabel(title);
315  // Make the title bold.
316  label.setFont(ContentViewerDefaults.getHeaderFont());
317  add(label, getTitleContraints(row));
318  }
319 
320  private void addSubTitle(String title, int row) {
321  JLabel label = new JLabel(title);
322  // Make the title bold.
323  label.setFont(label.getFont().deriveFont(Font.BOLD));
324  add(label, getSubtitleContraints(row));
325  }
326 
333  private void addPropertyName(String key, int row) {
334  JLabel label = new JLabel(key + ":");
335  add(label, getPropertyNameContraints(row));
336  }
337 
344  private void addLabel(String text, int row) {
345  JLabel label = new JLabel(text);
346  add(label, getPropertyNameContraints(row));
347  addPropertyValue("", row);
348  }
349 
356  private void addPropertyValue(String value, int row) {
357  JLabel label = new JLabel(value);
358  add(label, getPropertyValueContraints(row));
359  }
360 
368  private GridBagConstraints getTitleContraints(int row) {
369  GridBagConstraints constraints = new GridBagConstraints();
370 
371  constraints.gridx = 0;
372  constraints.gridy = row;
373  constraints.gridwidth = 2; // The title goes across the other columns
374  constraints.gridheight = 1;
375  constraints.anchor = GridBagConstraints.NORTHWEST;
376  constraints.fill = GridBagConstraints.HORIZONTAL;
377  constraints.weightx = 1;
378  constraints.insets = (row == 0)
379  ? FIRST_HEADER_INSETS
380  : HEADER_INSETS;
381 
382  return constraints;
383  }
384 
385  private GridBagConstraints getSubtitleContraints(int row) {
386  GridBagConstraints constraints = new GridBagConstraints();
387 
388  constraints.gridx = 0;
389  constraints.gridy = row;
390  constraints.gridwidth = 2; // The title goes across the other columns
391  constraints.gridheight = 1;
392  constraints.anchor = GridBagConstraints.NORTHWEST;
393  constraints.fill = GridBagConstraints.HORIZONTAL;
394  constraints.weightx = 1;
395  constraints.insets = SUBHEADER_COLUMN_INSETS;
396 
397  return constraints;
398  }
399 
407  private GridBagConstraints getPropertyNameContraints(int row) {
408  GridBagConstraints constraints = new GridBagConstraints();
409 
410  constraints.gridx = KEY_COLUMN;
411  constraints.gridy = row;
412  constraints.gridwidth = 1; // The title goes across the other columns
413  constraints.gridheight = 1;
414  constraints.anchor = GridBagConstraints.WEST;
415  constraints.insets = KEY_COLUMN_INSETS;
416 
417  return constraints;
418  }
419 
427  private GridBagConstraints getPropertyValueContraints(int row) {
428  GridBagConstraints constraints = new GridBagConstraints();
429 
430  constraints.gridx = VALUE_COLUMN;
431  constraints.gridy = row;
432  constraints.gridwidth = 1; // The title goes across the other columns
433  constraints.gridheight = 1;
434  constraints.fill = GridBagConstraints.HORIZONTAL;
435  constraints.insets = VALUE_COLUMN_INSETS;
436  constraints.weightx = 1;
437 
438  return constraints;
439  }
440 
444  private class PanelDataFetcher extends SwingWorker<WorkerResults, Void> {
445 
446  private final Long accountId;
447  private OsAccount account;
448 
454  PanelDataFetcher(Long accountId) {
455  this.accountId = accountId;
456  this.account = null;
457  }
458 
459  PanelDataFetcher(OsAccount account) {
460  this.account = account;
461  this.accountId = null;
462  }
463 
464  @Override
465  protected WorkerResults doInBackground() throws Exception {
466  Map<Host, Map<DataSource, List<OsAccountAttribute>>> hostMap = new HashMap<>();
467  Map<Host, DataSource> instanceMap = new HashMap<>();
468  SleuthkitCase skCase = Case.getCurrentCase().getSleuthkitCase();
469  OsAccountManager osAccountManager = skCase.getOsAccountManager();
470 
471  if (account == null) {
472  account = osAccountManager.getOsAccountByObjectId(accountId);
473  }
474 
475  OsAccountRealm realm = skCase.getOsAccountRealmManager().getRealmByRealmId(account.getRealmId());
476 
477  List<Host> hosts = osAccountManager.getHosts(account);
478  List<OsAccountAttribute> attributeList = account.getExtendedOsAccountAttributes();
479 
480  // Organize the attributes by hostId
481  Map<Long, Map<DataSource, List<OsAccountAttribute>>> idMap2 = new HashMap<>();
482  if (attributeList != null) {
483  for (OsAccountAttribute attribute : attributeList) {
484 
485  Long key = attribute.getHostId().orElse(null);
486  Long sourceID = attribute.getSourceObjectId().orElse(null);
487  DataSource dataSource = null;
488 
489  if (sourceID != null) {
490  Content sourceContent = skCase.getContentById(sourceID);
491  if (sourceContent != null) {
492  dataSource = (DataSource) sourceContent.getDataSource();
493  }
494  }
495 
496  Map<DataSource, List<OsAccountAttribute>> atMap = idMap2.get(key);
497  if (atMap == null) {
498  atMap = new HashMap<>();
499  idMap2.put(key, atMap);
500  }
501 
502  List<OsAccountAttribute> mapList = atMap.get(dataSource);
503  if (mapList == null) {
504  mapList = new ArrayList<>();
505  atMap.put(dataSource, mapList);
506  }
507  mapList.add(attribute);
508  }
509  }
510 
511  // Add attribute lists to the hostMap
512  if (hosts != null) {
513  for (Host host : hosts) {
514  hostMap.put(host, idMap2.get(host.getHostId()));
515  }
516  }
517 
518  hostMap.put(null, idMap2.get(null));
519  Map<DataSource, List<OsAccountAttribute>> atMap = idMap2.get(null);
520  if (atMap != null) {
521  hostMap.put(null, atMap);
522  }
523 
524  // Store both the host and the dataSource so that we get
525  // all of the calls to the db done in the thread.
526  for (OsAccountInstance instance : account.getOsAccountInstances()) {
527  instanceMap.put(instance.getDataSource().getHost(), instance.getDataSource());
528  }
529 
530  return new WorkerResults(hostMap, instanceMap, realm);
531  }
532 
533  @Override
534  protected void done() {
535  WorkerResults results = null;
536 
537  try {
538  if (this.isCancelled()) {
539  return;
540  } else {
541  results = get();
542  }
543  } catch (ExecutionException | InterruptedException ex) {
544  logger.log(Level.SEVERE, String.format("Failed to retrieve data for OsAccount (%d)", account.getId()), ex);
545  }
546 
547  if (results != null) {
548  removeAll();
549  setLayout(new GridBagLayout());
550 
551  List<Section> data = new ArrayList<>();
552  data.add(buildBasicProperties(account));
553  Map<Host, Map<DataSource, List<OsAccountAttribute>>> hostDataMap = results.getAttributeMap();
554  if (hostDataMap != null && !hostDataMap.isEmpty()) {
555  hostDataMap.entrySet().stream().forEach(pair -> {
556  if (pair.getKey() != null && pair.getValue() != null) {
557  data.add(buildHostData(pair.getKey(), pair.getValue()));
558  }
559  });
560  }
561 
562  OsAccountRealm realm = results.getRealm();
563  if (realm != null) {
564  data.add(buildRealmProperties(realm));
565  }
566 
567 // Removing the instance section for now. Leaving code here for
568 // future use.
569 // Map<Host, DataSource> instanceMap = results.getDataSourceMap();
570 // if (!instanceMap.isEmpty()) {
571 // SectionData instanceSection = new SectionData("Instances");
572 // instanceMap.forEach((K, V) -> instanceSection.addData(K.getName(), V.getName()));
573 //
574 // data.add(instanceSection);
575 // }
576  addDataComponents(data);
577 
578  revalidate();
579  repaint();
580  }
581  }
582  }
583 
588  private final class WorkerResults {
589 
590  private final Map<Host, Map<DataSource, List<OsAccountAttribute>>> attributeMap;
591  private final Map<Host, DataSource> instanceMap;
592  private final OsAccountRealm realm;
593 
602  WorkerResults(Map<Host, Map<DataSource, List<OsAccountAttribute>>> attributeMap, Map<Host, DataSource> instanceMap, OsAccountRealm realm) {
603  this.attributeMap = attributeMap;
604  this.instanceMap = instanceMap;
605  this.realm = realm;
606  }
607 
615  Map<Host, Map<DataSource, List<OsAccountAttribute>>> getAttributeMap() {
616  return attributeMap;
617  }
618 
624  Map<Host, DataSource> getDataSourceMap() {
625  return instanceMap;
626  }
627 
628  OsAccountRealm getRealm() {
629  return realm;
630  }
631  }
632 }
static String getFormattedTime(long epochTime)
final Map< Host, Map< DataSource, List< OsAccountAttribute > > > attributeMap
Section buildHostData(Host host, Map< DataSource, List< OsAccountAttribute >> attributeDataSourceMap)
synchronized static Logger getLogger(String name)
Definition: Logger.java:124

Copyright © 2012-2022 Basis Technology. Generated on: Tue Feb 6 2024
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.