diff options
-rw-r--r-- | src/Core/Unix/CoreService.cpp | 30 | ||||
-rw-r--r-- | src/Core/Unix/CoreUnix.cpp | 128 | ||||
-rw-r--r-- | src/Core/Unix/FreeBSD/CoreFreeBSD.cpp | 4 | ||||
-rw-r--r-- | src/Core/Unix/MacOSX/CoreMacOSX.cpp | 10 | ||||
-rw-r--r-- | src/Core/Unix/OpenBSD/CoreOpenBSD.cpp | 4 | ||||
-rw-r--r-- | src/Core/Unix/Solaris/CoreSolaris.cpp | 4 | ||||
-rw-r--r-- | src/Main/UserInterface.cpp | 80 | ||||
-rw-r--r-- | src/Platform/Unix/Process.cpp | 63 | ||||
-rw-r--r-- | src/Platform/Unix/Process.h | 2 |
9 files changed, 226 insertions, 99 deletions
diff --git a/src/Core/Unix/CoreService.cpp b/src/Core/Unix/CoreService.cpp index 7071f71c..c2eb2bf0 100644 --- a/src/Core/Unix/CoreService.cpp +++ b/src/Core/Unix/CoreService.cpp @@ -300,7 +300,14 @@ namespace VeraCrypt // We are using -n to avoid prompting the user for a password. // We are redirecting stderr to stdout and discarding both to avoid any output. // This approach also works on newer macOS versions (12.0 and later). - FILE* pipe = popen("sudo -n -l > /dev/null 2>&1", "r"); // redirect stderr to stdout and discard both. + std::string errorMsg; + + string sudoAbsolutePath = Process::FindSystemBinary("sudo", errorMsg); + if (sudoAbsolutePath.empty()) + throw SystemException(SRC_POS, errorMsg); + + std::string popenCommand = sudoAbsolutePath + " -n -l > /dev/null 2>&1"; // We redirect stderr to stdout (2>&1) to be able to catch the result of the command + FILE* pipe = popen(popenCommand.c_str(), "r"); if (pipe) { // We only care about the exit code @@ -396,15 +403,26 @@ namespace VeraCrypt { try { + // Throw exception if sudo is not found in secure locations + std::string errorMsg; + string sudoPath = Process::FindSystemBinary("sudo", errorMsg); + if (sudoPath.empty()) + throw SystemException(SRC_POS, errorMsg); + + string appPath = request.ApplicationExecutablePath; + // if appPath is empty or not absolute, use FindSystemBinary to get the full path of veracrpyt executable + if (appPath.empty() || appPath[0] != '/') + { + appPath = Process::FindSystemBinary("veracrypt", errorMsg); + if (appPath.empty()) + throw SystemException(SRC_POS, errorMsg); + } + throw_sys_if (dup2 (inPipe->GetReadFD(), STDIN_FILENO) == -1); throw_sys_if (dup2 (outPipe->GetWriteFD(), STDOUT_FILENO) == -1); throw_sys_if (dup2 (errPipe.GetWriteFD(), STDERR_FILENO) == -1); - string appPath = request.ApplicationExecutablePath; - if (appPath.empty()) - appPath = "veracrypt"; - - const char *args[] = { "sudo", "-S", "-p", "", appPath.c_str(), TC_CORE_SERVICE_CMDLINE_OPTION, nullptr }; + const char *args[] = { sudoPath.c_str(), "-S", "-p", "", appPath.c_str(), TC_CORE_SERVICE_CMDLINE_OPTION, nullptr }; execvp (args[0], ((char* const*) args)); throw SystemException (SRC_POS, args[0]); } diff --git a/src/Core/Unix/CoreUnix.cpp b/src/Core/Unix/CoreUnix.cpp index 5cdbfda6..f6827806 100644 --- a/src/Core/Unix/CoreUnix.cpp +++ b/src/Core/Unix/CoreUnix.cpp @@ -29,6 +29,41 @@ namespace VeraCrypt static bool SamePath (const string& path1, const string& path2); #endif + // Struct to hold terminal emulator information + struct TerminalInfo { + const char* name; + const char** args; + const char** dependency_path; + }; + + // Popular terminal emulators data and arguments + static const char* xterm_args[] = {"-T", "fsck", "-e", NULL}; + + static const char* gnome_args[] = {"--title", "fsck", "--", "sh", "-c", NULL}; + static const char* gnome_deps[] = {"dbus-launch", NULL}; + + static const char* konsole_args[] = {"--hold", "-p", "tabtitle=fsck", "-e", "sh", "-c", NULL}; + static const char* xfce4_args[] = {"--title=fsck", "-x", "sh", "-c", NULL}; + static const char* mate_args[] = {"--title", "fsck", "--", "sh", "-c", NULL}; + static const char* lxterminal_args[] = {"--title=fsck", "-e", "sh", "-c", NULL}; + static const char* terminator_args[] = {"-T", "fsck", "-x", "sh", "-c", NULL}; + static const char* urxvt_args[] = {"-title", "fsck", "-e", "sh", "-c", NULL}; + static const char* st_args[] = {"-t", "fsck", "-e", "sh", "-c", NULL}; + + // List of popular terminal emulators + static const TerminalInfo TERMINALS[] = { + {"xterm", xterm_args, NULL}, + {"gnome-terminal", gnome_args, gnome_deps}, + {"konsole", konsole_args, NULL}, + {"xfce4-terminal", xfce4_args, NULL}, + {"mate-terminal", mate_args, NULL}, + {"lxterminal", lxterminal_args, NULL}, + {"terminator", terminator_args, NULL}, + {"urxvt", urxvt_args, NULL}, + {"st", st_args, NULL}, + {NULL, NULL, NULL} + }; + CoreUnix::CoreUnix () { signal (SIGPIPE, SIG_IGN); @@ -47,14 +82,16 @@ namespace VeraCrypt if (!mountedVolume->MountPoint.IsEmpty()) DismountFilesystem (mountedVolume->MountPoint, false); - list <string> args; - - args.push_back ("-T"); - args.push_back ("fsck"); + // Find system fsck first + std::string errorMsg; + std::string fsckPath = Process::FindSystemBinary("fsck", errorMsg); + if (fsckPath.empty()) { + throw SystemException(SRC_POS, errorMsg); + } - args.push_back ("-e"); + list <string> args; - string xargs = "fsck "; + string xargs = fsckPath + " "; // Use absolute fsck path #ifdef TC_LINUX if (!repair) @@ -64,49 +101,48 @@ namespace VeraCrypt #endif xargs += string (mountedVolume->VirtualDevice) + "; echo '[Done]'; read W"; - args.push_back (xargs); + // Try each terminal + for (const TerminalInfo* term = TERMINALS; term->name != NULL; ++term) { + errno = 0; + std::string termPath = Process::FindSystemBinary(term->name, errorMsg); + if (termPath.length() > 0) { + // check dependencies + if (term->dependency_path) { + bool depFound = true; + for (const char** dep = term->dependency_path; *dep != NULL; ++dep) { + string depPath = Process::FindSystemBinary(*dep, errorMsg); + if (depPath.empty()) { + depFound = false; + break; + } + } - try - { - Process::Execute ("xterm", args, 1000); - } catch (TimeOut&) { } -#ifdef TC_LINUX - catch (SystemException&) - { - // xterm not available. Try with KDE konsole if it exists - struct stat sb; - if (stat("/usr/bin/konsole", &sb) == 0) - { - args.clear (); - args.push_back ("-p"); - args.push_back ("tabtitle=fsck"); - args.push_back ("-e"); - args.push_back ("sh"); - args.push_back ("-c"); - args.push_back (xargs); - try - { - Process::Execute ("konsole", args, 1000); - } catch (TimeOut&) { } - } - else if (stat("/usr/bin/gnome-terminal", &sb) == 0 && stat("/usr/bin/dbus-launch", &sb) == 0) - { - args.clear (); - args.push_back ("--title"); - args.push_back ("fsck"); - args.push_back ("--"); - args.push_back ("sh"); - args.push_back ("-c"); - args.push_back (xargs); - try - { - Process::Execute ("gnome-terminal", args, 1000); - } catch (TimeOut&) { } + if (!depFound) { + continue; // dependency not found, skip + } + } + + // Build args + std::list<std::string> args; + for (const char** arg = term->args; *arg != NULL; ++arg) { + args.push_back(*arg); + } + args.push_back(xargs); + + try { + Process::Execute (termPath, args, 1000); + return; + } + catch (TimeOut&) { + return; + } + catch (SystemException&) { + // Continue to next terminal + } } - else - throw TerminalNotFound(); } -#endif + + throw TerminalNotFound(); } void CoreUnix::DismountFilesystem (const DirectoryPath &mountPoint, bool force) const diff --git a/src/Core/Unix/FreeBSD/CoreFreeBSD.cpp b/src/Core/Unix/FreeBSD/CoreFreeBSD.cpp index 0192bcff..8f5b8048 100644 --- a/src/Core/Unix/FreeBSD/CoreFreeBSD.cpp +++ b/src/Core/Unix/FreeBSD/CoreFreeBSD.cpp @@ -46,7 +46,7 @@ namespace VeraCrypt args.push_back ("-f"); args.push_back (filePath); - string dev = StringConverter::Trim (Process::Execute ("mdconfig", args)); + string dev = StringConverter::Trim (Process::Execute ("/sbin/mdconfig", args)); if (dev.find ("/") == string::npos) dev = string ("/dev/") + dev; @@ -65,7 +65,7 @@ namespace VeraCrypt { try { - Process::Execute ("mdconfig", args); + Process::Execute ("/sbin/mdconfig", args); break; } catch (ExecutedProcessFailed&) diff --git a/src/Core/Unix/MacOSX/CoreMacOSX.cpp b/src/Core/Unix/MacOSX/CoreMacOSX.cpp index ccbd5a58..762552de 100644 --- a/src/Core/Unix/MacOSX/CoreMacOSX.cpp +++ b/src/Core/Unix/MacOSX/CoreMacOSX.cpp @@ -47,7 +47,7 @@ namespace VeraCrypt try { - Process::Execute ("hdiutil", args); + Process::Execute ("/usr/bin/hdiutil", args); } catch (ExecutedProcessFailed &e) { @@ -84,7 +84,7 @@ namespace VeraCrypt { try { - Process::Execute ("umount", args); + Process::Execute ("/usr/bin/umount", args); break; } catch (ExecutedProcessFailed&) @@ -114,7 +114,7 @@ namespace VeraCrypt else args.push_back ("/System/Applications/Utilities/Disk Utility.app"); - Process::Execute ("open", args); + Process::Execute ("/usr/bin/open", args); } void CoreMacOSX::MountAuxVolumeImage (const DirectoryPath &auxMountPoint, const MountOptions &options) const @@ -190,7 +190,7 @@ namespace VeraCrypt { try { - xml = Process::Execute ("hdiutil", args); + xml = Process::Execute ("/usr/bin/hdiutil", args); break; } catch (ExecutedProcessFailed &e) @@ -233,7 +233,7 @@ namespace VeraCrypt args.push_back (volImage); args.push_back ("-force"); - Process::Execute ("hdiutil", args); + Process::Execute ("/usr/bin/hdiutil", args); } catch (ExecutedProcessFailed&) { } throw; diff --git a/src/Core/Unix/OpenBSD/CoreOpenBSD.cpp b/src/Core/Unix/OpenBSD/CoreOpenBSD.cpp index b3ff3bd1..161d4a79 100644 --- a/src/Core/Unix/OpenBSD/CoreOpenBSD.cpp +++ b/src/Core/Unix/OpenBSD/CoreOpenBSD.cpp @@ -75,7 +75,7 @@ namespace VeraCrypt args.push_back (filePath); - Process::Execute ("vnconfig", args); + Process::Execute ("/sbin/vnconfig", args); return "/dev/" + freePath.str() + "c"; } @@ -90,7 +90,7 @@ namespace VeraCrypt { try { - Process::Execute ("vnconfig", args); + Process::Execute ("/sbin/vnconfig", args); break; } catch (ExecutedProcessFailed&) diff --git a/src/Core/Unix/Solaris/CoreSolaris.cpp b/src/Core/Unix/Solaris/CoreSolaris.cpp index e840cceb..c436be8f 100644 --- a/src/Core/Unix/Solaris/CoreSolaris.cpp +++ b/src/Core/Unix/Solaris/CoreSolaris.cpp @@ -35,7 +35,7 @@ namespace VeraCrypt args.push_back ("-a"); args.push_back (filePath); - return StringConverter::Trim (Process::Execute ("lofiadm", args)); + return StringConverter::Trim (Process::Execute ("/usr/sbin/lofiadm", args)); } void CoreSolaris::DetachLoopDevice (const DevicePath &devicePath) const @@ -48,7 +48,7 @@ namespace VeraCrypt { try { - Process::Execute ("lofiadm", args); + Process::Execute ("/usr/sbin/lofiadm", args); break; } catch (ExecutedProcessFailed&) diff --git a/src/Main/UserInterface.cpp b/src/Main/UserInterface.cpp index 76d090e6..5798cb31 100644 --- a/src/Main/UserInterface.cpp +++ b/src/Main/UserInterface.cpp @@ -872,11 +872,30 @@ namespace VeraCrypt } #if !defined(TC_WINDOWS) && !defined(TC_MACOSX) -// Function to check if a given executable exists and is executable -static bool IsExecutable(const string& exe) { - return wxFileName::IsFileExecutable("/usr/bin/" + exe) || - wxFileName::IsFileExecutable("/usr/local/bin/" + exe); -} +// Define file manager structures with their required parameters +struct FileManager { + const char* name; + const char* const* baseArgs; + size_t baseArgsCount; +}; + +// Array of supported file managers with their parameters +static const char* const gioArgs[] = {"open"}; +static const char* const kioclient5Args[] = {"exec"}; +static const char* const kfmclientArgs[] = {"openURL"}; +static const char* const exoOpenArgs[] = {"--launch", "FileManager"}; + +const FileManager fileManagers[] = { + {"gio", gioArgs, 1}, + {"kioclient5", kioclient5Args, 1}, + {"kfmclient", kfmclientArgs, 1}, + {"exo-open", exoOpenArgs, 2}, + {"nautilus", NULL, 0}, + {"dolphin", NULL, 0}, + {"caja", NULL, 0}, + {"thunar", NULL, 0}, + {"pcmanfm", NULL, 0} +}; #endif void UserInterface::OpenExplorerWindow (const DirectoryPath &path) @@ -898,17 +917,21 @@ static bool IsExecutable(const string& exe) { args.push_back (string (path)); try { - Process::Execute ("open", args); + Process::Execute ("/usr/bin/open", args); } catch (exception &e) { ShowError (e); } #else string directoryPath = string(path); // Primary attempt: Use xdg-open - if (IsExecutable("xdg-open")) { - try { + string errorMsg; + string binPath = Process::FindSystemBinary("xdg-open", errorMsg); + if (!binPath.empty()) + { + try + { args.push_back(directoryPath); - Process::Execute("xdg-open", args, 2000); + Process::Execute(binPath, args, 2000); return; } catch (TimeOut&) { } @@ -916,36 +939,23 @@ static bool IsExecutable(const string& exe) { } // Fallback attempts: Try known file managers - const char* fallbackFileManagers[] = { "gio", "kioclient5", "kfmclient", "exo-open", "nautilus", "dolphin", "caja", "thunar", "pcmanfm" }; - const size_t numFileManagers = sizeof(fallbackFileManagers) / sizeof(fallbackFileManagers[0]); - + const size_t numFileManagers = sizeof(fileManagers) / sizeof(fileManagers[0]); for (size_t i = 0; i < numFileManagers; ++i) { - const char* fm = fallbackFileManagers[i]; - if (IsExecutable(fm)) { + const FileManager& fm = fileManagers[i]; + string fmPath = Process::FindSystemBinary(fm.name, errorMsg); + if (!fmPath.empty()) { args.clear(); - if (strcmp(fm, "gio") == 0) { - args.push_back("open"); - args.push_back(directoryPath); - } - else if (strcmp(fm, "kioclient5") == 0) { - args.push_back("exec"); - args.push_back(directoryPath); - } - else if (strcmp(fm, "kfmclient") == 0) { - args.push_back("openURL"); - args.push_back(directoryPath); - } - else if (strcmp(fm, "exo-open") == 0) { - args.push_back("--launch"); - args.push_back("FileManager"); - args.push_back(directoryPath); - } - else { - args.push_back(directoryPath); + + // Add base arguments first + for (size_t j = 0; j < fm.baseArgsCount; ++j) { + args.push_back(fm.baseArgs[j]); } + + // Add path argument + args.push_back(directoryPath); try { - Process::Execute(fm, args, 2000); + Process::Execute(fmPath, args, 2000); return; // Success } catch (TimeOut&) { } @@ -954,7 +964,7 @@ static bool IsExecutable(const string& exe) { } ShowWarning(wxT("Unable to find a file manager to open the mounted volume.\n" - "Please install xdg-utils or set a default file manager.")); + "Please install xdg-utils or set a default file manager.")); #endif } diff --git a/src/Platform/Unix/Process.cpp b/src/Platform/Unix/Process.cpp index 45106918..0c2a9c59 100644 --- a/src/Platform/Unix/Process.cpp +++ b/src/Platform/Unix/Process.cpp @@ -27,12 +27,73 @@ namespace VeraCrypt { - string Process::Execute (const string &processName, const list <string> &arguments, int timeOut, ProcessExecFunctor *execFunctor, const Buffer *inputData) + + bool Process::IsExecutable(const std::string& path) { + struct stat sb; + if (stat(path.c_str(), &sb) == 0) { + return S_ISREG(sb.st_mode) && (sb.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)); + } + return false; + } + + // Find executable in system paths + std::string Process::FindSystemBinary(const char* name, std::string& errorMsg) { + if (!name) { + errno = EINVAL; // Invalid argument + errorMsg = "Invalid input: name or paths is NULL"; + return ""; + } + + // Default system directories to search for executables +#ifdef TC_MACOSX + const char* defaultDirs[] = {"/usr/local/bin", "/usr/bin", "/bin", "/user/sbin", "/sbin"}; +#elseif TC_FREEBSD + const char* defaultDirs[] = {"/sbin", "/bin", "/usr/sbin", "/usr/bin", "/usr/local/sbin", "/usr/local/bin"}; +#elseif TC_OPENBSD + const char* defaultDirs[] = {"/sbin", "/bin", "/usr/sbin", "/usr/bin", "/usr/X11R6/bin", "/usr/local/sbin", "/usr/local/bin"}; +#else + const char* defaultDirs[] = {"/usr/local/sbin", "/usr/local/bin", "/usr/sbin", "/usr/bin", "/sbin", "/bin"}; +#endif + const size_t defaultDirCount = sizeof(defaultDirs) / sizeof(defaultDirs[0]); + + std::string currentPath(name); + + // If path doesn't start with '/', prepend default directories + if (currentPath[0] != '/') { + for (size_t i = 0; i < defaultDirCount; ++i) { + std::string combinedPath = std::string(defaultDirs[i]) + "/" + currentPath; + if (IsExecutable(combinedPath)) { + return combinedPath; + } + } + } else if (IsExecutable(currentPath)) { + return currentPath; + } + + // Prepare error message + errno = ENOENT; // No such file or directory + errorMsg = std::string(name) + " not found in system directories"; + return ""; + } + + string Process::Execute (const string &processNameArg, const list <string> &arguments, int timeOut, ProcessExecFunctor *execFunctor, const Buffer *inputData) { char *args[32]; if (array_capacity (args) <= (arguments.size() + 1)) throw ParameterTooLarge (SRC_POS); + // if execFunctor is null and processName is not absolute path, find it in system paths + string processName; + if (!execFunctor && (processNameArg[0] != '/')) + { + std::string errorMsg; + processName = FindSystemBinary(processNameArg.c_str(), errorMsg); + if (processName.empty()) + throw SystemException(SRC_POS, errorMsg); + } + else + processName = processNameArg; + #if 0 stringstream dbg; dbg << "exec " << processName; diff --git a/src/Platform/Unix/Process.h b/src/Platform/Unix/Process.h index a796ed6a..83215956 100644 --- a/src/Platform/Unix/Process.h +++ b/src/Platform/Unix/Process.h @@ -31,6 +31,8 @@ namespace VeraCrypt Process (); virtual ~Process (); + static bool IsExecutable(const std::string& path); + static std::string FindSystemBinary(const char* name, std::string& errorMsg); static string Execute (const string &processName, const list <string> &arguments, int timeOut = -1, ProcessExecFunctor *execFunctor = nullptr, const Buffer *inputData = nullptr); protected: |