Autopsy  4.19.3
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  if (configPanel.subTypeIsLogicalEvidencePanel()) {
180  try {
181  //if the L01 option was chosen
182  localFilePaths = extractLogicalEvidenceFileContents(localFilePaths);
183  } catch (L01Exception ex) {
184  //contents of l01 could not be extracted don't add data source or run ingest
185  final List<String> errors = new ArrayList<>();
186  errors.add(ex.getMessage());
187  callback.done(DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS, errors, new ArrayList<>());
188  return;
189  } catch (NoCurrentCaseException ex) {
190  logger.log(Level.WARNING, "Exception while getting open case.", ex);
191  return;
192  }
193  }
194  run(UUID.randomUUID().toString(), configPanel.getFileSetName(), localFilePaths, host, progressMonitor, callback);
195  }
196 
209  private List<String> extractLogicalEvidenceFileContents(final List<String> logicalEvidenceFilePaths) throws L01Exception, NoCurrentCaseException {
210  final List<String> extractedPaths = new ArrayList<>();
211  Path ewfexportPath;
212  ewfexportPath = locateEwfexportExecutable();
213  List<String> command = new ArrayList<>();
214  for (final String l01Path : logicalEvidenceFilePaths) {
215  command.clear();
216  command.add(ewfexportPath.toAbsolutePath().toString());
217  command.add("-f");
218  command.add("files");
219  command.add("-t");
220  File l01Dir = new File(Case.getCurrentCaseThrows().getModuleDirectory(), L01_EXTRACTION_DIR);
221  if (!l01Dir.exists()) {
222  l01Dir.mkdirs();
223  }
224  Path dirPath = Paths.get(FilenameUtils.getBaseName(l01Path) + UNIQUENESS_CONSTRAINT_SEPERATOR + System.currentTimeMillis());
225 
226  command.add(dirPath.toString());
227  command.add(l01Path);
228  ProcessBuilder processBuilder = new ProcessBuilder(command);
229  processBuilder.directory(l01Dir);
230  try {
231  //redirect ewfexport stdout and stderr to txt file
232  Path logFileName = Paths.get(l01Dir.toString(), dirPath.toString() + LOG_FILE_EXTENSION);
233  File logFile = new File(logFileName.toString());
234  Path errFileName = Paths.get(l01Dir.toString(), dirPath.toString() + LOG_FILE_EXTENSION);
235  File errFile = new File(errFileName.toString());
236  processBuilder.redirectError(ProcessBuilder.Redirect.appendTo(errFile));
237  processBuilder.redirectOutput(ProcessBuilder.Redirect.appendTo(logFile));
238  // open the file with ewfexport to extract its contents
239  ExecUtil.execute(processBuilder, new ExecUtil.TimedProcessTerminator());
240  if (l01Dir.toPath().resolve(dirPath).toFile().exists()) {
241  extractedPaths.add(l01Dir.toPath().resolve(dirPath).toString());
242  } else { //if we failed to extract anything let the user know the L01 file was unable to be processed
243  throw new L01Exception("Can not process the selected L01 file, ewfExport was unable to extract any files from it.");
244  }
245 
246  } catch (SecurityException ex) {
247  throw new L01Exception("Security exception occcured while trying to extract l01 contents", ex);
248  } catch (IOException ex) {
249  throw new L01Exception("IOException occcured while trying to extract l01 contents", ex);
250  }
251  }
252  return extractedPaths;
253  }
254 
260  static FileFilter getLogicalEvidenceFilter() {
261  return LOGICAL_EVIDENCE_FILTER;
262  }
263 
272  private Path locateEwfexportExecutable() throws L01Exception {
273  // Must be running under a Windows operating system.
274  if (!PlatformUtil.isWindowsOS()) {
275  throw new L01Exception("L01 files are only supported on windows currently");
276  }
277 
278  // Build the expected path to either the 32-bit or 64-bit version of the
279  // ewfexport executable.
280  final File ewfRoot = InstalledFileLocator.getDefault().locate(EWFEXPORT_DIR, LocalFilesDSProcessor.class.getPackage().getName(), false);
281 
282  Path executablePath;
283  if (PlatformUtil.is64BitOS()) {
284  executablePath = Paths.get(
285  ewfRoot.getAbsolutePath(),
286  EWFEXPORT_64_BIT_DIR,
287  EWFEXPORT_WINDOWS_EXE);
288  } else {
289  executablePath = Paths.get(
290  ewfRoot.getAbsolutePath(),
291  EWFEXPORT_32_BIT_DIR,
292  EWFEXPORT_WINDOWS_EXE);
293  }
294 
295  // Make sure the executable exists at the expected location and that it
296  // can be run.
297  final File ewfexport = executablePath.toFile();
298  if (null == ewfexport || !ewfexport.exists()) {
299  throw new LocalFilesDSProcessor.L01Exception("EWF export executable was not found");
300  }
301  if (!ewfexport.canExecute()) {
302  throw new LocalFilesDSProcessor.L01Exception("EWF export executable can not be executed");
303  }
304 
305  return executablePath;
306  }
307 
332  public void run(String deviceId, String rootVirtualDirectoryName, List<String> localFilePaths, Host host, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
333  new Thread(new AddLocalFilesTask(deviceId, rootVirtualDirectoryName, localFilePaths, host, progressMonitor, callback)).start();
334  }
335 
359  public void run(String deviceId, String rootVirtualDirectoryName, List<String> localFilePaths, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
360  run(deviceId, rootVirtualDirectoryName, localFilePaths, null, progressMonitor, callback);
361  }
362 
373  @Override
374  public void cancel() {
375  }
376 
381  @Override
382  public void reset() {
383  configPanel.select();
384  localFilePaths = null;
385  }
386 
387  @Override
388  public int canProcess(Path dataSourcePath) throws AutoIngestDataSourceProcessorException {
389  // Local files DSP can process any file by simply adding it as a logical file.
390  // It should return lowest possible non-zero confidence level and be treated
391  // as the "option of last resort" for auto ingest purposes
392 
393  List<String> filePaths = Arrays.asList(new String[]{dataSourcePath.toString()});
394  //If there is only 1 file check if it is an L01 file and if it is extract the
395  //contents and replace the paths, if the contents can't be extracted return 0
396  if (filePaths.size() == 1) {
397  for (final String path : filePaths) {
398  if (new File(path).isFile() && LOGICAL_EVIDENCE_FILTER.accept(new File(path))) {
399  try {
400  //if the L01 option was chosen
401  filePaths = extractLogicalEvidenceFileContents(filePaths);
402  } catch (L01Exception ex) {
403  logger.log(Level.WARNING, "File extension was .l01 but contents of logical evidence file were unable to be extracted", ex);
404  //contents of l01 could not be extracted don't add data source or run ingest
405  return 0;
406  } catch (NoCurrentCaseException ex) {
407  logger.log(Level.WARNING, "Exception while getting open case.", ex);
408  return 0;
409  }
410  }
411  }
412  }
413  return 1;
414  }
415 
416  @Override
417  public void process(String deviceId, Path dataSourcePath, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack) {
418  process(deviceId, dataSourcePath, null, progressMonitor, callBack);
419  }
420 
421  @Override
422  public void process(String deviceId, Path dataSourcePath, Host host, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack) {
423  List<String> filePaths = Arrays.asList(new String[]{dataSourcePath.toString()});
424  run(deviceId, "", filePaths, host, progressMonitor, callBack);
425  }
426 
430  private final class L01Exception extends Exception {
431 
432  private static final long serialVersionUID = 1L;
433 
434  L01Exception(final String message) {
435  super(message);
436  }
437 
438  L01Exception(final String message, final Throwable cause) {
439  super(message, cause);
440  }
441  }
442 
443 }
void run(DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback)
static int execute(ProcessBuilder processBuilder)
Definition: ExecUtil.java:172
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: Thu Sep 29 2022
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.