19 package org.sleuthkit.autopsy.report.caseuco;
 
   21 import com.fasterxml.jackson.core.JsonEncoding;
 
   22 import com.fasterxml.jackson.core.JsonFactory;
 
   23 import com.fasterxml.jackson.core.JsonGenerator;
 
   24 import com.fasterxml.jackson.core.util.DefaultIndenter;
 
   25 import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
 
   26 import com.google.common.collect.Lists;
 
   28 import java.io.IOException;
 
   29 import java.nio.file.Files;
 
   30 import java.nio.file.Path;
 
   31 import java.nio.file.Paths;
 
   32 import java.sql.ResultSet;
 
   33 import java.sql.SQLException;
 
   34 import java.util.List;
 
   35 import java.util.SimpleTimeZone;
 
   36 import java.util.TimeZone;
 
   37 import java.util.logging.Level;
 
   38 import org.apache.commons.io.FileUtils;
 
   39 import org.openide.util.NbBundle;
 
   67     private static final BlackboardAttribute.Type 
SET_NAME = 
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME);
 
   68     private static final BlackboardArtifact.ARTIFACT_TYPE 
INTERESTING_FILE_HIT = BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT;
 
   69     private static final BlackboardArtifact.ARTIFACT_TYPE 
INTERESTING_ARTIFACT_HIT = BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT;
 
   84         "ReportCaseUco.noCaseOpen=Unable to open currect case",
 
   85         "ReportCaseUco.unableToCreateDirectories=Unable to create directory for CASE-UCO report",
 
   86         "ReportCaseUco.initializing=Creating directories...",
 
   87         "ReportCaseUco.querying=Querying files...",
 
   88         "ReportCaseUco.ingestWarning=Warning, this report will be created before ingest services completed",
 
   89         "ReportCaseUco.processing=Saving files in CASE-UCO format...",
 
   90         "ReportCaseUco.srcModuleName.text=CASE-UCO Report" 
   92     @SuppressWarnings(
"deprecation")
 
   97         progressPanel.
start();
 
  101         JsonFactory jsonGeneratorFactory = 
new JsonFactory();
 
  102         java.io.File reportFile = Paths.get(reportOutputPath).toFile();
 
  104             Files.createDirectories(Paths.get(reportFile.getParent()));
 
  105         } 
catch (IOException ex) {
 
  106             logger.log(Level.SEVERE, 
"Unable to create directory for CASE-UCO report", ex); 
 
  117         JsonGenerator jsonGenerator = null;
 
  118         SimpleTimeZone timeZone = 
new SimpleTimeZone(0, 
"GMT");
 
  120             jsonGenerator = jsonGeneratorFactory.createGenerator(reportFile, JsonEncoding.UTF8);
 
  122             jsonGenerator.setPrettyPrinter(
new DefaultPrettyPrinter().withObjectIndenter(
new DefaultIndenter(
"  ", 
"\n")));
 
  132             String caseTraceId = 
saveCaseInfo(skCase, jsonGenerator);
 
  135             String dataSourceTraceId = 
saveDataSourceInfo(selectedDataSourceId, caseTraceId, skCase, jsonGenerator);
 
  138             final String getAllFilesQuery = 
"select obj_id, name, size, crtime, atime, mtime, md5, parent_path, mime_type, extension from tsk_files where " 
  139                     + 
"data_source_obj_id = " + Long.toString(selectedDataSourceId)
 
  140                     + 
" AND ((meta_type = " + TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_UNDEF.getValue()
 
  141                     + 
") OR (meta_type = " + TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_REG.getValue()
 
  142                     + 
") OR (meta_type = " + TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_VIRT.getValue() + 
"))"; 
 
  144             try (SleuthkitCase.CaseDbQuery queryResult = skCase.executeQuery(getAllFilesQuery)) {
 
  145                 ResultSet resultSet = queryResult.getResultSet();
 
  150                 while (resultSet.next()) {
 
  156                     Long objectId = resultSet.getLong(1);
 
  157                     String fileName = resultSet.getString(2);
 
  158                     long size = resultSet.getLong(
"size");
 
  162                     String md5Hash = resultSet.getString(
"md5");
 
  163                     String parent_path = resultSet.getString(
"parent_path");
 
  164                     String mime_type = resultSet.getString(
"mime_type");
 
  165                     String extension = resultSet.getString(
"extension");
 
  167                     saveFileInCaseUcoFormat(objectId, fileName, parent_path, md5Hash, mime_type, size, crtime, atime, mtime, extension, jsonGenerator, dataSourceTraceId);
 
  177         } 
catch (TskCoreException ex) {
 
  178             logger.log(Level.SEVERE, 
"Failed to get list of files from case database", ex); 
 
  180         } 
catch (IOException ex) {
 
  181             logger.log(Level.SEVERE, 
"Failed to create JSON output for the CASE-UCO report", ex); 
 
  183         } 
catch (SQLException ex) {
 
  184             logger.log(Level.WARNING, 
"Unable to read result set", ex); 
 
  187             logger.log(Level.SEVERE, 
"No current case open", ex); 
 
  190             if (jsonGenerator != null) {
 
  192                     jsonGenerator.close();
 
  193                 } 
catch (IOException ex) {
 
  194                     logger.log(Level.WARNING, 
"Failed to close JSON output file", ex); 
 
  215         "CaseUcoFormatExporter.startMsg=Generating CASE-UCO Report",
 
  216         "CaseUcoFormatExporter.datasourceMsg=Generating CASE-UCO Report for %s",
 
  217         "CaseUcoFormatExporter.finishMsg=Finished generating CASE-UCO Report" 
  219     public static void export(List<TagName> tagTypes, List<String> interestingItemSets,
 
  220             File caseReportFolder, 
ReportProgressPanel progressPanel) 
throws IOException, SQLException,
 
  231         Path tmpDir = Paths.get(caseTempDirectory, TEMP_DIR_NAME);
 
  232         FileUtils.deleteDirectory(tmpDir.toFile());
 
  233         Files.createDirectory(tmpDir);
 
  236         Path reportFile = Paths.get(caseReportFolder.toString(), 
 
  240         SimpleTimeZone timeZone = 
new SimpleTimeZone(0, 
"GMT");
 
  245             String caseTraceId = 
saveCaseInfo(skCase, jsonGenerator);
 
  247             for (DataSource ds : skCase.getDataSources()) {
 
  249                         Bundle.CaseUcoFormatExporter_datasourceMsg(), ds.getName()));
 
  251                         caseTraceId, skCase, jsonGenerator);
 
  252                 for (TagName tn : tagTypes) {
 
  255                                 jsonGenerator, timeZone, dataSourceTraceId);
 
  259                                 jsonGenerator, timeZone, dataSourceTraceId);
 
  262                 if(!interestingItemSets.isEmpty()) {
 
  263                     List<BlackboardArtifact.ARTIFACT_TYPE> typesToQuery = Lists.newArrayList(
 
  265                     for(BlackboardArtifact.ARTIFACT_TYPE artType : typesToQuery) {
 
  266                         for(BlackboardArtifact bArt : skCase.getBlackboardArtifacts(artType)) {
 
  267                             if(bArt.getDataSource().getId() != ds.getId()) {
 
  270                             BlackboardAttribute setAttr = bArt.getAttribute(
SET_NAME);
 
  271                             if (interestingItemSets.contains(setAttr.getValueString())) {
 
  272                                 Content content = skCase.getContentById(bArt.getObjectID());
 
  274                                         jsonGenerator, timeZone, dataSourceTraceId);
 
  298             TimeZone timeZone, String dataSourceTraceId) 
throws IOException {
 
  299         if (content instanceof AbstractFile && !(content instanceof DataSource)) {
 
  300             AbstractFile absFile = (AbstractFile) content;
 
  301             Path filePath = tmpDir.resolve(Long.toString(absFile.getId()));
 
  302             if (!Files.exists(filePath) && !absFile.isDir()) {
 
  306                         absFile.getParentPath(),
 
  307                         absFile.getMd5Hash(),
 
  308                         absFile.getMIMEType(),
 
  313                         absFile.getNameExtension(),
 
  317                 filePath.toFile().createNewFile();
 
  323         JsonFactory jsonGeneratorFactory = 
new JsonFactory();
 
  324         JsonGenerator jsonGenerator = jsonGeneratorFactory.createGenerator(reportFile, JsonEncoding.UTF8);
 
  326         jsonGenerator.setPrettyPrinter(
new DefaultPrettyPrinter().withObjectIndenter(
new DefaultIndenter(
"  ", 
"\n")));
 
  327         return jsonGenerator;
 
  331         catalog.writeStartObject();
 
  332         catalog.writeFieldName(
"@graph");
 
  333         catalog.writeStartArray();
 
  337         catalog.writeEndArray();
 
  338         catalog.writeEndObject();
 
  352     private static String 
saveCaseInfo(SleuthkitCase skCase, JsonGenerator catalog) 
throws TskCoreException, SQLException, IOException, NoCurrentCaseException {
 
  355         String uniqueCaseName;
 
  357         TskData.DbType dbType = skCase.getDatabaseType();
 
  358         if (dbType == TskData.DbType.SQLITE) {
 
  360             dbFileName = skCase.getDatabaseName();
 
  362             uniqueCaseName = skCase.getDatabaseName();
 
  366         String caseDirPath = skCase.getDbDirPath();
 
  367         String caseTraceId = 
"case-" + uniqueCaseName;
 
  368         catalog.writeStartObject();
 
  369         catalog.writeStringField(
"@id", caseTraceId);
 
  370         catalog.writeStringField(
"@type", 
"Trace");
 
  372         catalog.writeFieldName(
"propertyBundle");
 
  373         catalog.writeStartArray();
 
  374         catalog.writeStartObject();
 
  377         caseDirPath = caseDirPath.replaceAll(
"\\\\", 
"/");
 
  379         catalog.writeStringField(
"@type", 
"File");
 
  380         if (dbType == TskData.DbType.SQLITE) {
 
  381             catalog.writeStringField(
"filePath", caseDirPath + 
"/" + dbFileName);
 
  382             catalog.writeBooleanField(
"isDirectory", 
false);
 
  384             catalog.writeStringField(
"filePath", caseDirPath);
 
  385             catalog.writeBooleanField(
"isDirectory", 
true);
 
  387         catalog.writeEndObject();
 
  389         catalog.writeEndArray();
 
  390         catalog.writeEndObject();
 
  407     private static String 
saveDataSourceInfo(Long selectedDataSourceId, String caseTraceId, SleuthkitCase skCase, JsonGenerator jsonGenerator) 
throws TskCoreException, SQLException, IOException {
 
  409         Long imageSize = (long) 0;
 
  410         String imageName = 
"";
 
  411         boolean isImageDataSource = 
false;
 
  412         String getImageDataSourceQuery = 
"select size from tsk_image_info where obj_id = " + selectedDataSourceId;
 
  413         try (SleuthkitCase.CaseDbQuery queryResult = skCase.executeQuery(getImageDataSourceQuery)) {
 
  414             ResultSet resultSet = queryResult.getResultSet();
 
  416             while (resultSet.next()) {
 
  418                 imageSize = resultSet.getLong(1);
 
  419                 isImageDataSource = 
true;
 
  424         if (isImageDataSource) {
 
  426             String getPathToDataSourceQuery = 
"select name from tsk_image_names where obj_id = " + selectedDataSourceId;
 
  427             try (SleuthkitCase.CaseDbQuery queryResult = skCase.executeQuery(getPathToDataSourceQuery)) {
 
  428                 ResultSet resultSet = queryResult.getResultSet();
 
  429                 while (resultSet.next()) {
 
  430                     imageName = resultSet.getString(1);
 
  436             String getLogicalDataSourceQuery = 
"select name from tsk_files where obj_id = " + selectedDataSourceId;
 
  437             try (SleuthkitCase.CaseDbQuery queryResult = skCase.executeQuery(getLogicalDataSourceQuery)) {
 
  438                 ResultSet resultSet = queryResult.getResultSet();
 
  439                 while (resultSet.next()) {
 
  440                     imageName = resultSet.getString(1);
 
  449     private static String 
saveDataSourceInCaseUcoFormat(JsonGenerator catalog, String imageName, Long imageSize, Long selectedDataSourceId, String caseTraceId) 
throws IOException {
 
  452         String dataSourceTraceId = 
"data-source-" + selectedDataSourceId;
 
  453         catalog.writeStartObject();
 
  454         catalog.writeStringField(
"@id", dataSourceTraceId);
 
  455         catalog.writeStringField(
"@type", 
"Trace");
 
  457         catalog.writeFieldName(
"propertyBundle");
 
  458         catalog.writeStartArray();
 
  460         catalog.writeStartObject();
 
  461         catalog.writeStringField(
"@type", 
"File");
 
  464         imageName = imageName.replaceAll(
"\\\\", 
"/");
 
  466         catalog.writeStringField(
"filePath", imageName);
 
  467         catalog.writeEndObject();
 
  470             catalog.writeStartObject();
 
  471             catalog.writeStringField(
"@type", 
"ContentData");
 
  472             catalog.writeStringField(
"sizeInBytes", Long.toString(imageSize));
 
  473             catalog.writeEndObject();
 
  476         catalog.writeEndArray();
 
  477         catalog.writeEndObject();
 
  480         catalog.writeStartObject();
 
  481         catalog.writeStringField(
"@id", 
"relationship-" + caseTraceId);
 
  482         catalog.writeStringField(
"@type", 
"Relationship");
 
  483         catalog.writeStringField(
"source", dataSourceTraceId);
 
  484         catalog.writeStringField(
"target", caseTraceId);
 
  485         catalog.writeStringField(
"kindOfRelationship", 
"contained-within");
 
  486         catalog.writeBooleanField(
"isDirectional", 
true);
 
  488         catalog.writeFieldName(
"propertyBundle");
 
  489         catalog.writeStartArray();
 
  490         catalog.writeStartObject();
 
  491         catalog.writeStringField(
"@type", 
"PathRelation");
 
  492         catalog.writeStringField(
"path", imageName);
 
  493         catalog.writeEndObject();
 
  494         catalog.writeEndArray();
 
  496         catalog.writeEndObject();
 
  498         return dataSourceTraceId;
 
  501     private static void saveFileInCaseUcoFormat(Long objectId, String fileName, String parent_path, String md5Hash, String mime_type, 
long size, String ctime,
 
  502             String atime, String mtime, String extension, JsonGenerator catalog, String dataSourceTraceId) 
throws IOException {
 
  504         String fileTraceId = 
"file-" + objectId;
 
  507         catalog.writeStartObject();
 
  508         catalog.writeStringField(
"@id", fileTraceId);
 
  509         catalog.writeStringField(
"@type", 
"Trace");
 
  511         catalog.writeFieldName(
"propertyBundle");
 
  512         catalog.writeStartArray();
 
  514         catalog.writeStartObject();
 
  515         catalog.writeStringField(
"@type", 
"File");
 
  516         catalog.writeStringField(
"createdTime", ctime);
 
  517         catalog.writeStringField(
"accessedTime", atime);
 
  518         catalog.writeStringField(
"modifiedTime", mtime);
 
  519         if (extension != null) {
 
  520             catalog.writeStringField(
"extension", extension);
 
  522         catalog.writeStringField(
"fileName", fileName);
 
  523         if (parent_path != null) {
 
  524             catalog.writeStringField(
"filePath", parent_path + fileName);
 
  526         catalog.writeBooleanField(
"isDirectory", 
false);
 
  527         catalog.writeStringField(
"sizeInBytes", Long.toString(size));
 
  528         catalog.writeEndObject();
 
  530         catalog.writeStartObject();
 
  531         catalog.writeStringField(
"@type", 
"ContentData");
 
  532         if (mime_type != null) {
 
  533             catalog.writeStringField(
"mimeType", mime_type);
 
  535         if (md5Hash != null) {
 
  536             catalog.writeFieldName(
"hash");
 
  537             catalog.writeStartArray();
 
  538             catalog.writeStartObject();
 
  539             catalog.writeStringField(
"@type", 
"Hash");
 
  540             catalog.writeStringField(
"hashMethod", 
"MD5");
 
  541             catalog.writeStringField(
"hashValue", md5Hash);
 
  542             catalog.writeEndObject();
 
  543             catalog.writeEndArray();
 
  545         catalog.writeStringField(
"sizeInBytes", Long.toString(size));
 
  547         catalog.writeEndObject();
 
  549         catalog.writeEndArray();
 
  550         catalog.writeEndObject();
 
  553         catalog.writeStartObject();
 
  554         catalog.writeStringField(
"@id", 
"relationship-" + objectId);
 
  555         catalog.writeStringField(
"@type", 
"Relationship");
 
  556         catalog.writeStringField(
"source", fileTraceId);
 
  557         catalog.writeStringField(
"target", dataSourceTraceId);
 
  558         catalog.writeStringField(
"kindOfRelationship", 
"contained-within");
 
  559         catalog.writeBooleanField(
"isDirectional", 
true);
 
  561         catalog.writeFieldName(
"propertyBundle");
 
  562         catalog.writeStartArray();
 
  563         catalog.writeStartObject();
 
  564         catalog.writeStringField(
"@type", 
"PathRelation");
 
  565         if (parent_path != null) {
 
  566             catalog.writeStringField(
"path", parent_path + fileName);
 
  568             catalog.writeStringField(
"path", fileName);
 
  570         catalog.writeEndObject();
 
  571         catalog.writeEndArray();
 
  573         catalog.writeEndObject();
 
static synchronized IngestManager getInstance()
 
String getTempDirectory()
 
static void warn(String message)
 
static String getReportFileName()
 
void complete(ReportStatus reportStatus)
 
boolean isIngestRunning()
 
void addReport(String localPath, String srcModuleName, String reportName)
 
void setIndeterminate(boolean indeterminate)
 
static String getStringTimeISO8601(long epochSeconds, TimeZone tzone)
 
TagsManager getTagsManager()
 
SleuthkitCase getSleuthkitCase()
 
synchronized static Logger getLogger(String name)
 
static Case getCurrentCaseThrows()
 
void updateStatusLabel(String statusMessage)
 
static void error(String message)