Sleuth Kit Java Bindings (JNI)  4.6
Java bindings for using The Sleuth Kit
Blackboard.java
Go to the documentation of this file.
1 /*
2  * Sleuth Kit Data Model
3  *
4  * Copyright 2018 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.datamodel;
20 
21 import com.google.common.collect.ImmutableSet;
22 import java.sql.ResultSet;
23 import java.sql.SQLException;
24 import java.sql.Statement;
25 import java.util.ArrayList;
26 import java.util.Arrays;
27 import java.util.Collection;
28 import java.util.Collections;
29 import java.util.HashSet;
30 import java.util.List;
31 import java.util.Objects;
32 import java.util.Set;
33 import java.util.stream.Collectors;
34 
39 public final class Blackboard {
40 
41  private final SleuthkitCase caseDb;
42 
49  Blackboard(SleuthkitCase casedb) {
50  this.caseDb = Objects.requireNonNull(casedb, "Cannot create Blackboard for null SleuthkitCase");
51  }
52 
64  public void postArtifact(BlackboardArtifact artifact, String moduleName) throws BlackboardException {
65  postArtifacts(Collections.singleton(artifact), moduleName);
66  }
67 
83  public void postArtifacts(Collection<BlackboardArtifact> artifacts, String moduleName) throws BlackboardException {
84  /*
85  * For now this just processes them one by one, but in the future it
86  * could be smarter and use transactions, etc.
87  */
88  for (BlackboardArtifact artifact : artifacts) {
89  try {
90  caseDb.getTimelineManager().addArtifactEvents(artifact);
91  } catch (TskCoreException ex) {
92  throw new BlackboardException("Failed to add events for artifact: " + artifact, ex);
93  }
94  }
95 
96  caseDb.fireTSKEvent(new ArtifactsPostedEvent(artifacts, moduleName));
97  }
98 
111  public BlackboardArtifact.Type getOrAddArtifactType(String typeName, String displayName) throws BlackboardException {
112 
113  try {
114  return caseDb.addBlackboardArtifactType(typeName, displayName);
115  } catch (TskDataException typeExistsEx) {
116  try {
117  return caseDb.getArtifactType(typeName);
118  } catch (TskCoreException ex) {
119  throw new BlackboardException("Failed to get or add artifact type", ex);
120  }
121  } catch (TskCoreException ex) {
122  throw new BlackboardException("Failed to get or add artifact type", ex);
123  }
124  }
125 
140 
141  try {
142  return caseDb.addArtifactAttributeType(typeName, valueType, displayName);
143  } catch (TskDataException typeExistsEx) {
144  try {
145  return caseDb.getAttributeType(typeName);
146  } catch (TskCoreException ex) {
147  throw new BlackboardException("Failed to get or add attribute type", ex);
148  }
149  } catch (TskCoreException ex) {
150  throw new BlackboardException("Failed to get or add attribute type", ex);
151  }
152  }
153 
165  public List<BlackboardArtifact.Type> getArtifactTypesInUse(long dataSourceObjId) throws TskCoreException {
166 
167  final String queryString = "SELECT DISTINCT arts.artifact_type_id AS artifact_type_id, "
168  + "types.type_name AS type_name, types.display_name AS display_name "
169  + "FROM blackboard_artifact_types AS types "
170  + "INNER JOIN blackboard_artifacts AS arts "
171  + "ON arts.artifact_type_id = types.artifact_type_id "
172  + "WHERE arts.data_source_obj_id = " + dataSourceObjId;
173 
175  try (SleuthkitCase.CaseDbConnection connection = caseDb.getConnection();
176  Statement statement = connection.createStatement();
177  ResultSet resultSet = connection.executeQuery(statement, queryString);) {
178 
179  List<BlackboardArtifact.Type> uniqueArtifactTypes = new ArrayList<>();
180  while (resultSet.next()) {
181  uniqueArtifactTypes.add(new BlackboardArtifact.Type(resultSet.getInt("artifact_type_id"),
182  resultSet.getString("type_name"), resultSet.getString("display_name")));
183  }
184  return uniqueArtifactTypes;
185  } catch (SQLException ex) {
186  throw new TskCoreException("Error getting artifact types is use for data source." + ex.getMessage(), ex);
187  } finally {
189  }
190  }
191 
204  public long getArtifactsCount(int artifactTypeID, long dataSourceObjId) throws TskCoreException {
205  return getArtifactsCountHelper(artifactTypeID,
206  "blackboard_artifacts.data_source_obj_id = '" + dataSourceObjId + "';");
207  }
208 
221  public List<BlackboardArtifact> getArtifacts(int artifactTypeID, long dataSourceObjId) throws TskCoreException {
222  return caseDb.getArtifactsHelper("blackboard_artifacts.data_source_obj_id = " + dataSourceObjId
223  + " AND blackboard_artifact_types.artifact_type_id = " + artifactTypeID + ";");
224  }
225 
238  private long getArtifactsCountHelper(int artifactTypeID, String whereClause) throws TskCoreException {
239  String queryString = "SELECT COUNT(*) AS count FROM blackboard_artifacts "
240  + "WHERE blackboard_artifacts.artifact_type_id = " + artifactTypeID
241  + " AND blackboard_artifacts.review_status_id !=" + BlackboardArtifact.ReviewStatus.REJECTED.getID()
242  + " AND " + whereClause;
243 
245  try (SleuthkitCase.CaseDbConnection connection = caseDb.getConnection();
246  Statement statement = connection.createStatement();
247  ResultSet resultSet = connection.executeQuery(statement, queryString);) {
248  //NON-NLS
249  long count = 0;
250  if (resultSet.next()) {
251  count = resultSet.getLong("count");
252  }
253  return count;
254  } catch (SQLException ex) {
255  throw new TskCoreException("Error getting artifact types is use for data source." + ex.getMessage(), ex);
256  } finally {
258  }
259  }
260 
261  /*
262  * Determine if an artifact of a given type exists for given content with a
263  * specific list of attributes.
264  *
265  * @param content The content whose artifacts need to be looked at. @param
266  * artifactType The type of artifact to look for. @param attributesList The
267  * list of attributes to look for.
268  *
269  * @return True if the specific artifact exists; otherwise false.
270  *
271  * @throws TskCoreException If there is a problem getting artifacts or
272  * attributes.
273  */
274  public boolean artifactExists(Content content, BlackboardArtifact.ARTIFACT_TYPE artifactType,
275  Collection<BlackboardAttribute> attributesList) throws TskCoreException {
276 
277  ArrayList<BlackboardArtifact> artifactsList;
278 
279  /*
280  * Get the content's artifacts.
281  */
282  artifactsList = content.getArtifacts(artifactType);
283  if (artifactsList.isEmpty()) {
284  return false;
285  }
286 
287  /*
288  * Get each artifact's attributes and analyze them for matches.
289  */
290  for (BlackboardArtifact artifact : artifactsList) {
291  if (attributesMatch(artifact.getAttributes(), attributesList)) {
292  /*
293  * The exact artifact exists, so we don't need to look any
294  * further.
295  */
296  return true;
297  }
298  }
299 
300  /*
301  * None of the artifacts have the exact set of attribute type/value
302  * combinations. The provided content does not have the artifact being
303  * sought.
304  */
305  return false;
306  }
307 
317  private boolean attributesMatch(Collection<BlackboardAttribute> fileAttributesList, Collection<BlackboardAttribute> expectedAttributesList) {
318  for (BlackboardAttribute expectedAttribute : expectedAttributesList) {
319  boolean match = false;
320  for (BlackboardAttribute fileAttribute : fileAttributesList) {
321  BlackboardAttribute.Type attributeType = fileAttribute.getAttributeType();
322 
323  if (attributeType.getTypeID() != expectedAttribute.getAttributeType().getTypeID()) {
324  continue;
325  }
326 
327  Object fileAttributeValue;
328  Object expectedAttributeValue;
329  switch (attributeType.getValueType()) {
330  case BYTE:
331  fileAttributeValue = fileAttribute.getValueBytes();
332  expectedAttributeValue = expectedAttribute.getValueBytes();
333  break;
334  case DOUBLE:
335  fileAttributeValue = fileAttribute.getValueDouble();
336  expectedAttributeValue = expectedAttribute.getValueDouble();
337  break;
338  case INTEGER:
339  fileAttributeValue = fileAttribute.getValueInt();
340  expectedAttributeValue = expectedAttribute.getValueInt();
341  break;
342  case LONG: // Fall-thru
343  case DATETIME:
344  fileAttributeValue = fileAttribute.getValueLong();
345  expectedAttributeValue = expectedAttribute.getValueLong();
346  break;
347  case STRING: // Fall-thru
348  case JSON:
349  fileAttributeValue = fileAttribute.getValueString();
350  expectedAttributeValue = expectedAttribute.getValueString();
351  break;
352  default:
353  fileAttributeValue = fileAttribute.getDisplayString();
354  expectedAttributeValue = expectedAttribute.getDisplayString();
355  break;
356  }
357 
358  /*
359  * If the exact attribute was found, mark it as a match to
360  * continue looping through the expected attributes list.
361  */
362  if (fileAttributeValue instanceof byte[]) {
363  if (Arrays.equals((byte[]) fileAttributeValue, (byte[]) expectedAttributeValue)) {
364  match = true;
365  break;
366  }
367  } else if (fileAttributeValue.equals(expectedAttributeValue)) {
368  match = true;
369  break;
370  }
371  }
372  if (!match) {
373  /*
374  * The exact attribute type/value combination was not found.
375  */
376  return false;
377  }
378  }
379 
380  /*
381  * All attribute type/value combinations were found in the provided
382  * attributes list.
383  */
384  return true;
385 
386  }
387 
391  public static final class BlackboardException extends Exception {
392 
393  private static final long serialVersionUID = 1L;
394 
400  BlackboardException(String message) {
401  super(message);
402  }
403 
411  BlackboardException(String message, Throwable cause) {
412  super(message, cause);
413  }
414  }
415 
421  final public class ArtifactsPostedEvent {
422 
423  private final String moduleName;
424  private final ImmutableSet<BlackboardArtifact.Type> artifactTypes;
425  private final ImmutableSet<BlackboardArtifact> artifacts;
426 
427  private ArtifactsPostedEvent(Collection<BlackboardArtifact> artifacts, String moduleName) throws BlackboardException {
428  Set<Integer> typeIDS = artifacts.stream()
430  .collect(Collectors.toSet());
431  Set<BlackboardArtifact.Type> types = new HashSet<>();
432  for (Integer typeID : typeIDS) {
433  try {
434  types.add(caseDb.getArtifactType(typeID));
435  } catch (TskCoreException tskCoreException) {
436  throw new BlackboardException("Error getting artifact type by id.", tskCoreException);
437  }
438  }
439  artifactTypes = ImmutableSet.copyOf(types);
440  this.artifacts = ImmutableSet.copyOf(artifacts);
441  this.moduleName = moduleName;
442 
443  }
444 
445  public Collection<BlackboardArtifact> getArtifacts() {
446  return artifacts;
447  }
448 
449  public Collection<BlackboardArtifact> getArtifacts(BlackboardArtifact.Type artifactType) {
450  Set<BlackboardArtifact> tempSet = artifacts.stream()
451  .filter(artifact -> artifact.getArtifactTypeID() == artifactType.getTypeID())
452  .collect(Collectors.toSet());
453  return ImmutableSet.copyOf(tempSet);
454  }
455 
456  public String getModuleName() {
457  return moduleName;
458  }
459 
460  public Collection<BlackboardArtifact.Type> getArtifactTypes() {
461  return artifactTypes;
462  }
463  }
464 }
void postArtifact(BlackboardArtifact artifact, String moduleName)
Definition: Blackboard.java:64
void postArtifacts(Collection< BlackboardArtifact > artifacts, String moduleName)
Definition: Blackboard.java:83
Collection< BlackboardArtifact > getArtifacts()
Collection< BlackboardArtifact > getArtifacts(BlackboardArtifact.Type artifactType)
BlackboardAttribute.Type addArtifactAttributeType(String attrTypeString, TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE valueType, String displayName)
BlackboardAttribute.Type getOrAddAttributeType(String typeName, BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE valueType, String displayName)
List< BlackboardArtifact > getArtifacts(int artifactTypeID, long dataSourceObjId)
BlackboardAttribute.Type getAttributeType(String attrTypeName)
BlackboardArtifact.Type getArtifactType(String artTypeName)
boolean artifactExists(Content content, BlackboardArtifact.ARTIFACT_TYPE artifactType, Collection< BlackboardAttribute > attributesList)
Collection< BlackboardArtifact.Type > getArtifactTypes()
BlackboardArtifact.Type getOrAddArtifactType(String typeName, String displayName)
long getArtifactsCount(int artifactTypeID, long dataSourceObjId)
List< BlackboardArtifact.Type > getArtifactTypesInUse(long dataSourceObjId)
BlackboardArtifact.Type addBlackboardArtifactType(String artifactTypeName, String displayName)

Copyright © 2011-2018 Brian Carrier. (carrier -at- sleuthkit -dot- org)
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.