diff --git a/Core/src/org/sleuthkit/autopsy/actions/ExitAction.java b/Core/src/org/sleuthkit/autopsy/actions/ExitAction.java index a8d0979a97..7240afca92 100755 --- a/Core/src/org/sleuthkit/autopsy/actions/ExitAction.java +++ b/Core/src/org/sleuthkit/autopsy/actions/ExitAction.java @@ -18,17 +18,23 @@ */ package org.sleuthkit.autopsy.actions; +import java.awt.Cursor; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.util.concurrent.ExecutionException; import java.util.logging.Level; +import javax.swing.SwingWorker; import org.openide.LifecycleManager; import org.openide.awt.ActionID; import org.openide.awt.ActionReference; import org.openide.awt.ActionRegistration; import org.openide.util.NbBundle; +import org.openide.windows.WindowManager; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.CaseActionException; +import org.sleuthkit.autopsy.casemodule.StartupWindowProvider; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; /** * The action associated with the Case/Exit menu item. It closes the current @@ -39,23 +45,40 @@ import org.sleuthkit.autopsy.coreutils.Logger; @ActionID(id = "org.sleuthkit.autopsy.casemodule.ExitAction", category = "Case") final public class ExitAction implements ActionListener { + private static final Logger logger = Logger.getLogger(ExitAction.class.getName()); + @NbBundle.Messages({ "ExitAction.confirmationDialog.title=Ingest is Running", - "ExitAction.confirmationDialog.message=Ingest is running, are you sure you want to exit?" - + "ExitAction.confirmationDialog.message=Ingest is running, are you sure you want to exit?", + "# {0} - exception message", "ExitAction.messageBox.caseCloseExceptionMessage=Error closing case: {0}" }) @Override public void actionPerformed(ActionEvent e) { if (IngestRunningCheck.checkAndConfirmProceed(Bundle.ExitAction_confirmationDialog_title(), Bundle.ExitAction_confirmationDialog_message())) { - new Thread(() -> { - try { + WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + new SwingWorker() { + + @Override + protected Void doInBackground() throws Exception { Case.closeCurrentCase(); - } catch (CaseActionException ex) { - Logger.getLogger(ExitAction.class.getName()).log(Level.SEVERE, "Error closing the current case on exit", ex); //NON-NLS - } finally { - LifecycleManager.getDefault().exit(); + return null; } - }).start(); + + @Override + protected void done() { + try { + get(); + } catch (InterruptedException ex) { + logger.log(Level.SEVERE, "Unexpected interrupt closing the current case", ex); + } catch (ExecutionException ex) { + logger.log(Level.SEVERE, "Error closing the current case", ex); + MessageNotifyUtil.Message.error(Bundle.ExitAction_messageBox_caseCloseExceptionMessage(ex.getMessage())); + } finally { + WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + LifecycleManager.getDefault().exit(); + } + } + }.execute(); } } } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java index 5ad9a606a6..05668a5087 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageTask.java @@ -27,7 +27,7 @@ import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.imagewriter.ImageWriterService; -import org.sleuthkit.autopsy.ingest.IngestManager; +import org.sleuthkit.autopsy.imagewriter.ImageWriterSettings; import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.Image; import org.sleuthkit.datamodel.SleuthkitJNI; @@ -43,7 +43,7 @@ class AddImageTask implements Runnable { private final String deviceId; private final String imagePath; private final String timeZone; - private final String imageWriterPath; + private final ImageWriterSettings imageWriterSettings; private final boolean ignoreFatOrphanFiles; private final DataSourceProcessorProgressMonitor progressMonitor; private final DataSourceProcessorCallback callback; @@ -83,13 +83,13 @@ class AddImageTask implements Runnable { * processing. * @param callback Callback to call when processing is done. */ - AddImageTask(String deviceId, String imagePath, String timeZone, boolean ignoreFatOrphanFiles, String imageWriterPath, + AddImageTask(String deviceId, String imagePath, String timeZone, boolean ignoreFatOrphanFiles, ImageWriterSettings imageWriterSettings, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) { this.deviceId = deviceId; this.imagePath = imagePath; this.timeZone = timeZone; this.ignoreFatOrphanFiles = ignoreFatOrphanFiles; - this.imageWriterPath = imageWriterPath; + this.imageWriterSettings = imageWriterSettings; this.callback = callback; this.progressMonitor = progressMonitor; tskAddImageProcessLock = new Object(); @@ -103,12 +103,17 @@ class AddImageTask implements Runnable { progressMonitor.setIndeterminate(true); progressMonitor.setProgress(0); Case currentCase = Case.getCurrentCase(); + String imageWriterPath = ""; + if(imageWriterSettings != null){ + imageWriterPath = imageWriterSettings.getPath(); + } List errorMessages = new ArrayList<>(); List newDataSources = new ArrayList<>(); try { currentCase.getSleuthkitCase().acquireExclusiveLock(); synchronized (tskAddImageProcessLock) { - tskAddImageProcess = currentCase.getSleuthkitCase().makeAddImageProcess(timeZone, true, ignoreFatOrphanFiles, imageWriterPath); + tskAddImageProcess = currentCase.getSleuthkitCase().makeAddImageProcess(timeZone, true, + ignoreFatOrphanFiles, imageWriterPath); } Thread progressUpdateThread = new Thread(new ProgressUpdater(progressMonitor, tskAddImageProcess)); progressUpdateThread.start(); @@ -208,8 +213,8 @@ class AddImageTask implements Runnable { if (!verificationError.isEmpty()) { errorMessages.add(verificationError); } - if(! imageWriterPath.isEmpty()){ - ImageWriterService.createImageWriter(imageId); + if(imageWriterSettings != null){ + ImageWriterService.createImageWriter(imageId, imageWriterSettings); } newDataSources.add(newImage); } else { diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties index f22ada5664..7390868798 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties @@ -241,3 +241,4 @@ CasePropertiesPanel.lbDbType.text=Case Type: CasePropertiesPanel.examinerLabel.text=Examiner: CasePropertiesPanel.caseNumberLabel.text=Case Number: CasePropertiesPanel.deleteCaseButton.text=Delete Case +LocalDiskPanel.changeDatabasePathCheckbox.text=Change image path in the case to the VHD upon completion diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java b/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java index 5d976c0baa..36abbd307a 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/ImageDSProcessor.java @@ -185,7 +185,7 @@ public class ImageDSProcessor implements DataSourceProcessor, AutoIngestDataSour * @param callback Callback to call when processing is done. */ public void run(String deviceId, String imagePath, String timeZone, boolean ignoreFatOrphanFiles, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) { - addImageTask = new AddImageTask(deviceId, imagePath, timeZone, ignoreFatOrphanFiles, "", progressMonitor, callback); + addImageTask = new AddImageTask(deviceId, imagePath, timeZone, ignoreFatOrphanFiles, null, progressMonitor, callback); new Thread(addImageTask).start(); } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskDSProcessor.java b/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskDSProcessor.java index c09a89e489..35944d9d73 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskDSProcessor.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskDSProcessor.java @@ -30,6 +30,7 @@ import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor; import org.sleuthkit.autopsy.coreutils.DriveUtils; +import org.sleuthkit.autopsy.imagewriter.ImageWriterSettings; import org.sleuthkit.autopsy.framework.AutoIngestDataSourceProcessor; /** @@ -55,6 +56,7 @@ public class LocalDiskDSProcessor implements DataSourceProcessor, AutoIngestData private String drivePath; private String timeZone; private String imageWriterPath = ""; + private ImageWriterSettings imageWriterSettings = null; private boolean ignoreFatOrphanFiles; private boolean setDataSourceOptionsCalled; @@ -139,10 +141,10 @@ public class LocalDiskDSProcessor implements DataSourceProcessor, AutoIngestData timeZone = configPanel.getTimeZone(); ignoreFatOrphanFiles = configPanel.getNoFatOrphans(); if (configPanel.getImageWriterEnabled()) { - imageWriterPath = configPanel.getImageWriterPath(); + imageWriterSettings = configPanel.getImageWriterSettings(); } } - addDiskTask = new AddImageTask(deviceId, drivePath, timeZone, ignoreFatOrphanFiles, imageWriterPath, progressMonitor, callback); + addDiskTask = new AddImageTask(deviceId, drivePath, timeZone, ignoreFatOrphanFiles, imageWriterSettings, progressMonitor, callback); new Thread(addDiskTask).start(); } @@ -168,7 +170,7 @@ public class LocalDiskDSProcessor implements DataSourceProcessor, AutoIngestData * @param callback Callback to call when processing is done. */ public void run(String deviceId, String drivePath, String timeZone, boolean ignoreFatOrphanFiles, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) { - addDiskTask = new AddImageTask(deviceId, drivePath, timeZone, ignoreFatOrphanFiles, imageWriterPath, progressMonitor, callback); + addDiskTask = new AddImageTask(deviceId, drivePath, timeZone, ignoreFatOrphanFiles, imageWriterSettings, progressMonitor, callback); new Thread(addDiskTask).start(); } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.form b/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.form index a51dc82ef8..3683577766 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.form +++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.form @@ -45,14 +45,18 @@ - - - - - - - + + + + + + + + + + + @@ -87,11 +91,13 @@ + + - + @@ -247,5 +253,12 @@ + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.java index 899030b4ba..8e6da54b7b 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/LocalDiskPanel.java @@ -40,6 +40,7 @@ import org.sleuthkit.autopsy.coreutils.LocalDisk; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.coreutils.PlatformUtil; +import org.sleuthkit.autopsy.imagewriter.ImageWriterSettings; /** * ImageTypePanel for adding a local disk or partition such as PhysicalDrive0 or @@ -114,6 +115,7 @@ final class LocalDiskPanel extends JPanel { imageWriterErrorLabel.setText(""); pathTextField.setEnabled(copyImageCheckbox.isSelected()); browseButton.setEnabled(copyImageCheckbox.isSelected()); + changeDatabasePathCheckbox.setEnabled(copyImageCheckbox.isSelected()); } /** @@ -138,6 +140,7 @@ final class LocalDiskPanel extends JPanel { browseButton = new javax.swing.JButton(); jLabel1 = new javax.swing.JLabel(); imageWriterErrorLabel = new javax.swing.JLabel(); + changeDatabasePathCheckbox = new javax.swing.JCheckBox(); setMinimumSize(new java.awt.Dimension(0, 420)); setPreferredSize(new java.awt.Dimension(485, 410)); @@ -193,6 +196,8 @@ final class LocalDiskPanel extends JPanel { imageWriterErrorLabel.setForeground(new java.awt.Color(255, 0, 0)); org.openide.awt.Mnemonics.setLocalizedText(imageWriterErrorLabel, org.openide.util.NbBundle.getMessage(LocalDiskPanel.class, "LocalDiskPanel.imageWriterErrorLabel.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(changeDatabasePathCheckbox, org.openide.util.NbBundle.getMessage(LocalDiskPanel.class, "LocalDiskPanel.changeDatabasePathCheckbox.text")); // NOI18N + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( @@ -216,13 +221,16 @@ final class LocalDiskPanel extends JPanel { .addGroup(layout.createSequentialGroup() .addGap(21, 21, 21) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(imageWriterErrorLabel) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jLabel1) - .addGroup(layout.createSequentialGroup() - .addComponent(pathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 342, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(browseButton, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)))))))) + .addGroup(layout.createSequentialGroup() + .addComponent(pathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 342, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(browseButton, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(imageWriterErrorLabel) + .addComponent(jLabel1) + .addComponent(changeDatabasePathCheckbox)) + .addGap(0, 0, Short.MAX_VALUE))))))) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); layout.setVerticalGroup( @@ -247,17 +255,20 @@ final class LocalDiskPanel extends JPanel { .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) .addComponent(browseButton) .addComponent(pathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(changeDatabasePathCheckbox) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jLabel1) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(imageWriterErrorLabel) - .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addContainerGap(66, Short.MAX_VALUE)) ); }// //GEN-END:initComponents private void copyImageCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_copyImageCheckboxActionPerformed pathTextField.setEnabled(copyImageCheckbox.isSelected()); browseButton.setEnabled(copyImageCheckbox.isSelected()); + changeDatabasePathCheckbox.setEnabled(copyImageCheckbox.isSelected()); fireUpdateEvent(); }//GEN-LAST:event_copyImageCheckboxActionPerformed @@ -283,6 +294,7 @@ final class LocalDiskPanel extends JPanel { // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton browseButton; + private javax.swing.JCheckBox changeDatabasePathCheckbox; private javax.swing.JCheckBox copyImageCheckbox; private javax.swing.JLabel descLabel; private javax.swing.JLabel diskLabel; @@ -397,8 +409,8 @@ final class LocalDiskPanel extends JPanel { return copyImageCheckbox.isSelected(); } - String getImageWriterPath() { - return pathTextField.getText(); + ImageWriterSettings getImageWriterSettings() { + return new ImageWriterSettings(pathTextField.getText(), changeDatabasePathCheckbox.isSelected()); } /** diff --git a/Core/src/org/sleuthkit/autopsy/core/Installer.java b/Core/src/org/sleuthkit/autopsy/core/Installer.java index 187dab5920..748870d783 100644 --- a/Core/src/org/sleuthkit/autopsy/core/Installer.java +++ b/Core/src/org/sleuthkit/autopsy/core/Installer.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2014 Basis Technology Corp. + * Copyright 2011-2017 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -18,16 +18,24 @@ */ package org.sleuthkit.autopsy.core; +import java.awt.Cursor; import java.io.File; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.FutureTask; import java.util.logging.Handler; import java.util.logging.Level; import javafx.application.Platform; import javafx.embed.swing.JFXPanel; +import javax.swing.SwingWorker; +import org.openide.LifecycleManager; import org.openide.modules.ModuleInstall; import org.openide.util.NbBundle; import org.openide.windows.WindowManager; +import org.sleuthkit.autopsy.actions.IngestRunningCheck; +import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.coreutils.PlatformUtil; @@ -38,6 +46,8 @@ import org.sleuthkit.autopsy.coreutils.PlatformUtil; */ public class Installer extends ModuleInstall { + private static final long serialVersionUID = 1L; + private final List packageInstallers; private static final Logger logger = Logger.getLogger(Installer.class.getName()); private static volatile boolean javaFxInit = false; @@ -142,7 +152,9 @@ public class Installer extends ModuleInstall { logger.log(Level.SEVERE, "Error loading VHDI library, ", e); //NON-NLS } - /* PostgreSQL */ + /* + * PostgreSQL + */ try { System.loadLibrary("msvcr120"); //NON-NLS logger.log(Level.INFO, "MSVCR 120 library loaded"); //NON-NLS @@ -177,7 +189,7 @@ public class Installer extends ModuleInstall { } catch (UnsatisfiedLinkError e) { logger.log(Level.SEVERE, "Error loading libintl-8 library, ", e); //NON-NLS } - + try { System.loadLibrary("libpq"); //NON-NLS logger.log(Level.INFO, "LIBPQ library loaded"); //NON-NLS @@ -190,11 +202,11 @@ public class Installer extends ModuleInstall { public Installer() { logger.log(Level.INFO, "core installer created"); //NON-NLS javaFxInit = false; - + // Prevent the Autopsy UI from shrinking on high DPI displays System.setProperty("sun.java2d.dpiaware", "false"); System.setProperty("prism.allowhidpi", "false"); - + packageInstallers = new ArrayList<>(); packageInstallers.add(org.sleuthkit.autopsy.coreutils.Installer.getDefault()); packageInstallers.add(org.sleuthkit.autopsy.corecomponents.Installer.getDefault()); @@ -217,7 +229,7 @@ public class Installer extends ModuleInstall { System.setProperty("javafx.macosx.embedded", "true"); try { // Creating a JFXPanel initializes JavaFX - new JFXPanel(); + JFXPanel panel = new JFXPanel(); Platform.setImplicitExit(false); javaFxInit = true; } catch (UnsatisfiedLinkError | NoClassDefFoundError | Exception e) { @@ -267,7 +279,7 @@ public class Installer extends ModuleInstall { logger.log(Level.INFO, "{0} validate()", mi.getClass().getName()); //NON-NLS try { mi.validate(); - } catch (Exception e) { + } catch (IllegalStateException e) { logger.log(Level.WARNING, "", e); } } @@ -289,6 +301,40 @@ public class Installer extends ModuleInstall { } } + @NbBundle.Messages({ + "Installer.closing.confirmationDialog.title=Ingest is Running", + "Installer.closing.confirmationDialog.message=Ingest is running, are you sure you want to exit?", + "# {0} - exception message", "Installer.closing.messageBox.caseCloseExceptionMessage=Error closing case: {0}" + }) + @Override + public boolean closing() { + if (IngestRunningCheck.checkAndConfirmProceed(Bundle.Installer_closing_confirmationDialog_title(), Bundle.Installer_closing_confirmationDialog_message())) { + WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + FutureTask future = new FutureTask<>(new Callable() { + @Override + public Void call() throws Exception { + Case.closeCurrentCase(); + return null; + } + }); + Thread thread = new Thread(future); + thread.start(); + try { + future.get(); + } catch (InterruptedException ex) { + logger.log(Level.SEVERE, "Unexpected interrupt closing the current case", ex); + } catch (ExecutionException ex) { + logger.log(Level.SEVERE, "Error closing the current case", ex); + MessageNotifyUtil.Message.error(Bundle.Installer_closing_messageBox_caseCloseExceptionMessage(ex.getMessage())); + } finally { + WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + } + return true; + } else { + return false; + } + } + @Override public void close() { super.close(); diff --git a/Core/src/org/sleuthkit/autopsy/imagewriter/ImageWriter.java b/Core/src/org/sleuthkit/autopsy/imagewriter/ImageWriter.java index 55bfa23326..084c716d5a 100644 --- a/Core/src/org/sleuthkit/autopsy/imagewriter/ImageWriter.java +++ b/Core/src/org/sleuthkit/autopsy/imagewriter/ImageWriter.java @@ -21,6 +21,7 @@ package org.sleuthkit.autopsy.imagewriter; import com.google.common.util.concurrent.ThreadFactoryBuilder; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; +import java.util.concurrent.Callable; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.ScheduledFuture; @@ -33,6 +34,7 @@ import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.core.RuntimeProperties; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.Image; +import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.ingest.events.DataSourceAnalysisCompletedEvent; import org.sleuthkit.datamodel.SleuthkitJNI; @@ -50,9 +52,10 @@ class ImageWriter implements PropertyChangeListener{ private final Logger logger = Logger.getLogger(ImageWriter.class.getName()); private final Long dataSourceId; + private final ImageWriterSettings settings; private Long imageHandle = null; - private Future finishTask = null; + private Future finishTask = null; private ProgressHandle progressHandle = null; private ScheduledFuture progressUpdateTask = null; private boolean isCancelled = false; @@ -62,15 +65,27 @@ class ImageWriter implements PropertyChangeListener{ private ScheduledThreadPoolExecutor periodicTasksExecutor = null; private final boolean doUI; + private SleuthkitCase caseDb = null; /** * Create the Image Writer object. * After creation, startListeners() should be called. * @param dataSourceId */ - ImageWriter(Long dataSourceId){ - this.dataSourceId = dataSourceId; - doUI = RuntimeProperties.runningWithGUI(); + ImageWriter(Long dataSourceId, ImageWriterSettings settings){ + this.dataSourceId = dataSourceId; + this.settings = settings; + doUI = RuntimeProperties.runningWithGUI(); + + // We save the reference to the sleuthkit case here in case getCurrentCase() is set to + // null before Image Writer finishes. The user can still elect to wait for image writer + // (in ImageWriterService.closeCaseResources) even though the case is closing. + try{ + caseDb = Case.getCurrentCase().getSleuthkitCase(); + } catch (IllegalStateException ex){ + logger.log(Level.SEVERE, "Unable to load case. Image writer will be cancelled."); + this.isCancelled = true; + } } /** @@ -160,11 +175,23 @@ class ImageWriter implements PropertyChangeListener{ // The added complexity here with the Future is because we absolutely need to make sure // the call to finishImageWriter returns before allowing the TSK data structures to be freed // during case close. - finishTask = Executors.newSingleThreadExecutor().submit(() -> { - try{ - SleuthkitJNI.finishImageWriter(imageHandle); - } catch (TskCoreException ex){ - logger.log(Level.SEVERE, "Error finishing VHD image", ex); //NON-NLS + finishTask = Executors.newSingleThreadExecutor().submit(new Callable(){ + @Override + public Integer call() throws TskCoreException{ + try{ + int result = SleuthkitJNI.finishImageWriter(imageHandle); + + // We've decided to always update the path to the VHD, even if it wasn't finished. + // This supports the case where an analyst has partially ingested a device + // but has to stop before completion. They will at least have part of the image. + if(settings.getUpdateDatabasePath()){ + caseDb.updateImagePath(settings.getPath(), dataSourceId); + } + return result; + } catch (TskCoreException ex){ + logger.log(Level.SEVERE, "Error finishing VHD image", ex); //NON-NLS + return -1; + } } }); @@ -173,9 +200,10 @@ class ImageWriter implements PropertyChangeListener{ } // Wait for finishImageWriter to complete + int result = 0; try{ // The call to get() can happen multiple times if the user closes the case, which is ok - finishTask.get(); + result = finishTask.get(); } catch (InterruptedException | ExecutionException ex){ logger.log(Level.SEVERE, "Error finishing VHD image", ex); //NON-NLS } @@ -189,7 +217,11 @@ class ImageWriter implements PropertyChangeListener{ } } - logger.log(Level.INFO, String.format("Finished writing VHD image for %s", dataSourceName)); //NON-NLS + if(result == 0){ + logger.log(Level.INFO, String.format("Successfully finished writing VHD image for %s", dataSourceName)); //NON-NLS + } else { + logger.log(Level.INFO, String.format("Finished VHD image for %s with errors", dataSourceName)); //NON-NLS + } } /** diff --git a/Core/src/org/sleuthkit/autopsy/imagewriter/ImageWriterService.java b/Core/src/org/sleuthkit/autopsy/imagewriter/ImageWriterService.java index 8f3791d53c..594532cbc6 100644 --- a/Core/src/org/sleuthkit/autopsy/imagewriter/ImageWriterService.java +++ b/Core/src/org/sleuthkit/autopsy/imagewriter/ImageWriterService.java @@ -18,14 +18,15 @@ */ package org.sleuthkit.autopsy.imagewriter; -import java.util.HashSet; -import java.util.Set; +import java.util.ArrayList; +import java.util.List; import org.openide.DialogDescriptor; import org.openide.DialogDisplayer; import org.openide.NotifyDescriptor; import org.openide.util.NbBundle; import org.openide.util.lookup.ServiceProvider; import org.openide.util.lookup.ServiceProviders; +import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.framework.AutopsyService; @ServiceProviders(value = {@ServiceProvider(service = AutopsyService.class)}) @@ -39,20 +40,20 @@ import org.sleuthkit.autopsy.framework.AutopsyService; public class ImageWriterService implements AutopsyService { - private static final Set imageWriters = new HashSet<>(); // Contains all Image Writer objects + private static final List imageWriters = new ArrayList<>(); // Contains all Image Writer objects private static final Object imageWritersLock = new Object(); // Get this lock before accessing currentImageWriters /** * Create an image writer object for the given data source ID. * @param imageId ID for the image */ - public static void createImageWriter(Long imageId){ + public static void createImageWriter(Long imageId, ImageWriterSettings settings){ // ImageWriter objects are created during the addImageTask. They can not arrive while // we're closing case resources so we don't need to worry about one showing up while // doing our close/cleanup. synchronized(imageWritersLock){ - ImageWriter writer = new ImageWriter(imageId); + ImageWriter writer = new ImageWriter(imageId, settings); writer.subscribeToEvents(); imageWriters.add(writer); } diff --git a/Core/src/org/sleuthkit/autopsy/imagewriter/ImageWriterSettings.java b/Core/src/org/sleuthkit/autopsy/imagewriter/ImageWriterSettings.java new file mode 100644 index 0000000000..a8d653d853 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/imagewriter/ImageWriterSettings.java @@ -0,0 +1,41 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2011-2016 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.imagewriter; + +/** + * Helper class to hold the image writer settings from the local disk panel + */ +public class ImageWriterSettings { + private final String path; + private final boolean updateDatabasePath; + + public ImageWriterSettings(String path, boolean updateDatabasePath){ + this.path = path; + this.updateDatabasePath = updateDatabasePath; + } + + public String getPath(){ + return path; + } + + public boolean getUpdateDatabasePath(){ + return updateDatabasePath; + } +} + diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestJobSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestJobSettingsPanel.java index 8b1c81a19a..ac045ea63b 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestJobSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestJobSettingsPanel.java @@ -74,6 +74,7 @@ public final class IngestJobSettingsPanel extends javax.swing.JPanel { /** * Construct a panel to allow a user to make ingest job settings. + * This constructor assumes there is no ingest history. * * @param settings The initial settings for the ingest job. */ @@ -88,12 +89,13 @@ public final class IngestJobSettingsPanel extends javax.swing.JPanel { } /** - * Construct a panel to allow a user to make ingest job settings. + * Construct a panel to allow a user to make ingest job settings. + * This constructor enables tracking of ingest job history. * * @param settings The initial settings for the ingest job. * @param dataSources The data sources ingest is being run on. */ - IngestJobSettingsPanel(IngestJobSettings settings, List dataSources) { + public IngestJobSettingsPanel(IngestJobSettings settings, List dataSources) { this.settings = settings; this.dataSources.addAll(dataSources); try { diff --git a/Core/src/org/sleuthkit/autopsy/ingest/runIngestModuleWizard/IngestModulesConfigWizardPanel.java b/Core/src/org/sleuthkit/autopsy/ingest/runIngestModuleWizard/IngestModulesConfigWizardPanel.java index 7f77ce2b40..e7ac23d7ab 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/runIngestModuleWizard/IngestModulesConfigWizardPanel.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/runIngestModuleWizard/IngestModulesConfigWizardPanel.java @@ -19,12 +19,14 @@ package org.sleuthkit.autopsy.ingest.runIngestModuleWizard; import java.awt.Component; +import java.util.List; import javax.swing.event.ChangeListener; import org.openide.WizardDescriptor; import org.openide.util.HelpCtx; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.ingest.IngestJobSettings; import org.sleuthkit.autopsy.ingest.IngestJobSettingsPanel; +import org.sleuthkit.datamodel.Content; /** * A wizard panel for configuring an ingest job. @@ -34,16 +36,17 @@ class IngestModulesConfigWizardPanel extends ShortcutWizardDescriptorPanel { private final String executionContext; private final IngestJobSettings.IngestType ingestType; private IngestJobSettingsPanel ingestJobSettingsPanel; - + private final List dataSources; /** * Constructs a wizard panel for configuring an ingest job. * * @param executionContest The execution context for the wizard. * @param ingestType The ingest type. */ - IngestModulesConfigWizardPanel(String executionContest, IngestJobSettings.IngestType ingestType) { + IngestModulesConfigWizardPanel(String executionContest, IngestJobSettings.IngestType ingestType, List dataSources) { this.executionContext = executionContest; this.ingestType = ingestType; + this.dataSources = dataSources; } /** @@ -64,7 +67,7 @@ class IngestModulesConfigWizardPanel extends ShortcutWizardDescriptorPanel { * Creating an ingest job settings object is expensive, so it is * deferred until this panel is actually used in the wizard. */ - ingestJobSettingsPanel = new IngestJobSettingsPanel(new IngestJobSettings(executionContext, ingestType)); + ingestJobSettingsPanel = new IngestJobSettingsPanel(new IngestJobSettings(executionContext, ingestType), dataSources); } ingestJobSettingsPanel.setName(Bundle.IngestModulesConfigWizardPanel_name_text()); return ingestJobSettingsPanel; diff --git a/Core/src/org/sleuthkit/autopsy/ingest/runIngestModuleWizard/RunIngestModulesAction.java b/Core/src/org/sleuthkit/autopsy/ingest/runIngestModuleWizard/RunIngestModulesAction.java index 01ab11e7d6..7a1e6fa4db 100755 --- a/Core/src/org/sleuthkit/autopsy/ingest/runIngestModuleWizard/RunIngestModulesAction.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/runIngestModuleWizard/RunIngestModulesAction.java @@ -91,7 +91,7 @@ public final class RunIngestModulesAction extends CallableSystemAction { * WizardDescriptor.Panel.getComponent().getName(). */ WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); - RunIngestModulesWizardIterator wizard = new RunIngestModulesWizardIterator(EXECUTION_CONTEXT, this.ingestType); + RunIngestModulesWizardIterator wizard = new RunIngestModulesWizardIterator(EXECUTION_CONTEXT, this.ingestType, this.dataSources); WizardDescriptor wiz = new WizardDescriptor(wizard); wiz.setTitleFormat(new MessageFormat("{0}")); wiz.setTitle(Bundle.RunIngestModulesAction_name()); diff --git a/Core/src/org/sleuthkit/autopsy/ingest/runIngestModuleWizard/RunIngestModulesWizardIterator.java b/Core/src/org/sleuthkit/autopsy/ingest/runIngestModuleWizard/RunIngestModulesWizardIterator.java index 8fb0b9ba4a..add27f8146 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/runIngestModuleWizard/RunIngestModulesWizardIterator.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/runIngestModuleWizard/RunIngestModulesWizardIterator.java @@ -27,6 +27,7 @@ import javax.swing.event.ChangeListener; import org.openide.WizardDescriptor; import org.sleuthkit.autopsy.ingest.IngestJobSettings; import org.sleuthkit.autopsy.ingest.IngestProfiles; +import org.sleuthkit.datamodel.Content; /** * A wizard that allows a user to configure an ingest job. @@ -45,7 +46,7 @@ final class RunIngestModulesWizardIterator implements WizardDescriptor.Iterator< * settings can differ by execution context. * @param ingestType The type of ingest to be configured. */ - RunIngestModulesWizardIterator(String executionContext, IngestJobSettings.IngestType ingestType) { + RunIngestModulesWizardIterator(String executionContext, IngestJobSettings.IngestType ingestType, List dataSources) { this.ingestType = ingestType; panels = new ArrayList<>(); List profiles = IngestProfiles.getIngestProfiles(); @@ -53,7 +54,7 @@ final class RunIngestModulesWizardIterator implements WizardDescriptor.Iterator< panels.add(new IngestProfileSelectionWizardPanel(executionContext, PROP_LASTPROFILE_NAME)); } - panels.add(new IngestModulesConfigWizardPanel(executionContext, this.ingestType)); + panels.add(new IngestModulesConfigWizardPanel(executionContext, this.ingestType, dataSources)); String[] steps = new String[panels.size()]; for (int i = 0; i < panels.size(); i++) { Component c = panels.get(i).getComponent(); diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSet.java b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSet.java index 6fb44839b5..43bb5a4a79 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSet.java +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/FilesSet.java @@ -763,7 +763,7 @@ public final class FilesSet implements Serializable { * matched. */ ExtensionCondition(Pattern extension) { - super(extension.pattern(), false); + super(extension); } @Override diff --git a/docs/doxygen-user/data_sources.dox b/docs/doxygen-user/data_sources.dox index 753c95bcbe..2f0321cfaf 100755 --- a/docs/doxygen-user/data_sources.dox +++ b/docs/doxygen-user/data_sources.dox @@ -21,23 +21,25 @@ The data source must remain accessible for the duration of the analysis because Regardless of the type of data source, there are some common steps in the process: -1) You will be prompted to specify the data source to add (details are provided below) +1) You will select the type of data source. \image html select-data-source-type.PNG +2) You will be prompted to specify the data source to add. This screen varies based on the data source type. Details on adding each type of data source are provided below. + NOTE: If you are adding a data source to a multi-user case, ensure that all Autopsy clients will have access to the data source at the same path. We recommend using UNC paths to ensure this consistent mapping. -2) Autopsy will perform a basic examination of the data source and populate an embedded database with an entry for each file in the data source. No content is analyzed in the process, only the files are enumerated. +3) Autopsy will perform a basic examination of the data source and populate an embedded database with an entry for each file in the data source. No content is analyzed in the process, only the files are enumerated. -3) While it is examining the data source, you will be prompted with a list of ingest modules to enable. +4) While it is examining the data source, you will be prompted with a list of ingest modules to enable. If one or more ingest profiles have been saved, there will be a screen before this asking whether to use one of the saved profiles or do a custom setup. See \ref ingest_page for more information on setting up ingest profiles. \image html select-ingest-modules.PNG -4) After you configure the ingest modules, you may need to wait for Autopsy to finish its basic examination of the data source. +5) After you configure the ingest modules, you may need to wait for Autopsy to finish its basic examination of the data source. \image html data-source-progress-bar.PNG -5) After the ingest modules have been configured and the basic examination of the data source is complete, the ingest modules will begin to analyze the file contents. +6) After the ingest modules have been configured and the basic examination of the data source is complete, the ingest modules will begin to analyze the file contents. You cannot remove a data source from a case. @@ -52,24 +54,29 @@ Autopsy supports disk images in the following formats: To add a disk image: --# Choose "Disk Image or VM File" from the pull down. +-# Choose "Disk Image or VM File" from the data source types. -# Browse to the first file in the disk image. You need to specify only the first file and Autopsy will find the rest. -# Choose the timezone that the disk image came from. This is most important for when adding FAT file systems because it does not store timezone information and Autopsy will not know how to normalize to UTC. -# Choose to perform orphan file finding on FAT file systems. This can be a time intensive process because it will require that Autopsy look at each sector in the device. -\section ds_local Adding a Local Drive +\section ds_local Adding a Local Disk -Autopsy can analyze a local drive without needing to first make an image copy of it. This is most useful when analyzing a USB-attached device through a write blocker. +Autopsy can analyze a local disk without needing to first make an image copy of it. This is most useful when analyzing a USB-attached device through a write blocker. -Note that if you are analyzing a local drive that is being updated, then Autopsy will not see files that are added after you add it as a data source. +Note that if you are analyzing a local disk that is being updated, then Autopsy will not see files that are added after you add it as a data source. You will need to be running Autopsy as an Administrator to view all devices. +There is an option to make a copy of the local disk as a VHD during analysis. This VHD can be loaded in Windows or analyzed through Autopsy. There is an additional option to update the image path in the case database to this newly created file. Enabling this option will allow you to browse the case data normally even after the local disk is removed. Note that at least one ingest module must successfully run in order to generate the complete image copy. + +\image html local-disk-data-source.PNG + To add a local drive: --# Choose "Local Drive" from the pull down. +-# Choose "Local Disk" from the data source types. -# Choose the device from the pull down list. -# Choose to perform orphan file finding. See comment in \ref ds_img about this setting. +-# Choose whether to create a VHD copy of the local disk and whether to update the image path. \section ds_log Adding a Logical File @@ -84,7 +91,7 @@ Some things to note when doing this: \image html change_logical_file_set_display_name.PNG To add logical files: --# Choose "Logical Files" from the pull down. +-# Choose "Logical Files" from the data source types. -# Press the "Add" button and navigate to a folder or file to add. Choosing a folder will cause all of its contents (including sub-folders) to be added. -# Continue to press "Add" until all files and folders have been selected. @@ -95,8 +102,8 @@ All of the files that you added in the panel will be grouped together into a sin \image html unallocated_space_options.PNG To add unallocated space image files: --# Choose "Unallocated Space Image File" from the pull down --# Browse to the file +-# Choose "Unallocated Space Image File" from the data source types. +-# Browse to the file. -# Choose whether to break the image up into chunks. Breaking the image up will give better performance since the chunks can be processed in parallel, but there is a chance that keywords or carved files that span chunk boundaries will be missed. */ \ No newline at end of file diff --git a/docs/doxygen-user/filetype.dox b/docs/doxygen-user/filetype.dox index 22d40add12..be69a0ed93 100644 --- a/docs/doxygen-user/filetype.dox +++ b/docs/doxygen-user/filetype.dox @@ -32,10 +32,12 @@ a data source. All user-defined and Tika rules are always applied. Seeing Results ------ -This module does not have obvious impacts in the user interface, though it is used by many other modules. +The results can be seen in the views area of the tree, under Views->File Types->By MIME Type. + +\image html mime-type-tree.PNG + +Note that only user-defined MIME types of the form (media type)/(media subtype) will be displayed in the tree. To see the file type of an individual file, view the "Results" tab in the lower right when you navigate to the file. You should see a page in there that mentions the file type. -The Views area of the tree does not take the results of this module into account. That part of the tree relies on extension. We will be updating it in the future to rely on extension when there is no output from this module for the file. - */ diff --git a/docs/doxygen-user/images/change_logical_file_set_display_name.PNG b/docs/doxygen-user/images/change_logical_file_set_display_name.PNG index ec73a232c6..6219181804 100755 Binary files a/docs/doxygen-user/images/change_logical_file_set_display_name.PNG and b/docs/doxygen-user/images/change_logical_file_set_display_name.PNG differ diff --git a/docs/doxygen-user/images/data-source-progress-bar.PNG b/docs/doxygen-user/images/data-source-progress-bar.PNG index d5a443d011..747031914e 100755 Binary files a/docs/doxygen-user/images/data-source-progress-bar.PNG and b/docs/doxygen-user/images/data-source-progress-bar.PNG differ diff --git a/docs/doxygen-user/images/filetype.PNG b/docs/doxygen-user/images/filetype.PNG index cd6d288391..142491862f 100755 Binary files a/docs/doxygen-user/images/filetype.PNG and b/docs/doxygen-user/images/filetype.PNG differ diff --git a/docs/doxygen-user/images/ingest-already-run.PNG b/docs/doxygen-user/images/ingest-already-run.PNG index e3243711fe..9e5ceb307b 100755 Binary files a/docs/doxygen-user/images/ingest-already-run.PNG and b/docs/doxygen-user/images/ingest-already-run.PNG differ diff --git a/docs/doxygen-user/images/ingest-file-filters.PNG b/docs/doxygen-user/images/ingest-file-filters.PNG new file mode 100644 index 0000000000..3bff2cb8a6 Binary files /dev/null and b/docs/doxygen-user/images/ingest-file-filters.PNG differ diff --git a/docs/doxygen-user/images/ingest-profile-create.PNG b/docs/doxygen-user/images/ingest-profile-create.PNG new file mode 100644 index 0000000000..d1139b55ef Binary files /dev/null and b/docs/doxygen-user/images/ingest-profile-create.PNG differ diff --git a/docs/doxygen-user/images/ingest-profiles.PNG b/docs/doxygen-user/images/ingest-profiles.PNG new file mode 100644 index 0000000000..7902140b9e Binary files /dev/null and b/docs/doxygen-user/images/ingest-profiles.PNG differ diff --git a/docs/doxygen-user/images/interesting_files_configuration.PNG b/docs/doxygen-user/images/interesting_files_configuration.PNG index d027d92454..0e1e39eada 100755 Binary files a/docs/doxygen-user/images/interesting_files_configuration.PNG and b/docs/doxygen-user/images/interesting_files_configuration.PNG differ diff --git a/docs/doxygen-user/images/interesting_files_ingest_settings.PNG b/docs/doxygen-user/images/interesting_files_ingest_settings.PNG index b4cda8c5a5..c5dc42e20e 100755 Binary files a/docs/doxygen-user/images/interesting_files_ingest_settings.PNG and b/docs/doxygen-user/images/interesting_files_ingest_settings.PNG differ diff --git a/docs/doxygen-user/images/keyword-search-configuration-dialog-general.PNG b/docs/doxygen-user/images/keyword-search-configuration-dialog-general.PNG index 86e392d2e3..360ec860b9 100755 Binary files a/docs/doxygen-user/images/keyword-search-configuration-dialog-general.PNG and b/docs/doxygen-user/images/keyword-search-configuration-dialog-general.PNG differ diff --git a/docs/doxygen-user/images/keyword-search-configuration-dialog-string-extraction.PNG b/docs/doxygen-user/images/keyword-search-configuration-dialog-string-extraction.PNG index cbe3bd976b..e5706a4df8 100755 Binary files a/docs/doxygen-user/images/keyword-search-configuration-dialog-string-extraction.PNG and b/docs/doxygen-user/images/keyword-search-configuration-dialog-string-extraction.PNG differ diff --git a/docs/doxygen-user/images/keyword-search-configuration-dialog.PNG b/docs/doxygen-user/images/keyword-search-configuration-dialog.PNG index 3923522990..b7c15ca36d 100755 Binary files a/docs/doxygen-user/images/keyword-search-configuration-dialog.PNG and b/docs/doxygen-user/images/keyword-search-configuration-dialog.PNG differ diff --git a/docs/doxygen-user/images/keyword-search-ingest-settings.PNG b/docs/doxygen-user/images/keyword-search-ingest-settings.PNG index a234b41dc8..b55eca62c5 100755 Binary files a/docs/doxygen-user/images/keyword-search-ingest-settings.PNG and b/docs/doxygen-user/images/keyword-search-ingest-settings.PNG differ diff --git a/docs/doxygen-user/images/local-disk-data-source.PNG b/docs/doxygen-user/images/local-disk-data-source.PNG new file mode 100644 index 0000000000..22fdc40ec5 Binary files /dev/null and b/docs/doxygen-user/images/local-disk-data-source.PNG differ diff --git a/docs/doxygen-user/images/mime-type-tree.PNG b/docs/doxygen-user/images/mime-type-tree.PNG new file mode 100644 index 0000000000..b7a5947acf Binary files /dev/null and b/docs/doxygen-user/images/mime-type-tree.PNG differ diff --git a/docs/doxygen-user/images/multiuser_settings.PNG b/docs/doxygen-user/images/multiuser_settings.PNG index cb6815c5de..0226c07662 100755 Binary files a/docs/doxygen-user/images/multiuser_settings.PNG and b/docs/doxygen-user/images/multiuser_settings.PNG differ diff --git a/docs/doxygen-user/images/previous-version-already-run.PNG b/docs/doxygen-user/images/previous-version-already-run.PNG index d2223795cd..3e685577d0 100755 Binary files a/docs/doxygen-user/images/previous-version-already-run.PNG and b/docs/doxygen-user/images/previous-version-already-run.PNG differ diff --git a/docs/doxygen-user/images/profile-data-source-panel.PNG b/docs/doxygen-user/images/profile-data-source-panel.PNG new file mode 100644 index 0000000000..e22a412d1d Binary files /dev/null and b/docs/doxygen-user/images/profile-data-source-panel.PNG differ diff --git a/docs/doxygen-user/images/proxySettings.PNG b/docs/doxygen-user/images/proxySettings.PNG index 4ef7fc3424..b405bb53b0 100755 Binary files a/docs/doxygen-user/images/proxySettings.PNG and b/docs/doxygen-user/images/proxySettings.PNG differ diff --git a/docs/doxygen-user/images/select-data-source-type.PNG b/docs/doxygen-user/images/select-data-source-type.PNG index 662b84d495..2205f07d7b 100755 Binary files a/docs/doxygen-user/images/select-data-source-type.PNG and b/docs/doxygen-user/images/select-data-source-type.PNG differ diff --git a/docs/doxygen-user/images/select-ingest-modules.PNG b/docs/doxygen-user/images/select-ingest-modules.PNG index b706bc9b1f..fe359cbc15 100755 Binary files a/docs/doxygen-user/images/select-ingest-modules.PNG and b/docs/doxygen-user/images/select-ingest-modules.PNG differ diff --git a/docs/doxygen-user/images/threadcount.PNG b/docs/doxygen-user/images/threadcount.PNG index a23977033f..14ab551813 100755 Binary files a/docs/doxygen-user/images/threadcount.PNG and b/docs/doxygen-user/images/threadcount.PNG differ diff --git a/docs/doxygen-user/images/unallocated_space_options.PNG b/docs/doxygen-user/images/unallocated_space_options.PNG index 29742955a4..2f85e41b3d 100644 Binary files a/docs/doxygen-user/images/unallocated_space_options.PNG and b/docs/doxygen-user/images/unallocated_space_options.PNG differ diff --git a/docs/doxygen-user/ingest.dox b/docs/doxygen-user/ingest.dox index 7ab8212f85..9b76fbabfc 100644 --- a/docs/doxygen-user/ingest.dox +++ b/docs/doxygen-user/ingest.dox @@ -29,16 +29,42 @@ Once ingest is started, you can review the currently running ingest tasks in the \section ingest_configure Configuring Ingest Modules -You will be presented with an interface to configure the ingest modules. From here, you can choose to enable or disable each module and some modules will have further configuration settings. +You will be presented with an interface to configure the ingest modules. From here, you can choose which type of files to analyze and enable or disable each module. Some modules will have further configuration settings. \image html select-ingest-modules.PNG +The selection box at the top controls which files the ingest modules will run on. The two built-in options are "All files, directories, and unallocated space" and "All Files and Directories." The \ref file_filters section describes how to create custom file filters. The chosen filter applies to all ingest modules. + There are two places to configure ingest modules. When you select the module name, you may have some "run time" options to configure in the panel to the right. These are generally settings that you may want to change from image to image. There may also be an "Advanced" button that is enabled in the lower corner. Pressing this button allows you to change global settings that are not specific to a single image. This advanced configuration panel can often be found in the "Tools", "Options" menu too. As an example, the hash lookup module will allow you to enable or disable hash databases in the "run time" options panel, but requires you to go to the "Advanced" dialog to add or remove hash databases from the Autopsy configuration. +\section file_filters Custom File Filters + +The file filters panel can be opened from the ingest module selection panel or through the Ingest tab on the main options panel. File filters allow ingest modules to be run on only a subset of the files. In the example below, a filter has been set up to only run on files with a "png" extension. + +\image html ingest-file-filters.PNG + +Each filter contains one or more rules for selecting files based on file name and/or path. All files will still be displayed in the tree view, but the ingest modules will only run on a subset. If we use the previous example and run the hash module, only files ending in .png will have their hash computed. + +\section ingest_profiles Using Ingest Profiles + +Ingest profiles allow you to quickly choose a defined set of ingest modules to run. This can be useful if you run different sets of ingest modules (or different configurations of those ingest modules) on different types of data. Ingest profiles can be configured through the Ingest tab on the options panel. + +\image html ingest-profiles.PNG + +Each profile can specify different per-run settings for each ingest module, and you can choose use either a predefined or custom file filter (see \ref file_filters). + +\image html ingest-profile-create.PNG + +If any custom profiles are present, there will be a new screen in the add data source wizard. + +\image html profile-data-source-panel.PNG + +If you choose custom settings it will bring up the normal ingest module selection panel. If you choose a user-defined profile the ingest module screen will be skipped entirely and the ingest modules from that profile will be run on the data source. The profile selection panel will also appear when running ingest by right-clicking on a data source from the tree. +

\section ingest_already_run Notification of Ingest Already Run If an ingest module has already been run for a particular data source, you will see a triangular yellow icon with an exclaimation point next to the module in the "Run Ingest Modules" dialog, as shown in the screenshot below. diff --git a/docs/doxygen-user/interesting.dox b/docs/doxygen-user/interesting.dox deleted file mode 100644 index 6db33ba4f6..0000000000 --- a/docs/doxygen-user/interesting.dox +++ /dev/null @@ -1,66 +0,0 @@ -/*! \page interesting_page Interesting Files Module -Overview -======== - -The Interesting Files module allows you to search for files or directories in a data source and generate alerts when they are found. You configure rules for the files that you want to find. - -You would use this to be notified when certain things are found. There are examples later in this file to generate alerts when VMWare images are found or when iPhone backup files are found. This module is useful for file types that will frequently have a consistent name and that may not be part of the stanadrd checklist that you look for (or if you simply want to automated your checklist). - - - -Rules -======= - -Add rules using Tools -> Options -> Interesting Files. - -All rules need to be part of a set. Sets need to have the following defined: - -- Set Name (required) -- Set Description (optional) - -Rules specify what to look for in a data source. Each rule specifies: -- Type: If the rule should be applied to only files, only directories, or both files and directories. -- Name Pattern: String to match the file name against. -- Name Pattern Type: Should the pattern be matched against the full file type or just the extension. -- Path Pattern: A substring of the parent path that must be matched. This allows you to restrict generic names to a specific structure (such as an application name). A substring match is performed. -- Rule Name: Additional details that are displayed in the UI when that rule is matched. Allows you to determine which rule in the set matched. - - -Example -======= - -VMWare --------- -This set of rules is to detect VMWare Player or vmdk files. This would help to make sure you look into the virtual machines for additional evidence. - -NOTE: This is not extensive and is simply a minimal example: - - -- Set Name: VMWare -- Rule 1: - - Type: Files - - Full Name: vmplayer.exe - - Name: Program EXE -- Rule 2: - - Type: Files - - Extension: vmdk - - Name: VMDK File - -iPhone Backups -------------- -This set of rules is to detect a folder for iPhone Backups. These are typically in a folder such as "%AppData%\Roaming\Apple Computer\MobileSync\Backup" on Windows. Here is a rule that you could use for that. - -- Set Name: iPhone Backups -- Rule 1: - - Type: Directory - - Name: Backup - - Path: Apple Computer/MobileSync - -Using the Module -====== - -When you enable the Interesting Files module, you can choose what rule sets to enable. To add rules, use the "Advanced" button from the ingest module panel. - -When files are found, they will be in the Interesting Files area of the tree. You shoudl see the set and rule names with the match. - -*/ diff --git a/docs/doxygen-user/interesting_files.dox b/docs/doxygen-user/interesting_files.dox index 5525845991..d7dc6bb14b 100755 --- a/docs/doxygen-user/interesting_files.dox +++ b/docs/doxygen-user/interesting_files.dox @@ -12,11 +12,13 @@ Configuration Add rules using "Tools", "Options", "Interesting Files". -All rules need to be part of a set. Sets need to have the following defined: +All rules need to be part of a set. Select "New set" on the left side panel to create a new set. Sets need to have the following defined: - Set Name (required) - Set Description (optional) +Sets can be renamed, edited, copied, and imported and exported from the left side panel. + Rules specify what to look for in a data source. Each rule specifies: - Type: If the rule should be applied to only files, only directories, or both files and directories. - Name Pattern: String to match the file name against. diff --git a/docs/doxygen-user/keyword_search.dox b/docs/doxygen-user/keyword_search.dox index 92c8913585..5a17c6b0a1 100644 --- a/docs/doxygen-user/keyword_search.dox +++ b/docs/doxygen-user/keyword_search.dox @@ -16,7 +16,7 @@ Once files are placed in the Solr index, they can be searched quickly for specif \section keyword_search_configuration_dialog Keyword Search Configuration Dialog -The keyword search configuration dialog has three tabs, each with it's own purpose: +The keyword search configuration dialog has three tabs, each with its own purpose: \li The Lists tab is used to add, remove, and modify keyword search lists. \li The String Extraction tab is used to enable language scripts and extraction type. \li The General tab is used to configure the ingest timings and display information. @@ -26,7 +26,7 @@ To create a list, select the 'New List' button and choose a name for the new Key Regular expressions are supported using Lucene Regex Syntax which is documented here: https://lucene.apache.org/core/6_4_0/core/org/apache/lucene/util/automaton/RegExp.html. .* is automatically added to the beginning and end of the regular expressions to ensure all matches are found. Additionally, the resulting hits are split on common token separator boundaries (e.g. space, newline, colon, exclamation point etc.) to reduce false positives and to make the resulting keyword hit more amenable to highlighting. If you would prefer not to split on these common boundary characters, you can put .* at the start and/or end of the regex. List Import and Export \n -Autopsy supports importing Encase tab-delimited lists as well as lists created previously with Autopsy. For Encase lists, folder structure and hierarchy is currently ignored. This will be fixed in a future version. There is currently no way to export lists for use with Encase. This will also be added in future releases. +Autopsy supports importing Encase tab-delimited lists as well as lists created previously with Autopsy. For Encase lists, folder structure and hierarchy is ignored. There is currently no way to export lists for use with Encase, but lists can be exported to share between Autopsy users. Lists tab \n \image html keyword-search-configuration-dialog.PNG diff --git a/docs/doxygen-user/performance.dox b/docs/doxygen-user/performance.dox index 7928cefd1c..6174e640e4 100644 --- a/docs/doxygen-user/performance.dox +++ b/docs/doxygen-user/performance.dox @@ -6,7 +6,7 @@ After installing Autopsy, there are several hardware-based things that we sugges - Run Autopsy from the Start Menu or desktop - When presented with the case creation splash screen, cancel/close the window - Select "Tools", "Options" - - On the "Autopsy" tab, there is a drop down for _Number of threads to use for file ingest_. We recommend you set this value 4. If you set this number too high, performance can degrade because the pipelines are fighting for the same physical resources. Individual testing should be done to find an optimal setting, but our testing reveals that for most systems and setups, after four threads, the machine is I/O bound anyway, and increasing this number beyond 4 may actually reduce performance. + - On the "Ingest" panel on the "Settings" tab, there is a drop down for _Number of threads to use for file ingest_. We recommend you set this value 4. If you set this number too high, performance can degrade because the pipelines are fighting for the same physical resources. Individual testing should be done to find an optimal setting, but our testing reveals that for most systems and setups, after four threads, the machine is I/O bound anyway, and increasing this number beyond 4 may actually reduce performance. - After each change, restart Autopsy to let this setting take effect.