Autopsy  4.19.1
Graphical digital forensics platform for The Sleuth Kit and other tools.
OsAccounts.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.datamodel;
20 
21 import java.beans.PropertyChangeEvent;
22 import java.beans.PropertyChangeListener;
23 import java.lang.ref.WeakReference;
24 import java.text.SimpleDateFormat;
25 import java.util.ArrayList;
26 import java.util.Arrays;
27 import java.util.Collections;
28 import java.util.EnumSet;
29 import java.util.List;
30 import java.util.Optional;
31 import java.util.logging.Level;
32 import java.util.stream.Collectors;
33 import javax.swing.Action;
34 import javax.swing.SwingUtilities;
35 import org.apache.commons.lang3.StringUtils;
36 import org.openide.nodes.ChildFactory;
37 import org.openide.nodes.Children;
38 import org.openide.nodes.Node;
39 import org.openide.nodes.Sheet;
40 import org.openide.util.Exceptions;
41 import org.openide.util.NbBundle.Messages;
42 import org.openide.util.WeakListeners;
47 import static org.sleuthkit.autopsy.datamodel.AbstractContentNode.backgroundTasksPool;
49 import org.sleuthkit.datamodel.Host;
50 import org.sleuthkit.datamodel.OsAccount;
51 import org.sleuthkit.datamodel.OsAccountRealm;
52 import org.sleuthkit.datamodel.SleuthkitCase;
53 import org.sleuthkit.datamodel.Tag;
54 import org.sleuthkit.datamodel.TskCoreException;
55 import org.sleuthkit.datamodel.TskDataException;
56 
60 public final class OsAccounts implements AutopsyVisitableItem {
61 
62  private static final Logger logger = Logger.getLogger(OsAccounts.class.getName());
63  private static final String ICON_PATH = "org/sleuthkit/autopsy/images/os-account.png";
64  private static final SimpleDateFormat DATE_FORMATTER = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
65  private static final String OS_ACCOUNT_DATA_AVAILABLE_EVENT = "OS_ACCOUNT_DATA_AVAILABLE_EVENT";
66  private static final String LIST_NAME = Bundle.OsAccount_listNode_name();
67 
68  private SleuthkitCase skCase;
69  private final long filteringDSObjId;
70 
76  public static String getListName() {
77  return LIST_NAME;
78  }
79 
80  public OsAccounts(SleuthkitCase skCase) {
81  this(skCase, 0);
82  }
83 
84  public OsAccounts(SleuthkitCase skCase, long objId) {
85  this.skCase = skCase;
86  this.filteringDSObjId = objId;
87  }
88 
89  @Override
90  public <T> T accept(AutopsyItemVisitor<T> visitor) {
91  return visitor.visit(this);
92  }
93 
94  @Messages({
95  "OsAccount_listNode_name=OS Accounts"
96  })
100  public final class OsAccountListNode extends DisplayableItemNode {
101 
105  public OsAccountListNode() {
106  super(Children.create(new OsAccountNodeFactory(), true));
107  setName(LIST_NAME);
108  setDisplayName(LIST_NAME);
109  setIconBaseWithExtension("org/sleuthkit/autopsy/images/os-account.png");
110  }
111 
112  @Override
113  public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
114  return visitor.visit(this);
115  }
116 
117  @Override
118  public boolean isLeafTypeNode() {
119  return true;
120  }
121 
122  @Override
123  public String getItemType() {
124  return getClass().getName();
125  }
126  }
127 
132  private final class OsAccountNodeFactory extends ChildFactory.Detachable<OsAccount> {
133 
134  private final PropertyChangeListener listener = new PropertyChangeListener() {
135  @Override
136  public void propertyChange(PropertyChangeEvent evt) {
137  String eventType = evt.getPropertyName();
138  if (eventType.equals(Case.Events.OS_ACCOUNTS_ADDED.toString())
139  || eventType.equals(Case.Events.OS_ACCOUNTS_DELETED.toString())) {
140  refresh(true);
141  } else if (eventType.equals(Case.Events.CURRENT_CASE.toString())) {
142  // case was closed. Remove listeners so that we don't get called with a stale case handle
143  if (evt.getNewValue() == null) {
144  removeNotify();
145  skCase = null;
146  }
147  }
148  }
149  };
150 
151  private final PropertyChangeListener weakPcl = WeakListeners.propertyChange(listener, null);
152 
153  @Override
154  protected void finalize() throws Throwable {
155  super.finalize();
158  }
159 
160  @Override
161  protected void addNotify() {
164  }
165 
166  @Override
167  protected boolean createKeys(List<OsAccount> list) {
168  if (skCase != null) {
169  try {
170  if (filteringDSObjId == 0) {
171  list.addAll(skCase.getOsAccountManager().getOsAccounts());
172  } else {
173  Host host = skCase.getHostManager().getHostByDataSource(skCase.getDataSource(filteringDSObjId));
174  list.addAll(skCase.getOsAccountManager().getOsAccounts(host));
175  }
176  } catch (TskCoreException | TskDataException ex) {
177  logger.log(Level.SEVERE, "Unable to retrieve list of OsAccounts for case", ex);
178  return false;
179  }
180  }
181  return true;
182  }
183 
184  @Override
185  protected Node createNodeForKey(OsAccount key) {
186  return new OsAccountNode(key);
187  }
188  }
189 
193  public static final class OsAccountNode extends AbstractContentNode<OsAccount> {
194 
195  private OsAccount account;
196 
197  private final PropertyChangeListener listener = new PropertyChangeListener() {
198  @Override
199  public void propertyChange(PropertyChangeEvent evt) {
200  if (evt.getPropertyName().equals(Case.Events.OS_ACCOUNTS_UPDATED.name())) {
202  for (OsAccount acct : updateEvent.getOsAccounts()) {
203  if (acct.getId() == account.getId()) {
204  account = acct;
205  updateSheet();
206  break;
207  }
208  }
209  } else if (evt.getPropertyName().equals(OS_ACCOUNT_DATA_AVAILABLE_EVENT)
210  && evt.getNewValue() instanceof AsynchOsAcctData
211  && ((AsynchOsAcctData) evt.getNewValue()).getOsAccountId() == account.getId()) {
212 
213  List<NodeProperty<?>> propertiesToUpdate = new ArrayList<>();
214 
215  AsynchOsAcctData osAcctData = (AsynchOsAcctData) evt.getNewValue();
216 
217  List<String> realmNames = osAcctData.getOsAcctRealm().getRealmNames();
218  if (!realmNames.isEmpty()) {
219  String realmNamesStr = realmNames.stream()
220  .map(String::trim)
221  .distinct()
222  .sorted((a, b) -> a.compareToIgnoreCase(b))
223  .collect(Collectors.joining(", "));
224 
225  propertiesToUpdate.add(new NodeProperty<>(
226  Bundle.OsAccounts_accountRealmNameProperty_name(),
227  Bundle.OsAccounts_accountRealmNameProperty_displayName(),
228  Bundle.OsAccounts_accountRealmNameProperty_desc(),
229  realmNamesStr));
230  }
231 
232  String scopeName = osAcctData.getOsAcctRealm().getScope().getName();
233  if (StringUtils.isNotBlank(scopeName)) {
234  propertiesToUpdate.add(new NodeProperty<>(
235  Bundle.OsAccounts_accountScopeNameProperty_name(),
236  Bundle.OsAccounts_accountScopeNameProperty_displayName(),
237  Bundle.OsAccounts_accountScopeNameProperty_desc(),
238  scopeName));
239  }
240 
241  List<Host> hosts = osAcctData.getHosts();
242  if (!hosts.isEmpty()) {
243  String hostsString = hosts.stream()
244  .map(h -> h.getName().trim())
245  .distinct()
246  .sorted((a, b) -> a.compareToIgnoreCase(b))
247  .collect(Collectors.joining(", "));
248 
249  propertiesToUpdate.add(new NodeProperty<>(
250  Bundle.OsAccounts_accountHostNameProperty_name(),
251  Bundle.OsAccounts_accountHostNameProperty_displayName(),
252  Bundle.OsAccounts_accountHostNameProperty_desc(),
253  hostsString));
254  }
255 
256  SwingUtilities.invokeLater(() ->
257  updateSheet(propertiesToUpdate.toArray(new NodeProperty<?>[propertiesToUpdate.size()])));
258  }
259  }
260  };
261 
262  private final PropertyChangeListener weakListener = WeakListeners.propertyChange(listener, null);
263 
269  OsAccountNode(OsAccount account) {
270  super(account);
271  this.account = account;
272 
273  setName(account.getName());
274  setDisplayName(account.getName());
275  setIconBaseWithExtension(ICON_PATH);
276 
278  }
279 
280  @Override
281  public <T> T accept(DisplayableItemNodeVisitor<T> visitor) {
282  return visitor.visit(this);
283  }
284 
285  @Override
286  public boolean isLeafTypeNode() {
287  return true;
288  }
289 
290  @Override
291  public String getItemType() {
292  return getClass().getName();
293  }
294 
300  OsAccount getOsAccount() {
301  return account;
302  }
303 
304  @Messages({
305  "OsAccounts_accountNameProperty_name=Name",
306  "OsAccounts_accountNameProperty_displayName=Name",
307  "OsAccounts_accountNameProperty_desc=Os Account name",
308  "OsAccounts_accountRealmNameProperty_name=RealmName",
309  "OsAccounts_accountRealmNameProperty_displayName=Realm Name",
310  "OsAccounts_accountRealmNameProperty_desc=OS Account Realm Name",
311  "OsAccounts_accountHostNameProperty_name=HostName",
312  "OsAccounts_accountHostNameProperty_displayName=Host",
313  "OsAccounts_accountHostNameProperty_desc=OS Account Host Name",
314  "OsAccounts_accountScopeNameProperty_name=ScopeName",
315  "OsAccounts_accountScopeNameProperty_displayName=Scope",
316  "OsAccounts_accountScopeNameProperty_desc=OS Account Scope Name",
317  "OsAccounts_createdTimeProperty_name=creationTime",
318  "OsAccounts_createdTimeProperty_displayName=Creation Time",
319  "OsAccounts_createdTimeProperty_desc=OS Account Creation Time",
320  "OsAccounts_loginNameProperty_name=loginName",
321  "OsAccounts_loginNameProperty_displayName=Login Name",
322  "OsAccounts_loginNameProperty_desc=Os Account login name"
323  })
324 
328  void updateSheet() {
329  this.setSheet(createSheet());
330  }
331 
332  @Override
333  protected Sheet createSheet() {
334  Sheet sheet = super.createSheet();
335  Sheet.Set propertiesSet = sheet.get(Sheet.PROPERTIES);
336  if (propertiesSet == null) {
337  propertiesSet = Sheet.createPropertiesSet();
338  sheet.put(propertiesSet);
339  }
340 
341  propertiesSet.put(new NodeProperty<>(
342  Bundle.OsAccounts_accountNameProperty_name(),
343  Bundle.OsAccounts_accountNameProperty_displayName(),
344  Bundle.OsAccounts_accountNameProperty_desc(),
345  account.getName() != null ? account.getName() : ""));
346 
347  Optional<String> optional = account.getLoginName();
348  propertiesSet.put(new NodeProperty<>(
349  Bundle.OsAccounts_loginNameProperty_name(),
350  Bundle.OsAccounts_loginNameProperty_displayName(),
351  Bundle.OsAccounts_loginNameProperty_desc(),
352  optional.isPresent() ? optional.get() : ""));
353 
354  // Fill with empty string, fetch on background task.
355  propertiesSet.put(new NodeProperty<>(
356  Bundle.OsAccounts_accountHostNameProperty_name(),
357  Bundle.OsAccounts_accountHostNameProperty_displayName(),
358  Bundle.OsAccounts_accountHostNameProperty_desc(),
359  ""));
360 
361  propertiesSet.put(new NodeProperty<>(
362  Bundle.OsAccounts_accountScopeNameProperty_name(),
363  Bundle.OsAccounts_accountScopeNameProperty_displayName(),
364  Bundle.OsAccounts_accountScopeNameProperty_desc(),
365  ""));
366 
367  propertiesSet.put(new NodeProperty<>(
368  Bundle.OsAccounts_accountRealmNameProperty_name(),
369  Bundle.OsAccounts_accountRealmNameProperty_displayName(),
370  Bundle.OsAccounts_accountRealmNameProperty_desc(),
371  ""));
372 
373  Optional<Long> creationTimeValue = account.getCreationTime();
374  String timeDisplayStr
375  = creationTimeValue.isPresent() ? TimeZoneUtils.getFormattedTime(creationTimeValue.get()) : "";
376 
377  propertiesSet.put(new NodeProperty<>(
378  Bundle.OsAccounts_createdTimeProperty_name(),
379  Bundle.OsAccounts_createdTimeProperty_displayName(),
380  Bundle.OsAccounts_createdTimeProperty_desc(),
381  timeDisplayStr));
382 
383  backgroundTasksPool.submit(new GetOsAccountRealmTask(new WeakReference<>(this), weakListener));
384 
385  return sheet;
386  }
387 
388  @Override
389  public Action[] getActions(boolean popup) {
390  List<Action> actionsList = new ArrayList<>();
391  actionsList.addAll(Arrays.asList(super.getActions(popup)));
392  actionsList.addAll(DataModelActionsFactory.getActions(account));
393 
394  return actionsList.toArray(new Action[actionsList.size()]);
395  }
396 
397  @Override
398  protected List<Tag> getAllTagsFromDatabase() {
399  throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
400  }
401 
402  @Override
403  public <T> T accept(ContentNodeVisitor<T> visitor) {
404  return visitor.visit(this);
405  }
406 
410  static class GetOsAccountRealmTask implements Runnable {
411 
412  private final WeakReference<OsAccountNode> weakNodeRef;
413  private final PropertyChangeListener listener;
414 
421  GetOsAccountRealmTask(WeakReference<OsAccountNode> weakContentRef, PropertyChangeListener listener) {
422  this.weakNodeRef = weakContentRef;
423  this.listener = listener;
424  }
425 
426  @Override
427  public void run() {
428  OsAccountNode node = weakNodeRef.get();
429  if (node == null) {
430  return;
431  }
432 
433  try {
434  SleuthkitCase skCase = Case.getCurrentCase().getSleuthkitCase();
435  OsAccount osAcct = node.getOsAccount();
436  long realmId = osAcct.getRealmId();
437  OsAccountRealm realm = skCase.getOsAccountRealmManager().getRealmByRealmId(realmId);
438 
439  List<Host> hosts = skCase.getOsAccountManager().getHosts(osAcct);
440 
441  AsynchOsAcctData evtData = new AsynchOsAcctData(osAcct.getId(), realm, hosts);
442 
443  if (listener != null && realm != null) {
444  listener.propertyChange(new PropertyChangeEvent(
445  AutopsyEvent.SourceType.LOCAL.toString(),
447  null, evtData));
448  }
449 
450  } catch (TskCoreException ex) {
451  Exceptions.printStackTrace(ex);
452  }
453  }
454  }
455 
460  private static class AsynchOsAcctData {
461 
462  private final long osAccountId;
463  private final OsAccountRealm osAcctRealm;
464  private final List<Host> hosts;
465 
473  AsynchOsAcctData(long osAccountId, OsAccountRealm osAcctRealm, List<Host> hosts) {
474  this.osAccountId = osAccountId;
475  this.osAcctRealm = osAcctRealm;
476  this.hosts = hosts;
477  }
478 
482  long getOsAccountId() {
483  return osAccountId;
484  }
485 
489  OsAccountRealm getOsAcctRealm() {
490  return osAcctRealm;
491  }
492 
496  List<Host> getHosts() {
497  return hosts;
498  }
499  }
500  }
501 }
static final String OS_ACCOUNT_DATA_AVAILABLE_EVENT
Definition: OsAccounts.java:65
static List< Action > getActions(File file, boolean isArtifactSource)
OsAccounts(SleuthkitCase skCase, long objId)
Definition: OsAccounts.java:84
static String getFormattedTime(long epochTime)
static final SimpleDateFormat DATE_FORMATTER
Definition: OsAccounts.java:64
synchronized static Logger getLogger(String name)
Definition: Logger.java:124
static void addEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
Definition: Case.java:711
static void removeEventTypeSubscriber(Set< Events > eventTypes, PropertyChangeListener subscriber)
Definition: Case.java:756

Copyright © 2012-2021 Basis Technology. Generated on: Thu Sep 30 2021
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.