Autopsy  4.20.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
LocalFilesDSProcessor.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2011-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.casemodule;
20 
21 import java.io.File;
22 import java.io.IOException;
23 import java.nio.file.Path;
24 import java.nio.file.Paths;
25 import java.util.ArrayList;
26 import java.util.Arrays;
27 import java.util.List;
28 import java.util.UUID;
29 import java.util.logging.Level;
30 import javax.swing.JPanel;
31 import javax.swing.filechooser.FileFilter;
32 import org.apache.commons.io.FilenameUtils;
33 import org.openide.modules.InstalledFileLocator;
34 import org.openide.util.NbBundle;
35 import org.openide.util.NbBundle.Messages;
36 import org.openide.util.lookup.ServiceProvider;
37 import org.openide.util.lookup.ServiceProviders;
45 import org.sleuthkit.datamodel.Host;
46 import org.sleuthkit.datamodel.TskCoreException;
47 
54 @ServiceProviders(value = {
55  @ServiceProvider(service = DataSourceProcessor.class),
56  @ServiceProvider(service = AutoIngestDataSourceProcessor.class)
57 })
58 @Messages({
59  "LocalFilesDSProcessor.logicalEvidenceFilter.desc=Logical Evidence Files (L01)"
60 })
62 
63  private static final String DATA_SOURCE_TYPE = NbBundle.getMessage(LocalFilesDSProcessor.class, "LocalFilesDSProcessor.dsType");
64  private static final Logger logger = Logger.getLogger(LocalFilesDSProcessor.class.getName());
65  private final LogicalFilesDspPanel configPanel;
66  private static final String L01_EXTRACTION_DIR = "L01";
67  private static final String UNIQUENESS_CONSTRAINT_SEPERATOR = "_";
68  private static final String EWFEXPORT_DIR = "ewfexport_exec"; // NON-NLS
69  private static final String EWFEXPORT_32_BIT_DIR = "32-bit"; // NON-NLS
70  private static final String EWFEXPORT_64_BIT_DIR = "64-bit"; // NON-NLS
71  private static final String EWFEXPORT_WINDOWS_EXE = "ewfexport.exe"; // NON-NLS
72  private static final String LOG_FILE_EXTENSION = ".txt";
73  private static final List<String> LOGICAL_EVIDENCE_EXTENSIONS = Arrays.asList(".l01");
74  private static final String LOGICAL_EVIDENCE_DESC = Bundle.LocalFilesDSProcessor_logicalEvidenceFilter_desc();
75  private static final GeneralFilter LOGICAL_EVIDENCE_FILTER = new GeneralFilter(LOGICAL_EVIDENCE_EXTENSIONS, LOGICAL_EVIDENCE_DESC);
76  /*
77  * TODO: Remove the setDataSourceOptionsCalled flag and the settings fields
78  * when the deprecated method setDataSourceOptions is removed.
79  */
80  private List<String> localFilePaths;
81 
89  configPanel = LogicalFilesDspPanel.getDefault();
90  }
91 
99  public static String getType() {
100  return DATA_SOURCE_TYPE;
101  }
102 
110  @Override
111  public String getDataSourceType() {
112  return DATA_SOURCE_TYPE;
113  }
114 
123  @Override
124  public JPanel getPanel() {
125  configPanel.select();
126  return configPanel;
127  }
128 
136  @Override
137  public boolean isPanelValid() {
138  return configPanel.validatePanel();
139  }
140 
155  @Override
156  public void run(DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
157  run(null, progressMonitor, callback);
158  }
159 
175  @Override
176  public void run(Host host, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
177 
178  localFilePaths = configPanel.getContentPaths();
179  boolean createTimestamp = configPanel.getCreateTimestamp();
180  boolean modifiedTimestamp = configPanel.getModifiedTimestamp();
181  boolean accessTimestamp = configPanel.getAccessTimestamp();
182  if (configPanel.subTypeIsLogicalEvidencePanel()) {
183  try {
184  //if the L01 option was chosen
185  localFilePaths = extractLogicalEvidenceFileContents(localFilePaths);
186  } catch (L01Exception ex) {
187  //contents of l01 could not be extracted don't add data source or run ingest
188  final List<String> errors = new ArrayList<>();
189  errors.add(ex.getMessage());
190  callback.done(DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS, errors, new ArrayList<>());
191  return;
192  } catch (NoCurrentCaseException ex) {
193  logger.log(Level.WARNING, "Exception while getting open case.", ex);
194  return;
195  }
196  }
197  run(UUID.randomUUID().toString(), configPanel.getFileSetName(), localFilePaths, host, createTimestamp,
198  accessTimestamp, modifiedTimestamp, progressMonitor, callback);
199  }
200 
213  private List<String> extractLogicalEvidenceFileContents(final List<String> logicalEvidenceFilePaths) throws L01Exception, NoCurrentCaseException {
214  final List<String> extractedPaths = new ArrayList<>();
215  Path ewfexportPath;
216  ewfexportPath = locateEwfexportExecutable();
217  List<String> command = new ArrayList<>();
218  for (final String l01Path : logicalEvidenceFilePaths) {
219  command.clear();
220  command.add(ewfexportPath.toAbsolutePath().toString());
221  command.add("-f");
222  command.add("files");
223  command.add("-t");
224  File l01Dir = new File(Case.getCurrentCaseThrows().getModuleDirectory(), L01_EXTRACTION_DIR);
225  if (!l01Dir.exists()) {
226  l01Dir.mkdirs();
227  }
228  Path dirPath = Paths.get(FilenameUtils.getBaseName(l01Path) + UNIQUENESS_CONSTRAINT_SEPERATOR + System.currentTimeMillis());
229 
230  command.add(dirPath.toString());
231  command.add(l01Path);
232  ProcessBuilder processBuilder = new ProcessBuilder(command);
233  processBuilder.directory(l01Dir);
234  try {
235  //redirect ewfexport stdout and stderr to txt file
236  Path logFileName = Paths.get(l01Dir.toString(), dirPath.toString() + LOG_FILE_EXTENSION);
237  File logFile = new File(logFileName.toString());
238  Path errFileName = Paths.get(l01Dir.toString(), dirPath.toString() + LOG_FILE_EXTENSION);
239  File errFile = new File(errFileName.toString());
240  processBuilder.redirectError(ProcessBuilder.Redirect.appendTo(errFile));
241  processBuilder.redirectOutput(ProcessBuilder.Redirect.appendTo(logFile));
242  // open the file with ewfexport to extract its contents
243  ExecUtil.execute(processBuilder, new ExecUtil.TimedProcessTerminator());
244  if (l01Dir.toPath().resolve(dirPath).toFile().exists()) {
245  extractedPaths.add(l01Dir.toPath().resolve(dirPath).toString());
246  } else { //if we failed to extract anything let the user know the L01 file was unable to be processed
247  throw new L01Exception("Can not process the selected L01 file, ewfExport was unable to extract any files from it.");
248  }
249 
250  } catch (SecurityException ex) {
251  throw new L01Exception("Security exception occcured while trying to extract l01 contents", ex);
252  } catch (IOException ex) {
253  throw new L01Exception("IOException occcured while trying to extract l01 contents", ex);
254  }
255  }
256  return extractedPaths;
257  }
258 
264  static FileFilter getLogicalEvidenceFilter() {
265  return LOGICAL_EVIDENCE_FILTER;
266  }
267 
276  private Path locateEwfexportExecutable() throws L01Exception {
277  // Must be running under a Windows operating system.
278  if (!PlatformUtil.isWindowsOS()) {
279  throw new L01Exception("L01 files are only supported on windows currently");
280  }
281 
282  // Build the expected path to either the 32-bit or 64-bit version of the
283  // ewfexport executable.
284  final File ewfRoot = InstalledFileLocator.getDefault().locate(EWFEXPORT_DIR, LocalFilesDSProcessor.class.getPackage().getName(), false);
285 
286  Path executablePath;
287  if (PlatformUtil.is64BitOS()) {
288  executablePath = Paths.get(
289  ewfRoot.getAbsolutePath(),
290  EWFEXPORT_64_BIT_DIR,
291  EWFEXPORT_WINDOWS_EXE);
292  } else {
293  executablePath = Paths.get(
294  ewfRoot.getAbsolutePath(),
295  EWFEXPORT_32_BIT_DIR,
296  EWFEXPORT_WINDOWS_EXE);
297  }
298 
299  // Make sure the executable exists at the expected location and that it
300  // can be run.
301  final File ewfexport = executablePath.toFile();
302  if (null == ewfexport || !ewfexport.exists()) {
303  throw new LocalFilesDSProcessor.L01Exception("EWF export executable was not found");
304  }
305  if (!ewfexport.canExecute()) {
306  throw new LocalFilesDSProcessor.L01Exception("EWF export executable can not be executed");
307  }
308 
309  return executablePath;
310  }
311 
336  public void run(String deviceId, String rootVirtualDirectoryName, List<String> localFilePaths, Host host, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
337  new Thread(new AddLocalFilesTask(deviceId, rootVirtualDirectoryName, localFilePaths, host, false, false, false,progressMonitor, callback)).start();
338  }
339 
367  public void run(String deviceId, String rootVirtualDirectoryName, List<String> localFilePaths, Host host, boolean createTimestamp, boolean accessTimestamp,
368  boolean modifiedTimestamp, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
369  new Thread(new AddLocalFilesTask(deviceId, rootVirtualDirectoryName, localFilePaths, host, createTimestamp, accessTimestamp, modifiedTimestamp,
370  progressMonitor, callback)).start();
371  }
372 
396  public void run(String deviceId, String rootVirtualDirectoryName, List<String> localFilePaths, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
397  run(deviceId, rootVirtualDirectoryName, localFilePaths, null, progressMonitor, callback);
398  }
399 
410  @Override
411  public void cancel() {
412  }
413 
418  @Override
419  public void reset() {
420  configPanel.select();
421  localFilePaths = null;
422  }
423 
424  @Override
425  public int canProcess(Path dataSourcePath) throws AutoIngestDataSourceProcessorException {
426  // Local files DSP can process any file by simply adding it as a logical file.
427  // It should return lowest possible non-zero confidence level and be treated
428  // as the "option of last resort" for auto ingest purposes
429 
430  List<String> filePaths = Arrays.asList(new String[]{dataSourcePath.toString()});
431  //If there is only 1 file check if it is an L01 file and if it is extract the
432  //contents and replace the paths, if the contents can't be extracted return 0
433  if (filePaths.size() == 1) {
434  for (final String path : filePaths) {
435  if (new File(path).isFile() && LOGICAL_EVIDENCE_FILTER.accept(new File(path))) {
436  try {
437  //if the L01 option was chosen
438  filePaths = extractLogicalEvidenceFileContents(filePaths);
439  } catch (L01Exception ex) {
440  logger.log(Level.WARNING, "File extension was .l01 but contents of logical evidence file were unable to be extracted", ex);
441  //contents of l01 could not be extracted don't add data source or run ingest
442  return 0;
443  } catch (NoCurrentCaseException ex) {
444  logger.log(Level.WARNING, "Exception while getting open case.", ex);
445  return 0;
446  }
447  }
448  }
449  }
450  return 1;
451  }
452 
453  @Override
454  public void process(String deviceId, Path dataSourcePath, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack) {
455  process(deviceId, dataSourcePath, null, progressMonitor, callBack);
456  }
457 
458  @Override
459  public void process(String deviceId, Path dataSourcePath, Host host, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack) {
460  List<String> filePaths = Arrays.asList(new String[]{dataSourcePath.toString()});
461  run(deviceId, "", filePaths, host, progressMonitor, callBack);
462  }
463 
467  private final class L01Exception extends Exception {
468 
469  private static final long serialVersionUID = 1L;
470 
471  L01Exception(final String message) {
472  super(message);
473  }
474 
475  L01Exception(final String message, final Throwable cause) {
476  super(message, cause);
477  }
478  }
479 
480 }
void run(DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback)
static int execute(ProcessBuilder processBuilder)
Definition: ExecUtil.java:172
void run(String deviceId, String rootVirtualDirectoryName, List< String > localFilePaths, Host host, boolean createTimestamp, boolean accessTimestamp, boolean modifiedTimestamp, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback)
void process(String deviceId, Path dataSourcePath, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack)
void done(DataSourceProcessorResult result, List< String > errList, List< Content > newDataSources)
List< String > extractLogicalEvidenceFileContents(final List< String > logicalEvidenceFilePaths)
void run(String deviceId, String rootVirtualDirectoryName, List< String > localFilePaths, Host host, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback)
synchronized static Logger getLogger(String name)
Definition: Logger.java:124
void process(String deviceId, Path dataSourcePath, Host host, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack)
void run(String deviceId, String rootVirtualDirectoryName, List< String > localFilePaths, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback)
void run(Host host, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback)

Copyright © 2012-2022 Basis Technology. Generated on: Tue Aug 1 2023
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.