mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-19 19:14:55 +00:00
Merge pull request #1468 from karlmortensen/hostname_not_ip
use hostname in UNC paths for photorec
This commit is contained in:
commit
6a0a4fd4cb
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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) {
|
||||
|
299
Core/src/org/sleuthkit/autopsy/coreutils/UNCPathUtilities.java
Normal file
299
Core/src/org/sleuthkit/autopsy/coreutils/UNCPathUtilities.java
Normal 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;
|
||||
}
|
||||
}
|
@ -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}
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user