diff options
Diffstat (limited to 'src/Main/UserInterface.cpp')
-rw-r--r-- | src/Main/UserInterface.cpp | 201 |
1 files changed, 127 insertions, 74 deletions
diff --git a/src/Main/UserInterface.cpp b/src/Main/UserInterface.cpp index 8d046f87..b507d9a3 100644 --- a/src/Main/UserInterface.cpp +++ b/src/Main/UserInterface.cpp @@ -2,11 +2,11 @@ Derived from source code of TrueCrypt 7.1a, which is Copyright (c) 2008-2012 TrueCrypt Developers Association and which is governed by the TrueCrypt License 3.0. Modifications and additions to the original source code (contained in this file) - and all other portions of this file are Copyright (c) 2013-2017 IDRIX + and all other portions of this file are Copyright (c) 2013-2025 IDRIX and are governed by the Apache License 2.0 the full text of which is contained in the file License.txt included in VeraCrypt binary and source code distribution packages. */ @@ -30,10 +30,19 @@ #include "FavoriteVolume.h" #include "UserInterface.h" namespace VeraCrypt { + class AdminPasswordRequestHandler : public GetStringFunctor + { + public: + virtual void operator() (string &str) + { + throw ElevationFailed (SRC_POS, "sudo", 1, ""); + } + }; + UserInterface::UserInterface () { } UserInterface::~UserInterface () @@ -211,11 +220,11 @@ namespace VeraCrypt if (Preferences.Verbose) { if (!message.IsEmpty()) message += L'\n'; - message += StringFormatter (LangString["LINUX_VOL_DISMOUNTED"], wstring (volume->Path)); + message += StringFormatter (LangString["LINUX_VOL_UNMOUNTED"], wstring (volume->Path)); } } if (twoPassMode && firstPass) { @@ -388,11 +397,11 @@ namespace VeraCrypt errOutput += wxString (LangString["LINUX_CANT_GET_ADMIN_PRIV"]) + (StringConverter::Trim (execEx->GetErrorOutput()).empty() ? L". " : L": "); errOutput += StringConverter::ToWide (execEx->GetErrorOutput()); if (errOutput.empty()) - return errOutput + StringFormatter (LangString["LINUX_COMMAND_GET_ERROR"], execEx->GetCommand(), execEx->GetExitCode()); + return errOutput + static_cast<wstring>(StringFormatter (LangString["LINUX_COMMAND_GET_ERROR"], execEx->GetCommand(), execEx->GetExitCode())); return wxString (errOutput).Trim (true); } // PasswordIncorrect @@ -485,12 +494,12 @@ namespace VeraCrypt EX2MSG (PasswordIncorrect, LangString["PASSWORD_WRONG"]); EX2MSG (PasswordKeyfilesIncorrect, LangString["PASSWORD_OR_KEYFILE_WRONG"]); EX2MSG (PasswordOrKeyboardLayoutIncorrect, LangString["PASSWORD_OR_KEYFILE_WRONG"] + LangString["LINUX_EX2MSG_PASSWORDORKEYBOARDLAYOUTINCORRECT"]); EX2MSG (PasswordOrMountOptionsIncorrect, LangString["PASSWORD_OR_KEYFILE_OR_MODE_WRONG"] + LangString["LINUX_EX2MSG_PASSWORDORMOUNTOPTIONSINCORRECT"]); EX2MSG (PasswordTooLong, StringFormatter (LangString["LINUX_EX2MSG_PASSWORDTOOLONG"], (int) VolumePassword::MaxSize)); - EX2MSG (PasswordUTF8TooLong, LangString["PASSWORD_UTF8_TOO_LONG"]); - EX2MSG (PasswordLegacyUTF8TooLong, LangString["LEGACY_PASSWORD_UTF8_TOO_LONG"]); + EX2MSG (PasswordUTF8TooLong, StringFormatter (LangString["PASSWORD_UTF8_TOO_LONG"], (int) VolumePassword::MaxSize)); + EX2MSG (PasswordLegacyUTF8TooLong, StringFormatter (LangString["LEGACY_PASSWORD_UTF8_TOO_LONG"], (int) VolumePassword::MaxLegacySize)); EX2MSG (PasswordUTF8Invalid, LangString["PASSWORD_UTF8_INVALID"]); EX2MSG (PartitionDeviceRequired, LangString["LINUX_EX2MSG_PARTITIONDEVICEREQUIRED"]); EX2MSG (ProtectionPasswordIncorrect, LangString["LINUX_EX2MSG_PROTECTIONPASSWORDINCORRECT"]); EX2MSG (ProtectionPasswordKeyfilesIncorrect, LangString["LINUX_EX2MSG_PROTECTIONPASSWORDKEYFILESINCORRECT"]); EX2MSG (RootDeviceUnavailable, LangString["NODRIVER"]); @@ -508,13 +517,13 @@ namespace VeraCrypt EX2MSG (EMVUnknownCardType, LangString["EMV_UNKNOWN_CARD_TYPE"]); EX2MSG (EMVSelectAIDFailed, LangString["EMV_SELECT_AID_FAILED"]); EX2MSG (EMVIccCertNotFound, LangString["EMV_ICC_CERT_NOTFOUND"]); EX2MSG (EMVIssuerCertNotFound, LangString["EMV_ISSUER_CERT_NOTFOUND"]); EX2MSG (EMVCPLCNotFound, LangString["EMV_CPLC_NOTFOUND"]); - EX2MSG (InvalidEMVPath, LangString["EMV_PAN_NOTFOUND"]); - EX2MSG (EMVKeyfileDataNotFound, LangString["INVALID_EMV_PATH"]); - EX2MSG (EMVPANNotFound, LangString["EMV_KEYFILE_DATA_NOTFOUND"]); + EX2MSG (InvalidEMVPath, LangString["INVALID_EMV_PATH"]); + EX2MSG (EMVKeyfileDataNotFound, LangString["EMV_KEYFILE_DATA_NOTFOUND"]); + EX2MSG (EMVPANNotFound, LangString["EMV_PAN_NOTFOUND"]); #if defined (TC_LINUX) EX2MSG (TerminalNotFound, LangString["LINUX_EX2MSG_TERMINALNOTFOUND"]); EX2MSG (UnsupportedSectorSize, LangString["SECTOR_SIZE_UNSUPPORTED"]); EX2MSG (UnsupportedSectorSizeHiddenVolumeProtection, LangString["LINUX_EX2MSG_UNSUPPORTEDSECTORSIZEHIDDENVOLUMEPROTECTION"]); @@ -530,10 +539,13 @@ namespace VeraCrypt #ifdef TC_MACOSX EX2MSG (HigherFuseVersionRequired, LangString["LINUX_EX2MSG_HIGHERFUSEVERSIONREQUIRED"]); #endif + EX2MSG (MountPointBlocked, LangString["MOUNTPOINT_BLOCKED"]); + EX2MSG (MountPointNotAllowed, LangString["MOUNTPOINT_NOTALLOWED"]); + #undef EX2MSG return L""; } void UserInterface::Init () @@ -542,37 +554,35 @@ namespace VeraCrypt SetClassName (Application::GetName()); #ifdef CRYPTOPP_CPUID_AVAILABLE DetectX86Features (); #endif +#if CRYPTOPP_BOOL_ARMV8 + DetectArmFeatures(); +#endif LangString.Init(); Core->Init(); CmdLine.reset (new CommandLineInterface (argc, argv, InterfaceType)); SetPreferences (CmdLine->Preferences); Core->SetApplicationExecutablePath (Application::GetExecutablePath()); + Core->SetUserEnvPATH (getenv ("PATH")); if (!Preferences.NonInteractive) { Core->SetAdminPasswordCallback (GetAdminPasswordRequestHandler()); } else { - struct AdminPasswordRequestHandler : public GetStringFunctor - { - virtual void operator() (string &str) - { - throw ElevationFailed (SRC_POS, "sudo", 1, ""); - } - }; - Core->SetAdminPasswordCallback (shared_ptr <GetStringFunctor> (new AdminPasswordRequestHandler)); } -#if defined(TC_LINUX ) || defined (TC_FREEBSD) Core->ForceUseDummySudoPassword (CmdLine->ArgUseDummySudoPassword); + +#if defined(TC_UNIX) + Core->SetAllowInsecureMount (CmdLine->ArgAllowInsecureMount); #endif Core->WarningEvent.Connect (EventConnector <UserInterface> (this, &UserInterface::OnWarning)); Core->VolumeMountedEvent.Connect (EventConnector <UserInterface> (this, &UserInterface::OnVolumeMounted)); @@ -649,10 +659,11 @@ namespace VeraCrypt foreach_ref (const VolumeInfo &v, Core->GetMountedVolumes()) mountedVolumes.insert (v.Path); bool protectedVolumeMounted = false; bool legacyVolumeMounted = false; + bool vulnerableVolumeMounted = false; foreach_ref (const HostDevice &device, devices) { if (mountedVolumes.find (wstring (device.Path)) != mountedVolumes.end()) continue; @@ -691,10 +702,14 @@ namespace VeraCrypt if (newMountedVolumes.back()->Protection == VolumeProtection::HiddenVolumeReadOnly) protectedVolumeMounted = true; if (newMountedVolumes.back()->EncryptionAlgorithmMinBlockSize == 8) legacyVolumeMounted = true; + + if (newMountedVolumes.back()->MasterKeyVulnerable) + vulnerableVolumeMounted = true; + } catch (DriverError&) { } catch (MissingVolumeData&) { } catch (PasswordException&) { } catch (SystemException&) { } @@ -705,10 +720,13 @@ namespace VeraCrypt { ShowWarning (LangString [options.Keyfiles && !options.Keyfiles->empty() ? "PASSWORD_OR_KEYFILE_WRONG_AUTOMOUNT" : "PASSWORD_WRONG_AUTOMOUNT"]); } else { + if (vulnerableVolumeMounted) + ShowWarning ("ERR_XTS_MASTERKEY_VULNERABLE"); + if (someVolumesShared) ShowWarning ("DEVICE_IN_USE_INFO"); if (legacyVolumeMounted) ShowWarning ("WARN_64_BIT_BLOCK_CIPHER"); @@ -738,21 +756,24 @@ namespace VeraCrypt continue; } favorite.ToMountOptions (options); + bool mountPerformed = false; if (Preferences.NonInteractive) { BusyScope busy (this); newMountedVolumes.push_back (Core->MountVolume (options)); + mountPerformed = true; } else { try { BusyScope busy (this); newMountedVolumes.push_back (Core->MountVolume (options)); + mountPerformed = true; } catch (...) { UserPreferences prefs = GetPreferences(); if (prefs.CloseSecurityTokenSessionsAfterMount) @@ -766,10 +787,13 @@ namespace VeraCrypt if (!volume) break; newMountedVolumes.push_back (volume); } } + + if (mountPerformed && newMountedVolumes.back()->MasterKeyVulnerable) + ShowWarning ("ERR_XTS_MASTERKEY_VULNERABLE"); } if (!newMountedVolumes.empty() && GetPreferences().CloseSecurityTokenSessionsAfterMount) SecurityToken::CloseAllSessions(); @@ -802,10 +826,13 @@ namespace VeraCrypt { throw_err (LangString["FILE_IN_USE_FAILED"]); } } + if (volume->MasterKeyVulnerable) + ShowWarning ("ERR_XTS_MASTERKEY_VULNERABLE"); + if (volume->EncryptionAlgorithmMinBlockSize == 8) ShowWarning ("WARN_64_BIT_BLOCK_CIPHER"); if (VolumeHasUnrecommendedExtension (*options.Path)) ShowWarning ("EXE_FILE_EXTENSION_MOUNT_WARNING"); @@ -853,10 +880,37 @@ namespace VeraCrypt { ExceptionEventArgs &e = dynamic_cast <ExceptionEventArgs &> (args); ShowWarning (e.mException); } +#if !defined(TC_WINDOWS) && !defined(TC_MACOSX) +// 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) { if (path.IsEmpty()) return; @@ -872,69 +926,58 @@ namespace VeraCrypt #elif defined (TC_MACOSX) args.push_back (string (path)); try { - Process::Execute ("open", args); + Process::Execute ("/usr/bin/open", args); } catch (exception &e) { ShowError (e); } #else - // MIME handler for directory seems to be unavailable through wxWidgets - wxString desktop = GetTraits()->GetDesktopEnvironment(); - bool xdgOpenPresent = wxFileName::IsFileExecutable (wxT("/usr/bin/xdg-open")) || wxFileName::IsFileExecutable (wxT("/usr/local/bin/xdg-open")); - bool nautilusPresent = wxFileName::IsFileExecutable (wxT("/usr/bin/nautilus")) || wxFileName::IsFileExecutable (wxT("/usr/local/bin/nautilus")); - - if (desktop == L"GNOME" || (desktop.empty() && !xdgOpenPresent && nautilusPresent)) + string directoryPath = string(path); + // Primary attempt: Use xdg-open + string errorMsg; + string binPath = Process::FindSystemBinary("xdg-open", errorMsg); + if (!binPath.empty()) { - // args.push_back ("--no-default-window"); // This option causes nautilus not to launch under FreeBSD 11 - args.push_back ("--no-desktop"); - args.push_back (string (path)); try { - Process::Execute ("nautilus", args, 2000); + args.push_back(directoryPath); + Process::Execute(binPath, args, 2000); + return; } catch (TimeOut&) { } - catch (exception &e) { ShowError (e); } + catch (exception&) {} } - else if (desktop == L"KDE") - { - try - { - args.push_back (string (path)); - Process::Execute ("dolphin", args, 2000); - } - catch (TimeOut&) { } - catch (exception&) - { + + // Fallback attempts: Try known file managers + const size_t numFileManagers = sizeof(fileManagers) / sizeof(fileManagers[0]); + for (size_t i = 0; i < numFileManagers; ++i) { + const FileManager& fm = fileManagers[i]; + string fmPath = Process::FindSystemBinary(fm.name, errorMsg); + if (!fmPath.empty()) { args.clear(); - args.push_back ("openURL"); - args.push_back (string (path)); - try - { - Process::Execute ("kfmclient", args, 2000); + + // 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(fmPath, args, 2000); + return; // Success } catch (TimeOut&) { } - catch (exception &e) { ShowError (e); } - } - } - else if (xdgOpenPresent) - { - // Fallback on the standard xdg-open command - // which is not always available by default - args.push_back (string (path)); - try - { - Process::Execute ("xdg-open", args, 2000); + catch (exception &) {} } - catch (TimeOut&) { } - catch (exception &e) { ShowError (e); } - } - else - { - ShowWarning (wxT("Unable to find a file manager to open the mounted volume")); } + + ShowWarning(wxT("Unable to find a file manager to open the mounted volume.\n" + "Please install xdg-utils or set a default file manager.")); #endif } bool UserInterface::ProcessCommandLine () { @@ -1131,11 +1174,11 @@ namespace VeraCrypt " 1) Create an outer volume with no filesystem.\n" " 2) Create a hidden volume within the outer volume.\n" " 3) Mount the outer volume using hidden volume protection.\n" " 4) Create a filesystem on the virtual device of the outer volume.\n" " 5) Mount the new filesystem and fill it with data.\n" - " 6) Dismount the outer volume.\n" + " 6) Unmount the outer volume.\n" " If at any step the hidden volume protection is triggered, start again from 1).\n" "\n" "--create-keyfile[=FILE_PATH]\n" " Create a new keyfile containing pseudo-random data.\n" "\n" @@ -1143,13 +1186,13 @@ namespace VeraCrypt " Change a password and/or keyfile(s) of a volume. Most options are requested\n" " from the user if not specified on command line. PKCS-5 PRF HMAC hash\n" " algorithm can be changed with option --hash. See also options -k,\n" " --new-keyfiles, --new-password, -p, --random-source.\n" "\n" - "-d, --dismount[=MOUNTED_VOLUME]\n" - " Dismount a mounted volume. If MOUNTED_VOLUME is not specified, all\n" - " volumes are dismounted. See below for description of MOUNTED_VOLUME.\n" + "-u, --unmount[=MOUNTED_VOLUME]\n" + " Unmount a mounted volume. If MOUNTED_VOLUME is not specified, all\n" + " volumes are unmounted. See below for description of MOUNTED_VOLUME.\n" "\n" "--delete-token-keyfiles\n" " Delete keyfiles from security tokens. See also command --list-token-keyfiles.\n" "\n" "--export-token-keyfile\n" @@ -1216,11 +1259,11 @@ namespace VeraCrypt " with option -t. Default type is 'auto'. When creating a new volume, this\n" " option specifies the filesystem to be created on the new volume.\n" " Filesystem type 'none' disables mounting or creating a filesystem.\n" "\n" "--force\n" - " Force mounting of a volume in use, dismounting of a volume in use, or\n" + " Force mounting of a volume in use, unmounting of a volume in use, or\n" " overwriting a file. Note that this option has no effect on some platforms.\n" "\n" "--fs-options=OPTIONS\n" " Filesystem mount options. The OPTIONS argument is passed to mount(8)\n" " command with option -o when a filesystem on a VeraCrypt volume is mounted.\n" @@ -1252,11 +1295,11 @@ namespace VeraCrypt " headerbak: Use backup headers when mounting a volume.\n" " nokernelcrypto: Do not use kernel cryptographic services.\n" " readonly|ro: Mount volume as read-only.\n" " system: Mount partition using system encryption.\n" " timestamp|ts: Do not restore host-file modification timestamp when a volume\n" - " is dismounted (note that the operating system under certain circumstances\n" + " is unmounted (note that the operating system under certain circumstances\n" " does not alter host-file timestamps, which may be mistakenly interpreted\n" " to mean that this option does not work).\n" " See also option --fs-options.\n" "\n" "--new-keyfiles=KEYFILE1[,KEYFILE2,KEYFILE3,...]\n" @@ -1287,11 +1330,11 @@ namespace VeraCrypt " outer volume is mounted with all sectors belonging to the hidden volume\n" " protected against write operations. When a write to the protected area is\n" " prevented, the whole volume is switched to read-only mode. Verbose list\n" " (-v -l) can be used to query the state of the hidden volume protection.\n" " Warning message is displayed when a volume switched to read-only is being\n" - " dismounted.\n" + " unmounted.\n" "\n" "--protection-keyfiles=KEYFILE1[,KEYFILE2,KEYFILE3,...]\n" " Use specified keyfiles to open a hidden volume to be protected. This option\n" " may be used only when mounting an outer volume with hidden volume protected.\n" " See also options -k and --protect-hidden.\n" @@ -1308,11 +1351,11 @@ namespace VeraCrypt "--random-source=FILE\n" " Use FILE as a source of random data (e.g., when creating a volume) instead\n" " of requiring the user to type random characters.\n" "\n" "--slot=SLOT\n" - " Use specified slot number when mounting, dismounting, or listing a volume.\n" + " Use specified slot number when mounting, unmounting, or listing a volume.\n" "\n" "--size=SIZE[K|KiB|M|MiB|G|GiB|T|TiB] or --size=max\n" " Use specified size when creating a new volume. If no suffix is indicated,\n" " then SIZE is interpreted in bytes. Suffixes K, M, G or T can be used to\n" " indicate a value in KiB, MiB, GiB or TiB respectively.\n" @@ -1353,15 +1396,15 @@ namespace VeraCrypt "veracrypt --filesystem=none volume.hc\n" "\n" "Mount a volume prompting only for its password:\n" "veracrypt -t -k \"\" --pim=0 --protect-hidden=no volume.hc /media/veracrypt1\n" "\n" - "Dismount a volume:\n" - "veracrypt -d volume.hc\n" + "Unmount a volume:\n" + "veracrypt -u volume.hc\n" "\n" - "Dismount all mounted volumes:\n" - "veracrypt -d\n" + "Unmount all mounted volumes:\n" + "veracrypt -u\n" ); #ifndef TC_NO_GUI if (Application::GetUserInterfaceType() == UserInterfaceType::Graphic) { @@ -1514,11 +1557,11 @@ namespace VeraCrypt throw TestFailed (SRC_POS); EncryptionTest::TestAll(); // StringFormatter - if (StringFormatter (L"{9} {8} {7} {6} {5} {4} {3} {2} {1} {0} {{0}}", "1", L"2", '3', L'4', 5, 6, 7, 8, 9, 10) != L"10 9 8 7 6 5 4 3 2 1 {0}") + if (static_cast<wstring>(StringFormatter (L"{9} {8} {7} {6} {5} {4} {3} {2} {1} {0} {{0}}", "1", L"2", '3', L'4', 5, 6, 7, 8, 9, 10)) != L"10 9 8 7 6 5 4 3 2 1 {0}") throw TestFailed (SRC_POS); try { StringFormatter (L"{0} {1}", 1); throw TestFailed (SRC_POS); @@ -1612,10 +1655,17 @@ namespace VeraCrypt } return sResult; } +#ifdef TC_UNIX + bool UserInterface::InsecureMountAllowed () const + { + return CmdLine->ArgAllowInsecureMount; + } +#endif + #define VC_CONVERT_EXCEPTION(NAME) if (dynamic_cast<NAME*> (ex)) throw (NAME&) *ex; void UserInterface::ThrowException (Exception* ex) { VC_CONVERT_EXCEPTION (PasswordIncorrect); @@ -1700,8 +1750,11 @@ namespace VeraCrypt VC_CONVERT_EXCEPTION (EMVCPLCNotFound); VC_CONVERT_EXCEPTION (InvalidEMVPath); VC_CONVERT_EXCEPTION (EMVKeyfileDataNotFound); VC_CONVERT_EXCEPTION (EMVPANNotFound); + VC_CONVERT_EXCEPTION (MountPointBlocked); + VC_CONVERT_EXCEPTION (MountPointNotAllowed); + throw *ex; } } |