mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-20 03:24:55 +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.Volume;
|
||||
import org.sleuthkit.autopsy.coreutils.FileUtil;
|
||||
import org.sleuthkit.autopsy.coreutils.HandleUNC;
|
||||
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
||||
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
|
||||
import org.sleuthkit.autopsy.ingest.ProcTerminationCode;
|
||||
@ -67,7 +68,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 +87,7 @@ final class PhotoRecCarverFileIngestModule implements FileIngestModule {
|
||||
private Path rootOutputDirPath;
|
||||
private File executableFile;
|
||||
private IngestServices services;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@ -122,8 +124,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 +189,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 +225,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 +233,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 +245,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 +265,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 +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.
|
||||
* @throws org.sleuthkit.autopsy.ingest.IngestModule.IngestModuleException
|
||||
*/
|
||||
synchronized static Path createModuleOutputDirectoryForCase() throws IngestModule.IngestModuleException {
|
||||
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 {
|
||||
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 +331,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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user