mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-20 11:26:53 +00:00
use hostname in UNC paths for photorec
This commit is contained in:
parent
e8779a86fb
commit
428d0bd90a
198
Core/src/org/sleuthkit/autopsy/coreutils/HandleUNC.java
Normal file
198
Core/src/org/sleuthkit/autopsy/coreutils/HandleUNC.java
Normal file
@ -0,0 +1,198 @@
|
|||||||
|
/*
|
||||||
|
* 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.concurrent.TimeUnit;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
public class HandleUNC {
|
||||||
|
|
||||||
|
private static HandleUNC instance = null;
|
||||||
|
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 int MAX_LINE_SCANS = 500;
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access method for singleton
|
||||||
|
*
|
||||||
|
* @return HandleUNC singleton object
|
||||||
|
*/
|
||||||
|
public synchronized static HandleUNC getInstance() {
|
||||||
|
if (instance == null) {
|
||||||
|
instance = new HandleUNC();
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private constructor for singleton
|
||||||
|
*/
|
||||||
|
private HandleUNC() {
|
||||||
|
drives = getMappedDrives();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Try to substitute in the path for a UNC string.
|
||||||
|
*
|
||||||
|
* @param path the path to substitute.
|
||||||
|
* @return returns the original string if unsuccessful, the substituted
|
||||||
|
* string if successful.
|
||||||
|
*/
|
||||||
|
public String attemptUNCSubstitution(String path) {
|
||||||
|
return attemptUNCSubstitution(Paths.get(path)).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Try to substitute in the path for a UNC string.
|
||||||
|
*
|
||||||
|
* @param path the path to substitute.
|
||||||
|
* @return returns the original string if unsuccessful, the substituted
|
||||||
|
* string if successful.
|
||||||
|
*/
|
||||||
|
public Path attemptUNCSubstitution(Path path) {
|
||||||
|
String uncPath = path.toString();
|
||||||
|
if (false == isUNC(path)) {
|
||||||
|
try {
|
||||||
|
String currentDrive = path.getRoot().toString().substring(STARTING_OFFSET, REPLACEMENT_SIZE);
|
||||||
|
String uncMapping = drives.get(currentDrive);
|
||||||
|
if (uncMapping != null) {
|
||||||
|
uncPath = uncMapping + uncPath.substring(REPLACEMENT_SIZE, uncPath.length());
|
||||||
|
}
|
||||||
|
} catch (Exception ex) {
|
||||||
|
// Didn't work. Skip it.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Paths.get(uncPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Takes a UNC path that may have an IP address in it and converts it to
|
||||||
|
* hostname, if it can.
|
||||||
|
*
|
||||||
|
* @param inputPath the path to convert to a hostname UNC path
|
||||||
|
* @return the path that was passed in if it was hostname before, the
|
||||||
|
* converted path if it was successfully converted
|
||||||
|
*/
|
||||||
|
public Path ipToHostName(Path inputPath) {
|
||||||
|
return Paths.get(ipToHostName(inputPath.toString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Takes a UNC path that may have an IP address in it and converts it to
|
||||||
|
* hostname, if it can.
|
||||||
|
*
|
||||||
|
* @param inputPath the path to convert to a hostname UNC path
|
||||||
|
* @return the path that was passed in if it was hostname before, the
|
||||||
|
* converted path if it was successfully converted
|
||||||
|
*/
|
||||||
|
public String ipToHostName(String inputPath) {
|
||||||
|
String result = inputPath;
|
||||||
|
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) {
|
||||||
|
// We didn't find a hostname for this potential IP address. Move on.
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test if a String is UNC
|
||||||
|
*
|
||||||
|
* @param inputPath
|
||||||
|
* @return true if UNC, false otherwise
|
||||||
|
*/
|
||||||
|
public static boolean isUNC(Path inputPath) {
|
||||||
|
return isUNC(inputPath.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test if a Path is UNC
|
||||||
|
*
|
||||||
|
* @param inputPath
|
||||||
|
* @return true if UNC, false otherwise
|
||||||
|
*/
|
||||||
|
public static boolean isUNC(String inputPath) {
|
||||||
|
return inputPath.startsWith(UNC_PATH_START);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Populate the mapped drives
|
||||||
|
*
|
||||||
|
* @return the hashmap
|
||||||
|
*/
|
||||||
|
private static Map<String, String> getMappedDrives() {
|
||||||
|
Map<String, String> driveMap = new HashMap<>();
|
||||||
|
try {
|
||||||
|
File mappedDrive = new File(MAPPED_DRIVES);
|
||||||
|
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)) {
|
||||||
|
int safetyCount = 0;
|
||||||
|
|
||||||
|
// scan past the header information until we find trigger
|
||||||
|
while (scanner.hasNext() && !scanner.nextLine().equals(DATA_TRIGGER)) {
|
||||||
|
if (++safetyCount > MAX_LINE_SCANS) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// parse the data and place it in the hashmap
|
||||||
|
while (scanner.hasNext()) {
|
||||||
|
String entry1 = scanner.next();
|
||||||
|
String entry2 = scanner.next();
|
||||||
|
String entry3 = scanner.next();
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Files.deleteIfExists(mappedDrive.toPath());
|
||||||
|
} catch (IOException | InterruptedException ex) {
|
||||||
|
// if we couldn't do it, no big deal
|
||||||
|
Logger.getLogger(HandleUNC.class.getName()).log(Level.WARNING, "Unable to parse 'net use' output", ex); //NON-NLS
|
||||||
|
}
|
||||||
|
return driveMap;
|
||||||
|
}
|
||||||
|
}
|
@ -58,6 +58,7 @@ import org.sleuthkit.datamodel.TskCoreException;
|
|||||||
import org.sleuthkit.datamodel.TskData;
|
import org.sleuthkit.datamodel.TskData;
|
||||||
import org.sleuthkit.datamodel.Volume;
|
import org.sleuthkit.datamodel.Volume;
|
||||||
import org.sleuthkit.autopsy.coreutils.FileUtil;
|
import org.sleuthkit.autopsy.coreutils.FileUtil;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.HandleUNC;
|
||||||
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
||||||
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
|
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
|
||||||
import org.sleuthkit.autopsy.ingest.ProcTerminationCode;
|
import org.sleuthkit.autopsy.ingest.ProcTerminationCode;
|
||||||
@ -67,7 +68,8 @@ import org.sleuthkit.autopsy.ingest.IngestServices;
|
|||||||
import org.sleuthkit.autopsy.ingest.ModuleContentEvent;
|
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 {
|
final class PhotoRecCarverFileIngestModule implements FileIngestModule {
|
||||||
|
|
||||||
@ -122,8 +124,7 @@ final class PhotoRecCarverFileIngestModule implements FileIngestModule {
|
|||||||
|
|
||||||
// Save the directories for the current job.
|
// Save the directories for the current job.
|
||||||
PhotoRecCarverFileIngestModule.pathsByJob.put(this.context.getJobId(), new WorkingPaths(outputDirPath, tempDirPath));
|
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()));
|
throw new IngestModule.IngestModuleException(NbBundle.getMessage(this.getClass(), "cannotCreateOutputDir.message", ex.getLocalizedMessage()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -232,13 +233,10 @@ final class PhotoRecCarverFileIngestModule implements FileIngestModule {
|
|||||||
context.addFilesToJob(new ArrayList<>(theList));
|
context.addFilesToJob(new ArrayList<>(theList));
|
||||||
services.fireModuleContentEvent(new ModuleContentEvent(theList.get(0))); // fire an event to update the tree
|
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
|
logger.log(Level.SEVERE, "Error processing " + file.getName() + " with PhotoRec carver", ex); // NON-NLS
|
||||||
return IngestModule.ProcessResult.ERROR;
|
return IngestModule.ProcessResult.ERROR;
|
||||||
}
|
} finally {
|
||||||
|
|
||||||
finally {
|
|
||||||
if (null != tempFilePath && Files.exists(tempFilePath)) {
|
if (null != tempFilePath && Files.exists(tempFilePath)) {
|
||||||
// Get rid of the unallocated space file.
|
// Get rid of the unallocated space file.
|
||||||
tempFilePath.toFile().delete();
|
tempFilePath.toFile().delete();
|
||||||
@ -267,8 +265,7 @@ final class PhotoRecCarverFileIngestModule implements FileIngestModule {
|
|||||||
// the working paths map entry for the job and deletes the temp dir.
|
// the working paths map entry for the job and deletes the temp dir.
|
||||||
WorkingPaths paths = PhotoRecCarverFileIngestModule.pathsByJob.remove(this.context.getJobId());
|
WorkingPaths paths = PhotoRecCarverFileIngestModule.pathsByJob.remove(this.context.getJobId());
|
||||||
FileUtil.deleteDir(new File(paths.getTempDirPath().toString()));
|
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
|
logger.log(Level.SEVERE, "Error shutting down PhotoRec carver module", ex); // NON-NLS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -294,20 +291,23 @@ 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.
|
* @return The absolute path of the output directory.
|
||||||
* @throws org.sleuthkit.autopsy.ingest.IngestModule.IngestModuleException
|
* @throws org.sleuthkit.autopsy.ingest.IngestModule.IngestModuleException
|
||||||
*/
|
*/
|
||||||
synchronized static Path createModuleOutputDirectoryForCase() throws IngestModule.IngestModuleException {
|
synchronized static Path createModuleOutputDirectoryForCase() throws IngestModule.IngestModuleException {
|
||||||
Path path = Paths.get(Case.getCurrentCase().getModuleDirectory(), PhotoRecCarverIngestModuleFactory.getModuleName());
|
Path path = Paths.get(Case.getCurrentCase().getModuleDirectory(), PhotoRecCarverIngestModuleFactory.getModuleName());
|
||||||
|
if (HandleUNC.isUNC(path)) {
|
||||||
|
// if the UNC path is using an IP address, convert to hostname
|
||||||
|
path = HandleUNC.getInstance().ipToHostName(path);
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
Files.createDirectory(path);
|
Files.createDirectory(path);
|
||||||
}
|
} catch (FileAlreadyExistsException ex) {
|
||||||
catch (FileAlreadyExistsException ex) {
|
|
||||||
// No worries.
|
// No worries.
|
||||||
}
|
} catch (IOException | SecurityException | UnsupportedOperationException ex) {
|
||||||
catch (IOException | SecurityException | UnsupportedOperationException ex) {
|
|
||||||
throw new IngestModule.IngestModuleException(NbBundle.getMessage(PhotoRecCarverFileIngestModule.class, "cannotCreateOutputDir.message", ex.getLocalizedMessage()));
|
throw new IngestModule.IngestModuleException(NbBundle.getMessage(PhotoRecCarverFileIngestModule.class, "cannotCreateOutputDir.message", ex.getLocalizedMessage()));
|
||||||
}
|
}
|
||||||
return path;
|
return path;
|
||||||
@ -331,8 +331,7 @@ final class PhotoRecCarverFileIngestModule implements FileIngestModule {
|
|||||||
}
|
}
|
||||||
parent = parent.getParent();
|
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
|
logger.log(Level.SEVERE, "PhotoRec carver exception while trying to get parent of AbstractFile.", ex); //NON-NLS
|
||||||
}
|
}
|
||||||
return id;
|
return id;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user