Merge pull request #1468 from karlmortensen/hostname_not_ip

use hostname in UNC paths for photorec
This commit is contained in:
Richard Cordovano 2015-07-30 14:31:29 -04:00
commit 6a0a4fd4cb
9 changed files with 381 additions and 69 deletions

View File

@ -244,16 +244,16 @@ CollaborationMonitor.addingDataSourceStatus.msg={0} adding data source
CollaborationMonitor.analyzingDataSourceStatus.msg={0} analyzing {1}
MissingImageDialog.lbWarning.text=
MissingImageDialog.lbWarning.toolTipText=
CaseConverter.AlreadyMultiUser=Case is already multi-user!
CaseConverter.FinishedConverting=Finished converting
CaseConverter.To= to
CaseConverter.BadCaseSourceFolder=Case source folder does not exist!
CaseConverter.BadImageSourceFolder=Image source folder does not exist!
CaseConverter.BadDatabaseFileName=Database file does not exist!
CaseConverter.NonUniqueOutputFolder=Output folder not unique. Skipping
CaseConverter.NonUniqueDatabaseName=Database name not unique. Skipping.
CaseConverter.PotentiallyNonUniqueDatabaseName=Unclear if database name unique. Moving ahead.
CaseConverter.ConvertedToMultiUser=This case was converted to a Multi-user collaborative case on
CaseConverter.UnableToCopySourceImages=Unable to copy source images
CaseConverter.ConversionSuccessful=. Conversion successful:
CaseConverter.DeletingCase=Deleting original case folder
SingleUserCaseImporter.AlreadyMultiUser=Case is already multi-user!
SingleUserCaseImporter.FinishedConverting=Finished converting
SingleUserCaseImporter.To=to
SingleUserCaseImporter.BadCaseSourceFolder=Case source folder does not exist!
SingleUserCaseImporter.BadImageSourceFolder=Image source folder does not exist!
SingleUserCaseImporter.BadDatabaseFileName=Database file does not exist!
SingleUserCaseImporter.NonUniqueOutputFolder=Output folder not unique. Skipping
SingleUserCaseImporter.NonUniqueDatabaseName=Database name not unique. Skipping.
SingleUserCaseImporter.PotentiallyNonUniqueDatabaseName=Unclear if database name unique. Moving ahead.
SingleUserCaseImporter.ConvertedToMultiUser=This case was converted to a Multi-user collaborative case on
SingleUserCaseImporter.UnableToCopySourceImages=Unable to copy source images
SingleUserCaseImporter.ConversionSuccessful=. Conversion successful:
SingleUserCaseImporter.DeletingCase=Deleting original case folder

View File

@ -255,7 +255,7 @@ public class Case {
private final static String CACHE_FOLDER = "Cache"; //NON-NLS
private final static String EXPORT_FOLDER = "Export"; //NON-NLS
private final static String LOG_FOLDER = "Log"; //NON-NLS
private final static String MODULE_FOLDER = "ModuleOutput"; //NON-NLS
final static String MODULE_FOLDER = "ModuleOutput"; //NON-NLS
private final static String REPORTS_FOLDER = "Reports"; //NON-NLS
private final static String TEMP_FOLDER = "Temp"; //NON-NLS

View File

@ -44,6 +44,7 @@ import org.apache.commons.io.FileUtils;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.casemodule.Case.CaseType;
import static org.sleuthkit.autopsy.casemodule.Case.MODULE_FOLDER;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.CaseDbConnectionInfo;
import org.sleuthkit.datamodel.SleuthkitCase;
@ -59,9 +60,10 @@ public class SingleUserCaseImporter implements Runnable {
private static final String DOTAUT = ".aut"; //NON-NLS
public static final String CASE_CONVERSION_LOG_FILE = "case_import_log.txt"; //NON-NLS
private static final String logDateFormat = "yyyy/MM/dd HH:mm:ss"; //NON-NLS
//If TIMELINE_FOLDER changes, also update TIMELINE in EventsRepository
private static final String TIMELINE_FOLDER = "Timeline"; //NON-NLS
//If TIMELINE_FILE changes, also update TIMELINE_FILE in EventDB
private final static String TIMELINE_FILE = "events.db"; //NON-NLS
private static final String MODULE_FOLDER = "ModuleOutput"; //NON-NLS
private final static String AIM_LOG_FILE_NAME = "auto_ingest_log.txt"; //NON-NLS
private static final SimpleDateFormat simpleDateFormat = new SimpleDateFormat(logDateFormat);
private static final int MAX_DB_NAME_LENGTH = 63;
@ -79,7 +81,7 @@ public class SingleUserCaseImporter implements Runnable {
private XMLCaseManagement newXmlCaseManagement;
/**
* CaseConverter constructor
* SingleUserCaseImporter constructor
*
* @param caseInput the folder to start our case search from. Will find
* valid cases from this folder down, and process them.
@ -138,7 +140,7 @@ public class SingleUserCaseImporter implements Runnable {
// read old xml config
oldXmlCaseManagement.open(input.resolve(oldCaseName + DOTAUT).toString());
if (oldXmlCaseManagement.getCaseType() == CaseType.MULTI_USER_CASE) {
throw new Exception(NbBundle.getMessage(SingleUserCaseImporter.class, "CaseConverter.AlreadyMultiUser"));
throw new Exception(NbBundle.getMessage(SingleUserCaseImporter.class, "SingleUserCaseImporter.AlreadyMultiUser"));
}
String newCaseFolder = prepareOutput(caseOutputFolder, oldCaseFolder);
@ -177,12 +179,12 @@ public class SingleUserCaseImporter implements Runnable {
// and database in the given directory so the user shouldn't be able to accidently blow away
// their C drive.
if (deleteCase) {
log(NbBundle.getMessage(SingleUserCaseImporter.class, "CaseConverter.DeletingCase") + " " + input);
log(NbBundle.getMessage(SingleUserCaseImporter.class, "SingleUserCaseImporter.DeletingCase") + " " + input);
FileUtils.deleteDirectory(input.toFile());
}
log(NbBundle.getMessage(SingleUserCaseImporter.class, "CaseConverter.FinishedConverting")
+ input.toString() + NbBundle.getMessage(SingleUserCaseImporter.class, "CaseConverter.To")
log(NbBundle.getMessage(SingleUserCaseImporter.class, "SingleUserCaseImporter.FinishedConverting")
+ input.toString() + " " + NbBundle.getMessage(SingleUserCaseImporter.class, "SingleUserCaseImporter.To")
+ caseOutputFolder + File.separatorChar + newCaseFolder);
} catch (Exception exp) {
/// clean up here
@ -202,13 +204,13 @@ public class SingleUserCaseImporter implements Runnable {
*/
private void checkInput(File caseInput, File imageInput) throws Exception {
if (false == caseInput.exists()) {
throw new Exception(NbBundle.getMessage(SingleUserCaseImporter.class, "CaseConverter.BadCaseSourceFolder"));
throw new Exception(NbBundle.getMessage(SingleUserCaseImporter.class, "SingleUserCaseImporter.BadCaseSourceFolder"));
} else if ((imageInput != null) && (false == imageInput.exists())) {
throw new Exception(NbBundle.getMessage(SingleUserCaseImporter.class, "CaseConverter.BadImageSourceFolder"));
throw new Exception(NbBundle.getMessage(SingleUserCaseImporter.class, "SingleUserCaseImporter.BadImageSourceFolder"));
}
Path path = Paths.get(caseInput.toString(), AUTOPSY_DB_FILE);
if (false == path.toFile().exists()) {
throw new Exception(NbBundle.getMessage(SingleUserCaseImporter.class, "CaseConverter.BadDatabaseFileName"));
throw new Exception(NbBundle.getMessage(SingleUserCaseImporter.class, "SingleUserCaseImporter.BadDatabaseFileName"));
}
}
@ -236,7 +238,7 @@ public class SingleUserCaseImporter implements Runnable {
while (specificOutputFolder.exists()) {
if (number == Integer.MAX_VALUE) {
// oops. it never became unique. give up.
throw new Exception(NbBundle.getMessage(SingleUserCaseImporter.class, "CaseConverter.NonUniqueOutputFolder") + caseFolder);
throw new Exception(NbBundle.getMessage(SingleUserCaseImporter.class, "SingleUserCaseImporter.NonUniqueOutputFolder") + caseFolder);
}
temp = sanitizedCaseName + "_" + Integer.toString(number) + timeStamp; //NON-NLS
specificOutputFolder = Paths.get(caseOutputFolder, temp).toFile();
@ -263,7 +265,7 @@ public class SingleUserCaseImporter implements Runnable {
String hostName = NetworkUtils.getLocalHostName();
Path destination;
Path source;
if (input.toFile().exists()) {
destination = Paths.get(caseOutputFolder, newCaseFolder, hostName);
FileUtils.copyDirectory(input.toFile(), destination.toFile());
@ -280,12 +282,12 @@ public class SingleUserCaseImporter implements Runnable {
destination = Paths.get(caseOutputFolder, newCaseFolder, AIM_LOG_FILE_NAME);
FileUtils.copyFile(source.toFile(), destination.toFile());
try (PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(destination.toString(), true)))) {
out.println(NbBundle.getMessage(SingleUserCaseImporter.class, "CaseConverter.ConvertedToMultiUser") + new Date());
out.println(NbBundle.getMessage(SingleUserCaseImporter.class, "SingleUserCaseImporter.ConvertedToMultiUser") + new Date());
} catch (IOException e) {
// if unable to log it, no problem
}
}
// Remove the single-user .aut file, database, Timeline database and log
File oldDatabaseFile = Paths.get(caseOutputFolder, newCaseFolder, hostName, caseName + DOTAUT).toFile();
if (oldDatabaseFile.exists()) {
@ -959,7 +961,7 @@ public class SingleUserCaseImporter implements Runnable {
// not unique. add numbers before dbName.
if (number == Integer.MAX_VALUE) {
// oops. it never became unique. give up.
throw new Exception(NbBundle.getMessage(SingleUserCaseImporter.class, "CaseConverter.NonUniqueDatabaseName"));
throw new Exception(NbBundle.getMessage(SingleUserCaseImporter.class, "SingleUserCaseImporter.NonUniqueDatabaseName"));
}
sanitizedDbName = "_" + Integer.toString(number) + "_" + baseDbName; //NON-NLS
@ -974,7 +976,7 @@ public class SingleUserCaseImporter implements Runnable {
} else {
// Could be caused by database credentials, using user accounts that
// can not check if other databases exist, so allow it to continue
log(NbBundle.getMessage(SingleUserCaseImporter.class, "CaseConverter.PotentiallyNonUniqueDatabaseName"));
log(NbBundle.getMessage(SingleUserCaseImporter.class, "SingleUserCaseImporter.PotentiallyNonUniqueDatabaseName"));
}
return sanitizedDbName;
@ -1007,7 +1009,7 @@ public class SingleUserCaseImporter implements Runnable {
if (chosenInput != null && chosenInput.exists()) {
FileUtils.copyDirectory(chosenInput, output);
} else {
log(NbBundle.getMessage(SingleUserCaseImporter.class, "CaseConverter.UnableToCopySourceImages"));
log(NbBundle.getMessage(SingleUserCaseImporter.class, "SingleUserCaseImporter.UnableToCopySourceImages"));
}
return chosenInput;
}
@ -1195,11 +1197,11 @@ public class SingleUserCaseImporter implements Runnable {
* not. True if all was successful, false otherwise.
*/
private void closeLog(boolean result) {
log(NbBundle.getMessage(SingleUserCaseImporter.class, "CaseConverter.FinishedConverting")
+ caseInputFolder
+ NbBundle.getMessage(SingleUserCaseImporter.class, "CaseConverter.To")
log(NbBundle.getMessage(SingleUserCaseImporter.class, "SingleUserCaseImporter.FinishedConverting")
+ caseInputFolder + " "
+ NbBundle.getMessage(SingleUserCaseImporter.class, "SingleUserCaseImporter.To")
+ caseOutputFolder
+ NbBundle.getMessage(SingleUserCaseImporter.class, "CaseConverter.ConversionSuccessful")
+ NbBundle.getMessage(SingleUserCaseImporter.class, "SingleUserCaseImporter.ConversionSuccessful")
+ result);
if (writer != null) {

View File

@ -0,0 +1,299 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2015 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> 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.coreutils;
import java.io.File;
import java.io.IOException;
import java.net.InetAddress;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
public class UNCPathUtilities {
private static Map<String, String> drives;
private static final String MAPPED_DRIVES = "_mapped_drives.txt"; //NON-NLS
private static final String DATA_TRIGGER = "----------"; //NON-NLS
private static final String OK_TXT = "OK"; //NON-NLS
private static final String COLON = ":"; //NON-NLS
private static final String UNC_PATH_START = "\\\\"; //NON-NLS
private static final String C_DRIVE = "C:"; //NON-NLS
private static final int DRIVE_LEN = 2;
private static final int STARTING_OFFSET = 0;
private static final int REPLACEMENT_SIZE = 2;
private static final int FIRST_ITEM = 0;
private final String nameString;
/**
* Constructor
*/
public UNCPathUtilities() {
// get UUID for this instance
this.nameString = UUID.randomUUID().toString();
drives = getMappedDrives();
}
/**
* This method converts a passed in path to UNC if it is not already UNC.
* The UNC path will end up in one of the following two forms:
* \\hostname\somefolder\otherfolder or \\IP_ADDRESS\somefolder\otherfolder
*
* This is accomplished by checking the mapped drives list the operating
* system maintains and substituting where required. If the drive of the
* path passed in does not exist in the cached mapped drives list, you can
* force a rescan of the mapped drives list with rescanDrives(), then call
* this method again. This would be of use if the end user added a mapped
* drive while your dialog was up, for example.
*
* @param inputPath a String of the path to convert
* @return returns a successfully converted inputPath or null if unable to
* find a matching drive and convert it to UNC
*/
synchronized public String mappedDriveToUNC(String inputPath) {
if (inputPath != null) {
// If it is a C:, do not attempt to convert. This is for the single-user case.
if (inputPath.toUpperCase().startsWith(C_DRIVE)) {
return null;
}
if (false == isUNC(inputPath)) {
String uncPath = null;
try {
String currentDrive = Paths.get(inputPath).getRoot().toString().substring(STARTING_OFFSET, REPLACEMENT_SIZE);
String uncMapping = drives.get(currentDrive);
if (uncMapping != null) {
uncPath = uncMapping + inputPath.substring(REPLACEMENT_SIZE, inputPath.length());
}
} catch (Exception ex) {
// Didn't work. Skip it.
}
return uncPath;
} else {
return inputPath;
}
} else {
return null;
}
}
/**
* This method converts a passed in path to UNC if it is not already UNC.
* The UNC path will end up in one of the following two forms:
* \\hostname\somefolder\otherfolder or \\IP_ADDRESS\somefolder\otherfolder
*
* This is accomplished by checking the mapped drives list the operating
* system maintains and substituting where required. If the drive of the
* path passed in does not exist in the cached mapped drives list, you can
* force a rescan of the mapped drives list with rescanDrives(), then call
* this method again. This would be of use if the end user added a mapped
* drive while your dialog was up, for example.
*
* @param inputPath the path to convert
* @return returns a successfully converted inputPath or null if unable to
* find a matching drive and convert it to UNC
*/
synchronized public Path mappedDriveToUNC(Path inputPath) {
if (inputPath != null) {
String uncPath = UNCPathUtilities.this.mappedDriveToUNC(inputPath.toString());
if (uncPath == null) {
return null;
} else {
return Paths.get(uncPath);
}
} else {
return null;
}
}
/**
* Tests if the drive in the passed in path is a mapped drive.
*
* @param inputPath the Path to test.
* @return true if the passed in drive is mapped, false otherwise
*/
synchronized public boolean isDriveMapped(Path inputPath) {
if (inputPath != null) {
return isDriveMapped(inputPath.toString());
} else {
return false;
}
}
/**
* Tests if the drive in the passed in path is a mapped drive.
*
* @param inputPath the Path to test.
* @return true if the passed in drive is mapped, false otherwise
*/
synchronized public boolean isDriveMapped(String inputPath) {
if (inputPath != null) {
String shortenedPath = inputPath.substring(STARTING_OFFSET, DRIVE_LEN);
for (String s : drives.keySet()) {
if (shortenedPath.equals(s)) {
return true;
}
}
}
return false;
}
/**
* Takes a UNC path that may have an IP address in it and converts it to
* hostname, if it can resolve the hostname. Given
* \\10.11.12.13\some\folder, the result will be \\TEDS_COMPUTER\some\folder
* if the IP address 10.11.12.13 belongs to a machine with the hostname
* TEDS_COMPUTER and the local machine is able to resolve the hostname.
*
* @param inputPath the path to convert to a hostname UNC path
* @return the successfully converted path or null if unable to resolve
*/
synchronized public Path ipToHostName(Path inputPath) {
if (inputPath != null) {
return Paths.get(ipToHostName(inputPath.toString()));
} else {
return null;
}
}
/**
* Takes a UNC path that may have an IP address in it and converts it to
* hostname, if it can resolve the hostname. Given
* \\10.11.12.13\some\folder, the result will be \\TEDS_COMPUTER\some\folder
* if the IP address 10.11.12.13 belongs to a machine with the hostname
* TEDS_COMPUTER and the local machine is able to resolve the hostname.
*
* @param inputPath a String of the path to convert to a hostname UNC path
* @return the successfully converted path or null if unable to resolve
*/
synchronized public String ipToHostName(String inputPath) {
if (inputPath != null) {
String result = null;
try {
if (isUNC(Paths.get(inputPath))) {
String potentialIP = Paths.get(inputPath.substring(REPLACEMENT_SIZE)).getName(FIRST_ITEM).toString();
String hostname = InetAddress.getByName(potentialIP).getHostName();
result = inputPath.replaceAll(potentialIP, hostname);
}
} catch (Exception ex) {
// Could not resolve hostname for IP address, return null result
}
return result;
} else {
return null;
}
}
/**
* Test if a Path is UNC. It is considered UNC if it begins with \\
*
* @param inputPath the path to check
* @return true if the passed in Path is UNC, false otherwise
*/
synchronized public static boolean isUNC(Path inputPath) {
if (inputPath != null) {
return isUNC(inputPath.toString());
} else {
return false;
}
}
/**
* Test if a String path is UNC. It is considered UNC if it begins with \\
*
* @param inputPath the String of the path to check
* @return true if the passed in Path is UNC, false otherwise
*/
synchronized public static boolean isUNC(String inputPath) {
if (inputPath != null) {
return inputPath.startsWith(UNC_PATH_START);
} else {
return false;
}
}
/**
* Updates the list of mapped drives this class contains. This list is used
* to resolve mappedDriveToUNC and isDriveMapped calls. This is useful to
* call if the user has potentially added mapped drives to their system
* after the module calling mappedDriveToUNC has already begun running. Note
* this uses system I/O, so call it with some care.
*
*/
synchronized public void rescanDrives() {
drives = getMappedDrives();
}
/**
* Populates the list of mapped drives this class contains. The list is used
* to resolve mappedDriveToUNC and isDriveMapped calls. Note this uses
* system I/O, so call it with some care.
*
* @return the hashmap
*/
synchronized private Map<String, String> getMappedDrives() {
Map<String, String> driveMap = new HashMap<>();
File mappedDrive = new File(nameString + MAPPED_DRIVES);
try {
Files.deleteIfExists(mappedDrive.toPath());
ProcessBuilder builder = new ProcessBuilder("cmd", "/c", "net", "use"); //NON-NLS
builder.redirectOutput(mappedDrive);
builder.redirectError(mappedDrive);
Process p = builder.start(); // throws IOException
p.waitFor(10, TimeUnit.SECONDS);
try (Scanner scanner = new Scanner(mappedDrive)) {
// parse the data and place it in the hashmap
while (scanner.hasNext()) {
String entry1 = scanner.next();
if (entry1.startsWith(DATA_TRIGGER)) {
continue;
}
String entry2 = scanner.next();
if (entry2.startsWith(DATA_TRIGGER)) {
continue;
}
String entry3 = scanner.next();
if (entry3.startsWith(DATA_TRIGGER)) {
continue;
}
scanner.nextLine();
if (entry1.length() == DRIVE_LEN && !entry1.equals(OK_TXT) && entry1.endsWith(COLON)) {
driveMap.put(entry1, entry2); // if there was no leading status, populate drive
} else if (entry2.length() == DRIVE_LEN && entry2.endsWith(COLON)) {
driveMap.put(entry2, entry3); // if there was a leading status, populate drive
}
}
}
} catch (IOException | InterruptedException ex) {
// if we couldn't do it, no big deal
Logger.getLogger(UNCPathUtilities.class.getName()).log(Level.WARNING, "Unable to parse 'net use' output", ex); //NON-NLS
} finally {
try {
Files.deleteIfExists(mappedDrive.toPath());
} catch (IOException ex) {
// if we couldn't do it, no big deal
}
}
return driveMap;
}
}

View File

@ -10,6 +10,7 @@ unsupportedOS.message=PhotoRec Module is supported only on Windows platforms
missingExecutable.message=Unable to locate PhotoRec executable.
cannotRunExecutable.message=Unable to execute PhotoRec
cannotCreateOutputDir.message=Unable to create output directory: {0}
PhotoRecIngestModule.nonHostnameUNCPathUsed=Photorec cannot operate on a UNC path containing IP addresses
PhotoRecIngestModule.processTerminated=PhotoRec Carver ingest module was terminated due to exceeding max allowable run time when scanning
PhotoRecIngestModule.moduleError=PhotoRec Carver Module Error
PhotoRecIngestModule.UnableToCarve=Unable to carve file: {0}

View File

@ -38,18 +38,12 @@ import org.openide.modules.InstalledFileLocator;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.coreutils.ExecUtil;
import org.sleuthkit.autopsy.coreutils.FileUtil;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
import org.sleuthkit.autopsy.datamodel.ContentUtils;
import org.sleuthkit.autopsy.ingest.FileIngestModule;
import org.sleuthkit.autopsy.ingest.FileIngestModuleProcessTerminator;
import org.sleuthkit.autopsy.ingest.IngestJobContext;
import org.sleuthkit.autopsy.ingest.IngestModule;
import org.sleuthkit.autopsy.ingest.IngestModuleReferenceCounter;
import org.sleuthkit.autopsy.ingest.IngestServices;
import org.sleuthkit.autopsy.ingest.ModuleContentEvent;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.Image;
@ -58,6 +52,7 @@ import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskData;
import org.sleuthkit.datamodel.Volume;
import org.sleuthkit.autopsy.coreutils.FileUtil;
import org.sleuthkit.autopsy.coreutils.UNCPathUtilities;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
import org.sleuthkit.autopsy.ingest.ProcTerminationCode;
@ -67,7 +62,8 @@ import org.sleuthkit.autopsy.ingest.IngestServices;
import org.sleuthkit.autopsy.ingest.ModuleContentEvent;
/**
* A file ingest module that runs the Unallocated Carver executable with unallocated space files as input.
* A file ingest module that runs the Unallocated Carver executable with
* unallocated space files as input.
*/
final class PhotoRecCarverFileIngestModule implements FileIngestModule {
@ -85,7 +81,8 @@ final class PhotoRecCarverFileIngestModule implements FileIngestModule {
private Path rootOutputDirPath;
private File executableFile;
private IngestServices services;
private UNCPathUtilities uncPathUtilities = new UNCPathUtilities();
/**
* @inheritDoc
*/
@ -102,7 +99,7 @@ final class PhotoRecCarverFileIngestModule implements FileIngestModule {
throw new IngestModule.IngestModuleException(NbBundle.getMessage(this.getClass(), "unallocatedSpaceProcessingSettingsError.message"));
}
this.rootOutputDirPath = PhotoRecCarverFileIngestModule.createModuleOutputDirectoryForCase();
this.rootOutputDirPath = createModuleOutputDirectoryForCase();
Path execName = Paths.get(PHOTOREC_DIRECTORY, PHOTOREC_EXECUTABLE);
executableFile = locateExecutable(execName.toString());
@ -122,8 +119,7 @@ final class PhotoRecCarverFileIngestModule implements FileIngestModule {
// Save the directories for the current job.
PhotoRecCarverFileIngestModule.pathsByJob.put(this.context.getJobId(), new WorkingPaths(outputDirPath, tempDirPath));
}
catch (SecurityException | IOException | UnsupportedOperationException ex) {
} catch (SecurityException | IOException | UnsupportedOperationException ex) {
throw new IngestModule.IngestModuleException(NbBundle.getMessage(this.getClass(), "cannotCreateOutputDir.message", ex.getLocalizedMessage()));
}
}
@ -188,10 +184,10 @@ final class PhotoRecCarverFileIngestModule implements FileIngestModule {
processAndSettings.environment().put("__COMPAT_LAYER", "RunAsInvoker"); //NON-NLS
processAndSettings.redirectErrorStream(true);
processAndSettings.redirectOutput(Redirect.appendTo(log));
FileIngestModuleProcessTerminator terminator = new FileIngestModuleProcessTerminator(this.context, true);
int exitValue = ExecUtil.execute(processAndSettings, terminator);
if (this.context.fileIngestIsCancelled() == true) {
// if it was cancelled by the user, result is OK
cleanup(outputDirPath, tempFilePath);
@ -224,7 +220,7 @@ final class PhotoRecCarverFileIngestModule implements FileIngestModule {
}
}
}
// Now that we've cleaned up the folders and data files, parse the xml output file to add carved items into the database
PhotoRecCarverOutputParser parser = new PhotoRecCarverOutputParser(outputDirPath);
List<LayoutFile> theList = parser.parse(newAuditFile, id, file);
@ -232,13 +228,10 @@ final class PhotoRecCarverFileIngestModule implements FileIngestModule {
context.addFilesToJob(new ArrayList<>(theList));
services.fireModuleContentEvent(new ModuleContentEvent(theList.get(0))); // fire an event to update the tree
}
}
catch (IOException ex) {
} catch (IOException ex) {
logger.log(Level.SEVERE, "Error processing " + file.getName() + " with PhotoRec carver", ex); // NON-NLS
return IngestModule.ProcessResult.ERROR;
}
finally {
} finally {
if (null != tempFilePath && Files.exists(tempFilePath)) {
// Get rid of the unallocated space file.
tempFilePath.toFile().delete();
@ -247,7 +240,7 @@ final class PhotoRecCarverFileIngestModule implements FileIngestModule {
return IngestModule.ProcessResult.OK;
}
private void cleanup(Path outputDirPath, Path tempFilePath) {
// cleanup the output path
FileUtil.deleteDir(new File(outputDirPath.toString()));
@ -267,8 +260,7 @@ final class PhotoRecCarverFileIngestModule implements FileIngestModule {
// the working paths map entry for the job and deletes the temp dir.
WorkingPaths paths = PhotoRecCarverFileIngestModule.pathsByJob.remove(this.context.getJobId());
FileUtil.deleteDir(new File(paths.getTempDirPath().toString()));
}
catch (SecurityException ex) {
} catch (SecurityException ex) {
logger.log(Level.SEVERE, "Error shutting down PhotoRec carver module", ex); // NON-NLS
}
}
@ -294,20 +286,26 @@ final class PhotoRecCarverFileIngestModule implements FileIngestModule {
}
/**
* Creates the output directory for this module for the current case, if it does not already exist.
* Creates the output directory for this module for the current case, if it
* does not already exist.
*
* @return The absolute path of the output directory.
* @throws org.sleuthkit.autopsy.ingest.IngestModule.IngestModuleException
*/
synchronized static Path createModuleOutputDirectoryForCase() throws IngestModule.IngestModuleException {
synchronized Path createModuleOutputDirectoryForCase() throws IngestModule.IngestModuleException {
Path path = Paths.get(Case.getCurrentCase().getModuleDirectory(), PhotoRecCarverIngestModuleFactory.getModuleName());
if (UNCPathUtilities.isUNC(path)) {
// if the UNC path is using an IP address, convert to hostname
path = uncPathUtilities.ipToHostName(path);
if (path == null) {
throw new IngestModule.IngestModuleException(NbBundle.getMessage(PhotoRecCarverFileIngestModule.class, "PhotoRecIngestModule.nonHostnameUNCPathUsed"));
}
}
try {
Files.createDirectory(path);
}
catch (FileAlreadyExistsException ex) {
} catch (FileAlreadyExistsException ex) {
// No worries.
}
catch (IOException | SecurityException | UnsupportedOperationException ex) {
} catch (IOException | SecurityException | UnsupportedOperationException ex) {
throw new IngestModule.IngestModuleException(NbBundle.getMessage(PhotoRecCarverFileIngestModule.class, "cannotCreateOutputDir.message", ex.getLocalizedMessage()));
}
return path;
@ -331,8 +329,7 @@ final class PhotoRecCarverFileIngestModule implements FileIngestModule {
}
parent = parent.getParent();
}
}
catch (TskCoreException ex) {
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "PhotoRec carver exception while trying to get parent of AbstractFile.", ex); //NON-NLS
}
return id;

View File

@ -108,6 +108,9 @@ public class EventDB {
private static final String WAS_INGEST_RUNNING_KEY = "was_ingest_running"; // NON-NLS
//If EVENTS_DATABASE changes, also update TIMELINE_FILE in SingleUserCaseImporter
private static final String TIMELINE_FILE = "events.db"; // NON-NLS
static {
//make sure sqlite driver is loaded // possibly redundant
try {
@ -128,7 +131,7 @@ public class EventDB {
*/
public static EventDB getEventDB(String dbPath) {
try {
EventDB eventDB = new EventDB(dbPath + File.separator + "events.db"); // NON-NLS
EventDB eventDB = new EventDB(dbPath + File.separator + TIMELINE_FILE); // NON-NLS
return eventDB;
} catch (SQLException ex) {

View File

@ -94,6 +94,7 @@ public class EventsRepository {
private final LoadingCache<ZoomParams, List<AggregateEvent>> aggregateEventsCache;
//If TIMELINE changes, also update TIMELINE_FOLDER in SingleUserCaseImporter
private static final String TIMELINE = "Timeline";
public Interval getBoundingEventsInterval(Interval timeRange, Filter filter) {

View File

@ -63,6 +63,7 @@ import org.apache.solr.client.solrj.response.CoreAdminResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrException;
import org.sleuthkit.autopsy.casemodule.Case.CaseType;
import org.sleuthkit.autopsy.coreutils.UNCPathUtilities;
import org.sleuthkit.autopsy.core.UserPreferences;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
@ -167,7 +168,8 @@ public class Server {
private int currentSolrServerPort = 0;
private int currentSolrStopPort = 0;
private static final boolean DEBUG = false;//(Version.getBuildType() == Version.Type.DEVELOPMENT);
private final UNCPathUtilities uncPathUtilities = new UNCPathUtilities();
public enum CORE_EVT_STATES {
STOPPED, STARTED
@ -650,9 +652,16 @@ public class Server {
* @return absolute path to index dir
*/
String getIndexDirPath(Case theCase) {
String indexDir = theCase.getModuleDirectory() +
File.separator + "keywordsearch" + File.separator + "data"; //NON-NLS
return indexDir;
String indexDir = theCase.getModuleDirectory() + File.separator + "keywordsearch" + File.separator + "data"; //NON-NLS
String result = uncPathUtilities.mappedDriveToUNC(indexDir);
if (result == null) {
uncPathUtilities.rescanDrives();
result = uncPathUtilities.mappedDriveToUNC(indexDir);
}
if (result == null) {
return indexDir;
}
return result;
}
/**