Autopsy  4.15.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
Persona.java
Go to the documentation of this file.
1 /*
2  * Central Repository
3  *
4  * Copyright 2020 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.centralrepository.datamodel;
20 
21 import java.sql.ResultSet;
22 import java.sql.SQLException;
23 import java.time.Instant;
24 import java.util.ArrayList;
25 import java.util.Collection;
26 import java.util.Collections;
27 import java.util.Objects;
28 import java.util.UUID;
29 import org.apache.commons.lang3.StringUtils;
30 import org.openide.util.NbBundle;
31 import org.sleuthkit.datamodel.SleuthkitCase;
32 
39 public class Persona {
40 
44  public enum Confidence {
45  LOW(1, "Low confidence"),
46  MODERATE(2, "Moderate confidence"),
47  HIGH(3, "High confidence");
48 
49  private final String name;
50  private final int level_id;
51 
52  Confidence(int level, String name) {
53  this.name = name;
54  this.level_id = level;
55 
56  }
57 
58  @Override
59  public String toString() {
60  return name;
61  }
62 
63  public int getLevelId() {
64  return this.level_id;
65  }
66 
67  static Confidence fromId(int value) {
68  for (Confidence confidence : Confidence.values()) {
69  if (confidence.getLevelId() == value) {
70  return confidence;
71  }
72  }
73  return Confidence.LOW;
74  }
75 
76  }
77 
81  public enum PersonaStatus {
82 
83  UNKNOWN(1, "Unknown"),
84  ACTIVE(2, "Active"),
85  MERGED(3, "Merged"),
86  SPLIT(4, "Split"),
87  DELETED(5, "Deleted");
88 
89  private final String description;
90  private final int status_id;
91 
92  PersonaStatus(int status, String description) {
93  this.status_id = status;
94  this.description = description;
95  }
96 
97  @Override
98  public String toString() {
99  return description;
100  }
101 
102  public int getStatusId() {
103  return this.status_id;
104  }
105 
106  static PersonaStatus fromId(int value) {
107  for (PersonaStatus status : PersonaStatus.values()) {
108  if (status.getStatusId() == value) {
109  return status;
110  }
111  }
112  return PersonaStatus.UNKNOWN;
113  }
114  }
115 
116  // primary key in the Personas table in CR database
117  private final long id;
118  private final String uuidStr;
119  private final String name;
120  private final String comment;
121  private final long createdDate;
122  private final long modifiedDate;
123  private final PersonaStatus status;
125 
126  @NbBundle.Messages("Persona.defaultName=Unnamed")
127  public static String getDefaultName() {
128  return Bundle.Persona_defaultName();
129  }
130 
131  public long getId() {
132  return id;
133  }
134 
135  public String getUuidStr() {
136  return uuidStr;
137  }
138 
139  public String getName() {
140  return name;
141  }
142 
143  public String getComment() {
144  return comment;
145  }
146 
147  public long getCreatedDate() {
148  return createdDate;
149  }
150 
151  public long getModifiedDate() {
152  return modifiedDate;
153  }
154 
156  return status;
157  }
158 
160  return examiner;
161  }
162 
163  Persona(long id, String uuidStr, String name, String comment, long created_date, long modified_date, PersonaStatus status, CentralRepoExaminer examiner) {
164  this.id = id;
165  this.uuidStr = uuidStr;
166  this.name = name;
167  this.comment = comment;
168  this.createdDate = created_date;
169  this.modifiedDate = modified_date;
170  this.status = status;
171  this.examiner = examiner;
172  }
173 
174  @Override
175  public int hashCode() {
176  int hash = 7;
177  hash = 67 * hash + (int) (this.id ^ (this.id >>> 32));
178  hash = 67 * hash + Objects.hashCode(this.uuidStr);
179  return hash;
180  }
181 
182  @Override
183  public boolean equals(Object obj) {
184  if (this == obj) {
185  return true;
186  }
187  if (obj == null) {
188  return false;
189  }
190  if (getClass() != obj.getClass()) {
191  return false;
192  }
193  final Persona other = (Persona) obj;
194  if (this.id != other.getId()) {
195  return false;
196  }
197  return this.uuidStr.equalsIgnoreCase(other.getUuidStr());
198  }
199 
215  public static Persona createPersonaForAccount(String personaName, String comment, PersonaStatus status, CentralRepoAccount account, String justification, Persona.Confidence confidence) throws CentralRepoException {
216  Persona persona = createPersona(personaName, comment, status);
217  persona.addAccount(account, justification, confidence);
218  return persona;
219  }
220 
234  private static Persona createPersona(String name, String comment, PersonaStatus status) throws CentralRepoException {
235  // generate a UUID for the persona
236  String uuidStr = UUID.randomUUID().toString();
237  CentralRepoExaminer examiner = getCRInstance().getOrInsertExaminer(System.getProperty("user.name"));
238 
239  Instant instant = Instant.now();
240  Long timeStampMillis = instant.toEpochMilli();
241  String insertClause = " INTO personas (uuid, comment, name, created_date, modified_date, status_id, examiner_id ) "
242  + "VALUES ( '" + uuidStr + "', "
243  + "'" + ((StringUtils.isBlank(comment) ? "" : SleuthkitCase.escapeSingleQuotes(comment))) + "',"
244  + "'" + ((StringUtils.isBlank(name) ? getDefaultName() : SleuthkitCase.escapeSingleQuotes(name))) + "',"
245  + timeStampMillis.toString() + ","
246  + timeStampMillis.toString() + ","
247  + status.getStatusId() + ","
248  + examiner.getId()
249  + ")";
250 
251  getCRInstance().executeInsertSQL(insertClause);
252  return getPersonaByUUID(uuidStr);
253  }
254 
262  public void setComment(String comment) throws CentralRepoException {
263  String updateClause = "UPDATE personas SET comment = '" + comment + "' WHERE id = " + id;
265  if (cr != null) {
266  getCRInstance().executeUpdateSQL(updateClause);
267  }
268  }
269 
277  public void setName(String name) throws CentralRepoException {
278  String updateClause = "UPDATE personas SET name = '" + name + "' WHERE id = " + id;
280  if (cr != null) {
281  cr.executeUpdateSQL(updateClause);
282  }
283  }
284 
297  public PersonaAccount addAccount(CentralRepoAccount account, String justification, Persona.Confidence confidence) throws CentralRepoException {
298  return PersonaAccount.addPersonaAccount(this, account, justification, confidence);
299  }
300 
309  public void removeAccount(PersonaAccount account) throws CentralRepoException {
310  PersonaAccount.removePersonaAccount(account.getId());
311  }
312 
323  public void modifyAccount(PersonaAccount account, Confidence confidence, String justification) throws CentralRepoException {
324  PersonaAccount.modifyPersonaAccount(account.getId(), confidence, justification);
325  }
326 
330  public void delete() throws CentralRepoException {
331  String deleteSQL = "UPDATE personas SET status_id = " + PersonaStatus.DELETED.status_id + " WHERE id = " + this.id;
333  if (cr != null) {
334  cr.executeUpdateSQL(deleteSQL);
335  }
336  }
337 
341  private static class PersonaQueryCallback implements CentralRepositoryDbQueryCallback {
342 
343  private final Collection<Persona> personaList = new ArrayList<>();
344 
345  @Override
346  public void process(ResultSet rs) throws SQLException {
347 
348  while (rs.next()) {
350  rs.getInt("examiner_id"),
351  rs.getString("login_name"));
352 
353  PersonaStatus status = PersonaStatus.fromId(rs.getInt("status_id"));
354  Persona persona = new Persona(
355  rs.getInt("id"),
356  rs.getString("uuid"),
357  rs.getString("name"),
358  rs.getString("comment"),
359  Long.parseLong(rs.getString("created_date")),
360  Long.parseLong(rs.getString("modified_date")),
361  status,
362  examiner
363  );
364 
365  personaList.add(persona);
366  }
367  }
368 
369  Collection<Persona> getPersonas() {
370  return Collections.unmodifiableCollection(personaList);
371  }
372  };
373 
374  // Partial query string to select from personas table,
375  // just supply the where clause.
376  private static final String PERSONA_QUERY =
377  "SELECT p.id, p.uuid, p.name, p.comment, p.created_date, p.modified_date, p.status_id, p.examiner_id, e.login_name, e.display_name "
378  + "FROM personas as p "
379  + "INNER JOIN examiners as e ON e.id = p.examiner_id ";
380 
381 
393  private static Persona getPersonaByUUID(String uuid) throws CentralRepoException {
394 
395  String queryClause =
396  PERSONA_QUERY
397  + "WHERE p.uuid = '" + uuid + "'";
398 
399  PersonaQueryCallback queryCallback = new PersonaQueryCallback();
400  getCRInstance().executeSelectSQL(queryClause, queryCallback);
401 
402  Collection<Persona> personas = queryCallback.getPersonas();
403 
404  return personas.isEmpty() ? null : personas.iterator().next();
405  }
406 
418  public static Collection<Persona> getPersonaByName(String partialName) throws CentralRepoException {
419 
420  String queryClause = PERSONA_QUERY
421  + "WHERE p.status_id != " + PersonaStatus.DELETED.status_id +
422  " AND LOWER(p.name) LIKE " + "LOWER('%" + partialName + "%')" ;
423 
424  PersonaQueryCallback queryCallback = new PersonaQueryCallback();
425  getCRInstance().executeSelectSQL(queryClause, queryCallback);
426 
427  return queryCallback.getPersonas();
428  }
429 
441  public static Collection<Persona> getPersonaByAccountIdentifierLike(String partialName) throws CentralRepoException {
442  String queryClause = "SELECT DISTINCT accounts.id as a_id,"
443  + "p.id, p.uuid, p.name, p.comment, p.created_date, p.modified_date, p.status_id, p.examiner_id, e.login_name, e.display_name"
444  + " FROM accounts"
445  + " JOIN persona_accounts as pa ON pa.account_id = accounts.id"
446  + " JOIN personas as p ON p.id = pa.persona_id"
447  + " JOIN examiners as e ON e.id = p.examiner_id"
448  + " WHERE LOWER(accounts.account_unique_identifier) LIKE LOWER('%" + partialName + "%')"
449  + " AND p.status_id != " + Persona.PersonaStatus.DELETED.getStatusId()
450  + " GROUP BY p.id";
451 
452  PersonaQueryCallback queryCallback = new PersonaQueryCallback();
454  if (cr != null) {
455  cr.executeSelectSQL(queryClause, queryCallback);
456  }
457 
458  return queryCallback.getPersonas();
459  }
460 
471  public PersonaAlias addAlias(String alias, String justification, Persona.Confidence confidence) throws CentralRepoException {
472  return PersonaAlias.addPersonaAlias(this, alias, justification, confidence);
473  }
474 
483  public void removeAlias(PersonaAlias alias) throws CentralRepoException {
484  PersonaAlias.removePersonaAlias(alias);
485  }
486 
497  public void modifyAlias(PersonaAlias key, Confidence confidence, String justification) throws CentralRepoException {
498  PersonaAlias.modifyPersonaAlias(key, confidence, justification);
499  }
500 
508  public Collection<PersonaAlias> getAliases() throws CentralRepoException {
509  return PersonaAlias.getPersonaAliases(this.getId());
510  }
511 
523  public PersonaMetadata addMetadata(String name, String value, String justification, Persona.Confidence confidence) throws CentralRepoException {
524  return PersonaMetadata.addPersonaMetadata(this.getId(), name, value, justification, confidence);
525  }
526 
535  public void removeMetadata(PersonaMetadata metadata) throws CentralRepoException {
536  PersonaMetadata.removePersonaMetadata(metadata);
537  }
538 
549  public void modifyMetadata(PersonaMetadata key, Confidence confidence, String justification) throws CentralRepoException {
550  PersonaMetadata.modifyPersonaMetadata(key, confidence, justification);
551  }
552 
560  public Collection<PersonaMetadata> getMetadata() throws CentralRepoException {
561  return PersonaMetadata.getPersonaMetadata(this.getId());
562  }
563 
572  public Collection<PersonaAccount> getPersonaAccounts() throws CentralRepoException {
573  return PersonaAccount.getPersonaAccountsForPersona(this.getId());
574  }
575 
580  private static class CaseForAccountInstanceQueryCallback implements CentralRepositoryDbQueryCallback {
581 
582  Collection<CorrelationCase> correlationCases = new ArrayList<>();
583 
584  @Override
585  public void process(ResultSet resultSet) throws CentralRepoException, SQLException {
586 
587  while (resultSet.next()) {
588  // get Case for case_id
589  CorrelationCase correlationCase = getCRInstance().getCaseById(resultSet.getInt("case_id"));
590  correlationCases.add(correlationCase);
591  }
592  }
593 
594  Collection<CorrelationCase> getCases() {
595  return Collections.unmodifiableCollection(correlationCases);
596  }
597  };
598 
606  public Collection<CorrelationCase> getCases() throws CentralRepoException {
607 
608  Collection<CorrelationCase> casesForPersona = new ArrayList<>();
609 
610  // get all accounts for this persona
611  Collection<CentralRepoAccount> accounts = PersonaAccount.getAccountsForPersona(this.getId());
612  for (CentralRepoAccount account : accounts) {
613  int corrTypeId = account.getAccountType().getCorrelationTypeId();
615 
616  String tableName = CentralRepoDbUtil.correlationTypeToInstanceTableName(correlationType);
617  String querySql = "SELECT DISTINCT case_id FROM " + tableName
618  + " WHERE account_id = " + account.getId();
619 
621  getCRInstance().executeSelectSQL(querySql, queryCallback);
622 
623  // Add any cases that aren't already on the list.
624  for (CorrelationCase corrCase : queryCallback.getCases()) {
625  if (!casesForPersona.stream().anyMatch(p -> p.getCaseUUID().equalsIgnoreCase(corrCase.getCaseUUID()))) {
626  casesForPersona.add(corrCase);
627  }
628  }
629  }
630 
631  return casesForPersona;
632  }
633 
638  private static class DatasourceForAccountInstanceQueryCallback implements CentralRepositoryDbQueryCallback {
639 
640  Collection<CorrelationDataSource> correlationDataSources = new ArrayList<>();
641 
642  @Override
643  public void process(ResultSet resultSet) throws CentralRepoException, SQLException {
644 
645  while (resultSet.next()) {
646  // get Case for case_id
647 
648  CorrelationCase correlationCase = getCRInstance().getCaseById(resultSet.getInt("case_id"));
649  CorrelationDataSource correlationDatasource = getCRInstance().getDataSourceById(correlationCase, resultSet.getInt("data_source_id"));
650 
651  // Add data source to list if not already on it.
652  if (!correlationDataSources.stream().anyMatch(p -> Objects.equals(p.getDataSourceObjectID(), correlationDatasource.getDataSourceObjectID()))) {
653  correlationDataSources.add(correlationDatasource);
654  }
655  }
656  }
657 
658  Collection<CorrelationDataSource> getDataSources() {
659  return Collections.unmodifiableCollection(correlationDataSources);
660  }
661  };
662 
671  public Collection<CorrelationDataSource> getDataSources() throws CentralRepoException {
672  Collection<CorrelationDataSource> correlationDataSources = new ArrayList<>();
673 
674  Collection<CentralRepoAccount> accounts = PersonaAccount.getAccountsForPersona(this.getId());
675  for (CentralRepoAccount account : accounts) {
676  int corrTypeId = account.getAccountType().getCorrelationTypeId();
678 
679  String tableName = CentralRepoDbUtil.correlationTypeToInstanceTableName(correlationType);
680  String querySql = "SELECT case_id, data_source_id FROM " + tableName
681  + " WHERE account_id = " + account.getId();
682 
684  getCRInstance().executeSelectSQL(querySql, queryCallback);
685 
686  // Add any data sources that aren't already on the list.
687  for (CorrelationDataSource correlationDatasource : queryCallback.getDataSources()) {
688  if (!correlationDataSources.stream().anyMatch(p -> Objects.equals(p.getDataSourceObjectID(), correlationDatasource.getDataSourceObjectID()))) {
689  correlationDataSources.add(correlationDatasource);
690  }
691  }
692  }
693 
694  return correlationDataSources;
695  }
696 
700  private static class PersonaFromAccountInstanceQueryCallback implements CentralRepositoryDbQueryCallback {
701 
702  Collection<Persona> personasList = new ArrayList<>();
703 
704  @Override
705  public void process(ResultSet resultSet) throws CentralRepoException, SQLException {
706 
707  while (resultSet.next()) {
708 
709  // examiner that created the persona
710  CentralRepoExaminer personaExaminer = new CentralRepoExaminer(
711  resultSet.getInt("persona_examiner_id"),
712  resultSet.getString("persona_examiner_login_name"));
713 
714  // create persona
715  PersonaStatus status = PersonaStatus.fromId(resultSet.getInt("status_id"));
716  Persona persona = new Persona(
717  resultSet.getInt("persona_id"),
718  resultSet.getString("uuid"),
719  resultSet.getString("name"),
720  resultSet.getString("comment"),
721  Long.parseLong(resultSet.getString("created_date")),
722  Long.parseLong(resultSet.getString("modified_date")),
723  status,
724  personaExaminer
725  );
726 
727  personasList.add(persona);
728  }
729  }
730 
731  Collection<Persona> getPersonasList() {
732  return Collections.unmodifiableCollection(personasList);
733  }
734  };
735 
744  private static String getPersonaFromInstanceTableQueryTemplate(CentralRepoAccount.CentralRepoAccountType crAccountType) throws CentralRepoException {
745 
746  int corrTypeId = crAccountType.getCorrelationTypeId();
748 
749  String instanceTableName = CentralRepoDbUtil.correlationTypeToInstanceTableName(correlationType);
750  return "SELECT " + instanceTableName + ".account_id, case_id, data_source_id, "
751  + " personas.id as persona_id, personas.uuid, personas.name, personas.comment, personas.created_date, personas.modified_date, personas.status_id, "
752  + " personas.examiner_id as persona_examiner_id, persona_examiner.login_name as persona_examiner_login_name, persona_examiner.display_name as persona_examiner_display_name "
753  + " FROM " + instanceTableName
754  + " JOIN persona_accounts as pa on pa.account_id = " + instanceTableName + ".account_id"
755  + " JOIN personas as personas on personas.id = pa.persona_id"
756  + " JOIN examiners as persona_examiner ON persona_examiner.id = personas.examiner_id ";
757 
758  }
759 
768  public static Collection<Persona> getPersonasForCase(CorrelationCase correlationCase) throws CentralRepoException {
769  Collection<Persona> personaList = new ArrayList<>();
770 
772  for (CentralRepoAccount.CentralRepoAccountType crAccountType : accountTypes) {
773 
774  String querySql = getPersonaFromInstanceTableQueryTemplate(crAccountType)
775  + " WHERE case_id = " + correlationCase.getID()
776  + "AND personas.status_id != " + Persona.PersonaStatus.DELETED.getStatusId();
777 
779  getCRInstance().executeSelectSQL(querySql, queryCallback);
780 
781  // Add persona that aren't already on the list.
782  for (Persona persona : queryCallback.getPersonasList()) {
783  if (!personaList.stream().anyMatch(p -> Objects.equals(p.getUuidStr(), persona.getUuidStr()))) {
784  personaList.add(persona);
785  }
786  }
787 
788  }
789  return personaList;
790  }
791 
800  public static Collection<Persona> getPersonasForDataSource(CorrelationDataSource dataSource) throws CentralRepoException {
801  Collection<Persona> personaList = new ArrayList<>();
802 
804  for (CentralRepoAccount.CentralRepoAccountType crAccountType : accountTypes) {
805 
806  String querySql = getPersonaFromInstanceTableQueryTemplate(crAccountType)
807  + " WHERE data_source_id = " + dataSource.getID()
808  + "AND personas.status_id != " + Persona.PersonaStatus.DELETED.getStatusId();
809 
811  getCRInstance().executeSelectSQL(querySql, queryCallback);
812 
813  // Add persona that aren't already on the list.
814  for (Persona persona : queryCallback.getPersonasList()) {
815  if (!personaList.stream().anyMatch(p -> Objects.equals(p.getUuidStr(), persona.getUuidStr()))) {
816  personaList.add(persona);
817  }
818  }
819 
820  }
821  return personaList;
822  }
823 
824 
833  private static CentralRepository getCRInstance() throws CentralRepoException {
835 
836  if(instance == null) {
837  throw new CentralRepoException("Failed to get instance of CentralRespository, CR was null");
838  }
839 
840  return instance;
841  }
842 }
void executeSelectSQL(String sql, CentralRepositoryDbQueryCallback queryCallback)
void modifyAlias(PersonaAlias key, Confidence confidence, String justification)
Definition: Persona.java:497
static Collection< Persona > getPersonaByName(String partialName)
Definition: Persona.java:418
static Persona createPersonaForAccount(String personaName, String comment, PersonaStatus status, CentralRepoAccount account, String justification, Persona.Confidence confidence)
Definition: Persona.java:215
PersonaAlias addAlias(String alias, String justification, Persona.Confidence confidence)
Definition: Persona.java:471
PersonaAccount addAccount(CentralRepoAccount account, String justification, Persona.Confidence confidence)
Definition: Persona.java:297
CentralRepoExaminer getOrInsertExaminer(String examinerLoginName)
void modifyAccount(PersonaAccount account, Confidence confidence, String justification)
Definition: Persona.java:323
PersonaMetadata addMetadata(String name, String value, String justification, Persona.Confidence confidence)
Definition: Persona.java:523
Collection< CorrelationDataSource > getDataSources()
Definition: Persona.java:671
void modifyMetadata(PersonaMetadata key, Confidence confidence, String justification)
Definition: Persona.java:549
static Collection< Persona > getPersonasForCase(CorrelationCase correlationCase)
Definition: Persona.java:768
static String correlationTypeToInstanceTableName(CorrelationAttributeInstance.Type type)
static String getPersonaFromInstanceTableQueryTemplate(CentralRepoAccount.CentralRepoAccountType crAccountType)
Definition: Persona.java:744
static Collection< PersonaAlias > getPersonaAliases(long personaId)
static Persona createPersona(String name, String comment, PersonaStatus status)
Definition: Persona.java:234
CorrelationAttributeInstance.Type getCorrelationTypeById(int typeId)
static Collection< Persona > getPersonasForDataSource(CorrelationDataSource dataSource)
Definition: Persona.java:800
static Collection< Persona > getPersonaByAccountIdentifierLike(String partialName)
Definition: Persona.java:441
CorrelationDataSource getDataSourceById(CorrelationCase correlationCase, int dataSourceId)

Copyright © 2012-2020 Basis Technology. Generated on: Mon Jul 6 2020
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.