Autopsy 4.22.1
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 */
19package org.sleuthkit.autopsy.contentviewers.osaccount;
20
21import java.awt.BorderLayout;
22import java.awt.Font;
23import java.awt.GridBagConstraints;
24import java.awt.GridBagLayout;
25import java.awt.Insets;
26import java.text.SimpleDateFormat;
27import java.util.ArrayList;
28import java.util.Date;
29import java.util.HashMap;
30import java.util.List;
31import static java.util.Locale.US;
32import java.util.Map;
33import java.util.Optional;
34import java.util.concurrent.ExecutionException;
35import java.util.logging.Level;
36import java.util.logging.Logger;
37import javax.swing.Box;
38import javax.swing.JLabel;
39import javax.swing.JPanel;
40import javax.swing.SwingWorker;
41import javax.swing.UIManager;
42import javax.swing.border.EmptyBorder;
43import org.openide.util.NbBundle.Messages;
44import org.sleuthkit.autopsy.casemodule.Case;
45import org.sleuthkit.autopsy.contentviewers.layout.ContentViewerDefaults;
46import org.sleuthkit.autopsy.contentviewers.osaccount.Section.SectionData;
47import org.sleuthkit.autopsy.contentviewers.osaccount.Section.RowData;
48import org.sleuthkit.autopsy.coreutils.TimeZoneUtils;
49import org.sleuthkit.datamodel.BlackboardAttribute;
50import org.sleuthkit.datamodel.Content;
51import org.sleuthkit.datamodel.DataSource;
52import org.sleuthkit.datamodel.Host;
53import org.sleuthkit.datamodel.OsAccount;
54import org.sleuthkit.datamodel.OsAccount.OsAccountAttribute;
55import org.sleuthkit.datamodel.OsAccountInstance;
56import org.sleuthkit.datamodel.OsAccountManager;
57import org.sleuthkit.datamodel.OsAccountRealm;
58import org.sleuthkit.datamodel.SleuthkitCase;
59
63public 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);
76 private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("MMM dd yyyy", US);
77
79
80 // Panel constructor.
81 OsAccountDataPanel() {
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)
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}
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
static String getFormattedTime(long epochTime)

Copyright © 2012-2024 Sleuth Kit Labs. Generated on:
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.