Skip to content
Snippets Groups Projects
Unverified Commit b5f49f85 authored by Richard Cordovano's avatar Richard Cordovano Committed by GitHub
Browse files

Merge pull request #1838 from rcordovano/6071-comm-mgr-new-acct-artifact-events

6071 Make CommunicationsManager post account artifacts
parents b64417c7 7d54b262
No related branches found
No related tags found
No related merge requests found
/*
* Sleuth Kit Data Model
*
* Copyright 2017-18 Basis Technology Corp.
* Copyright 2017-2020 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
......@@ -33,6 +33,7 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.sleuthkit.datamodel.Blackboard.BlackboardException;
import org.sleuthkit.datamodel.SleuthkitCase.CaseDbConnection;
import static org.sleuthkit.datamodel.SleuthkitCase.closeResultSet;
import static org.sleuthkit.datamodel.SleuthkitCase.closeStatement;
......@@ -48,20 +49,18 @@ public final class CommunicationsManager {
private final SleuthkitCase db;
private final Map<Account.Type, Integer> accountTypeToTypeIdMap
= new ConcurrentHashMap<Account.Type, Integer>();
= new ConcurrentHashMap<>();
private final Map<String, Account.Type> typeNameToAccountTypeMap
= new ConcurrentHashMap<String, Account.Type>();
// Artifact types that represent a relationship between accounts
private final static Set<Integer> RELATIONSHIP_ARTIFACT_TYPE_IDS
= new HashSet<Integer>(Arrays.asList(
BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE.getTypeID(),
BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID(),
BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT.getTypeID(),
BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG.getTypeID()
));
private static final String RELATIONSHIP_ARTIFACT_TYPE_IDS_CSV_STR
= StringUtils.buildCSVString(RELATIONSHIP_ARTIFACT_TYPE_IDS);
= new ConcurrentHashMap<>();
// Artifact types that can represent a relationship between accounts.
private static final Set<Integer> RELATIONSHIP_ARTIFACT_TYPE_IDS = new HashSet<Integer>(Arrays.asList(
BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE.getTypeID(),
BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID(),
BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT.getTypeID(),
BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG.getTypeID()
));
private static final String RELATIONSHIP_ARTIFACT_TYPE_IDS_CSV_STR = StringUtils.buildCSVString(RELATIONSHIP_ARTIFACT_TYPE_IDS);
/**
* Construct a CommunicationsManager for the given SleuthkitCase.
......@@ -328,7 +327,7 @@ public Account getAccount(org.sleuthkit.datamodel.Account.Type accountType, Stri
/**
* Adds relationships between the sender and each of the recipient account
* instances and between all recipient account instances. All account
* instances and between all recipient account instances. All account
* instances must be from the same data source.
*
* @param sender sender account
......@@ -450,36 +449,36 @@ private Account getOrCreateAccount(Account.Type accountType, String accountUniqu
}
/**
* Get the blackboard artifact for the given account type, account ID, and
* source file. Create an artifact if it doesn't already exist.
* Gets or creates an account artifact for an instance of an account found
* in a file.
*
* @param accountType account type
* @param accountUniqueID Unique account ID (such as email address)
* @param moduleName module name that found this instance (for the
* artifact)
* @param sourceFile Source file (for the artifact)
* @param accountType The account type of the account instance.
* @param accountUniqueID The account ID of the account instance, should be
* unique for the account type (e.g., an email
* address for an email account).
* @param moduleName The name of the module that found the account
* instance.
* @param sourceFile The file in which the account instance was found.
*
* @return blackboard artifact for the account file instance
* @return The account artifact.
*
* @throws TskCoreException exception thrown if a critical error occurs
* within TSK core
* @throws TskCoreException If there is an error querying or updating the
* case database.
*/
BlackboardArtifact getOrCreateAccountFileInstanceArtifact(Account.Type accountType, String accountUniqueID, String moduleName, Content sourceFile) throws TskCoreException {
// see if it already exists
private BlackboardArtifact getOrCreateAccountFileInstanceArtifact(Account.Type accountType, String accountUniqueID, String moduleName, Content sourceFile) throws TskCoreException {
BlackboardArtifact accountArtifact = getAccountFileInstanceArtifact(accountType, accountUniqueID, sourceFile);
if (null != accountArtifact) {
return accountArtifact;
if (accountArtifact == null) {
accountArtifact = db.newBlackboardArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT, sourceFile.getId());
Collection<BlackboardAttribute> attributes = new ArrayList<>();
attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE, moduleName, accountType.getTypeName()));
attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ID, moduleName, accountUniqueID));
accountArtifact.addAttributes(attributes);
try {
db.getBlackboard().postArtifact(accountArtifact, moduleName);
} catch (BlackboardException ex) {
LOGGER.log(Level.SEVERE, String.format("Error posting new account artifact to the blackboard (object ID = %d)", accountArtifact.getId()), ex);
}
}
// Create a new artifact.
accountArtifact = db.newBlackboardArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT, sourceFile.getId());
Collection<BlackboardAttribute> attributes = new ArrayList<BlackboardAttribute>();
attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE, moduleName, accountType.getTypeName()));
attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ID, moduleName, accountUniqueID));
accountArtifact.addAttributes(attributes);
return accountArtifact;
}
......@@ -662,11 +661,11 @@ public List<AccountDeviceInstance> getAccountDeviceInstancesWithRelationships(Co
CommunicationsFilter.RelationshipTypeFilter.class.getName()
));
String relationshipFilterSQL = getCommunicationsFilterSQL(filter, applicableInnerQueryFilters);
String relationshipLimitSQL = getMostRecentFilterLimitSQL(filter);
String relTblfilterQuery =
"SELECT * "
String relTblfilterQuery
= "SELECT * "
+ "FROM account_relationships as relationships"
+ (relationshipFilterSQL.isEmpty() ? "" : " WHERE " + relationshipFilterSQL)
+ (relationshipLimitSQL.isEmpty() ? "" : relationshipLimitSQL);
......@@ -901,17 +900,17 @@ public long getRelationshipSourcesCount(AccountDeviceInstance accountDeviceInsta
try {
s = connection.createStatement();
String innerQuery = " account_relationships AS relationships";
String limitStr = getMostRecentFilterLimitSQL(filter);
if(!limitStr.isEmpty()) {
if (!limitStr.isEmpty()) {
innerQuery = "(SELECT * FROM account_relationships as relationships " + limitStr + ") as relationships";
}
String queryStr
= "SELECT count(DISTINCT relationships.relationship_source_obj_id) as count "
+ " FROM" + innerQuery
+ " FROM" + innerQuery
+ " WHERE relationships.data_source_obj_id IN ( " + datasourceObjIdsCSV + " )"
+ " AND ( relationships.account1_id = " + account_id
+ " OR relationships.account2_id = " + account_id + " )"
......@@ -935,7 +934,8 @@ public long getRelationshipSourcesCount(AccountDeviceInstance accountDeviceInsta
* with accounts on specific devices (AccountDeviceInstance) that meet the
* filter criteria.
*
* Applicable filters: RelationshipTypeFilter, DateRangeFilter, MostRecentFilter
* Applicable filters: RelationshipTypeFilter, DateRangeFilter,
* MostRecentFilter
*
* @param accountDeviceInstanceList set of account device instances for
* which to get the relationship sources.
......@@ -985,10 +985,10 @@ public Set<Content> getRelationshipSources(Set<AccountDeviceInstance> accountDev
.getName()
));
String filterSQL = getCommunicationsFilterSQL(filter, applicableFilters);
String limitQuery = " account_relationships AS relationships";
String limitStr = getMostRecentFilterLimitSQL(filter);
if(!limitStr.isEmpty()) {
if (!limitStr.isEmpty()) {
limitQuery = "(SELECT * FROM account_relationships as relationships " + limitStr + ") as relationships";
}
......@@ -1152,8 +1152,8 @@ public List<AccountDeviceInstance> getRelatedAccountDeviceInstances(AccountDevic
* Get the sources (artifacts, content) of relationships between the given
* account device instances.
*
* Applicable filters: DeviceFilter, DateRangeFilter, RelationshipTypeFilter,
* MostRecentFilter
* Applicable filters: DeviceFilter, DateRangeFilter,
* RelationshipTypeFilter, MostRecentFilter
*
* @param account1 First AccountDeviceInstance
* @param account2 Second AccountDeviceInstance
......@@ -1172,13 +1172,13 @@ public List<Content> getRelationshipSources(AccountDeviceInstance account1, Acco
CommunicationsFilter.DeviceFilter.class.getName(),
CommunicationsFilter.RelationshipTypeFilter.class.getName()
));
String limitQuery = " account_relationships AS relationships";
String limitStr = getMostRecentFilterLimitSQL(filter);
if(!limitStr.isEmpty()) {
if (!limitStr.isEmpty()) {
limitQuery = "(SELECT * FROM account_relationships as relationships " + limitStr + ") as relationships";
}
String filterSQL = getCommunicationsFilterSQL(filter, applicableFilters);
final String queryString = "SELECT artifacts.artifact_id AS artifact_id,"
+ " artifacts.obj_id AS obj_id,"
......@@ -1187,7 +1187,7 @@ public List<Content> getRelationshipSources(AccountDeviceInstance account1, Acco
+ " artifacts.artifact_type_id AS artifact_type_id,"
+ " artifacts.review_status_id AS review_status_id"
+ " FROM blackboard_artifacts AS artifacts"
+ " JOIN " + limitQuery
+ " JOIN " + limitQuery
+ " ON artifacts.artifact_obj_id = relationships.relationship_source_obj_id"
+ " WHERE (( relationships.account1_id = " + account1.getAccount().getAccountID()
+ " AND relationships.account2_id = " + account2.getAccount().getAccountID()
......@@ -1220,44 +1220,44 @@ public List<Content> getRelationshipSources(AccountDeviceInstance account1, Acco
db.releaseSingleUserCaseReadLock();
}
}
/**
* Get a list AccountFileInstance for the given accounts.
*
*
* @param account List of accounts
*
* @return A lit of AccountFileInstances for the given accounts or null if
* none are found.
*
* @throws org.sleuthkit.datamodel.TskCoreException
*
* @return A lit of AccountFileInstances for the given accounts or null if
* none are found.
*
* @throws org.sleuthkit.datamodel.TskCoreException
*/
public List<AccountFileInstance> getAccountFileInstances(Account account) throws TskCoreException {
List<AccountFileInstance> accountFileInstanceList = new ArrayList<>();
List<BlackboardArtifact> artifactList = getSleuthkitCase().getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ID, account.getTypeSpecificID());
if(artifactList != null && !artifactList.isEmpty()) {
for(BlackboardArtifact artifact : artifactList) {
if (artifactList != null && !artifactList.isEmpty()) {
for (BlackboardArtifact artifact : artifactList) {
accountFileInstanceList.add(new AccountFileInstance(artifact, account));
}
}
if(!accountFileInstanceList.isEmpty()) {
if (!accountFileInstanceList.isEmpty()) {
return accountFileInstanceList;
} else {
return null;
}
}
/**
* Gets a list of the distinct account types that can currently be found in
* the case db.
*
*
* @return A list of distinct accounts or an empty list.
*
* @throws TskCoreException
*
* @throws TskCoreException
*/
public List<Account.Type> getAccountTypesInUse() throws TskCoreException{
public List<Account.Type> getAccountTypesInUse() throws TskCoreException {
CaseDbConnection connection = db.getConnection();
db.acquireSingleUserCaseReadLock();
Statement s = null;
......@@ -1272,12 +1272,12 @@ public List<Account.Type> getAccountTypesInUse() throws TskCoreException{
while (rs.next()) {
String accountTypeName = rs.getString("type_name");
accountType = this.typeNameToAccountTypeMap.get(accountTypeName);
if(accountType == null) {
if (accountType == null) {
accountType = new Account.Type(accountTypeName, rs.getString("display_name"));
this.accountTypeToTypeIdMap.put(accountType, rs.getInt("account_type_id"));
}
inUseAccounts.add(accountType);
}
return inUseAccounts;
......@@ -1341,8 +1341,8 @@ private String normalizePhoneNum(String phoneNum) {
if (phoneNum.startsWith("+")) {
normailzedPhoneNum = "+" + normailzedPhoneNum;
}
if(normailzedPhoneNum.isEmpty()) {
if (normailzedPhoneNum.isEmpty()) {
normailzedPhoneNum = phoneNum;
}
......@@ -1405,27 +1405,28 @@ private String getCommunicationsFilterSQL(CommunicationsFilter commFilter, Set<S
}
return sqlStr;
}
/**
* Builds the SQL for the MostRecentFilter.
*
*
* @param filter The CommunicationsFilter to get the SQL for.
* @return Order BY and LIMIT clause or empty
* string if no filter is available.
*
* @return Order BY and LIMIT clause or empty string if no filter is
* available.
*/
private String getMostRecentFilterLimitSQL(CommunicationsFilter filter) {
String limitStr = "";
if (filter != null && !filter.getAndFilters().isEmpty()) {
for (CommunicationsFilter.SubFilter subFilter : filter.getAndFilters()) {
if(subFilter.getClass().getName().equals(CommunicationsFilter.MostRecentFilter.class.getName())) {
limitStr = subFilter.getSQL(this);
if (subFilter.getClass().getName().equals(CommunicationsFilter.MostRecentFilter.class.getName())) {
limitStr = subFilter.getSQL(this);
break;
}
}
}
return limitStr;
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment