diff options
author | Mounir IDRASSI <mounir.idrassi@idrix.fr> | 2024-12-25 11:29:32 +0100 |
---|---|---|
committer | Mounir IDRASSI <mounir.idrassi@idrix.fr> | 2024-12-25 11:29:32 +0100 |
commit | ca331b8b349cf1a42e6219d8733ae581199961fc (patch) | |
tree | b04dce61a60a793c5b519b5cbb9754bb7b4c6c4e /src/Core | |
parent | 341411e935621ee74e816cf83a149ce9cf1e6f9e (diff) | |
download | VeraCrypt-ca331b8b349cf1a42e6219d8733ae581199961fc.tar.gz VeraCrypt-ca331b8b349cf1a42e6219d8733ae581199961fc.zip |
Linux/macOS: Simplify sudo session detection logic and extend it to macOS
This update simplifies the logic for detecting active sudo sessions by checking the exit code of the sudo -n -l command, which reliably returns 0 if a session is active.
Additionally, this approach is now applicable to recent macOS versions, as they no longer have the sudo bug that previously prevented us from using this method.
Diffstat (limited to 'src/Core')
-rw-r--r-- | src/Core/CoreBase.h | 4 | ||||
-rw-r--r-- | src/Core/Unix/CoreService.cpp | 55 |
2 files changed, 23 insertions, 36 deletions
diff --git a/src/Core/CoreBase.h b/src/Core/CoreBase.h index e646fce3..7f830336 100644 --- a/src/Core/CoreBase.h +++ b/src/Core/CoreBase.h @@ -77,10 +77,8 @@ namespace VeraCrypt virtual void SetFileOwner (const FilesystemPath &path, const UserId &owner) const = 0; virtual DirectoryPath SlotNumberToMountPoint (VolumeSlotNumber slotNumber) const = 0; virtual void WipePasswordCache () const = 0; -#if defined(TC_LINUX ) || defined (TC_FREEBSD) virtual void ForceUseDummySudoPassword (bool useDummySudoPassword) { UseDummySudoPassword = useDummySudoPassword;} virtual bool GetUseDummySudoPassword () const { return UseDummySudoPassword;} -#endif Event VolumeDismountedEvent; Event VolumeMountedEvent; @@ -91,9 +89,7 @@ namespace VeraCrypt bool DeviceChangeInProgress; FilePath ApplicationExecutablePath; -#if defined(TC_LINUX ) || defined (TC_FREEBSD) bool UseDummySudoPassword; -#endif private: CoreBase (const CoreBase &); diff --git a/src/Core/Unix/CoreService.cpp b/src/Core/Unix/CoreService.cpp index 6d0f05e5..e4b75dd3 100644 --- a/src/Core/Unix/CoreService.cpp +++ b/src/Core/Unix/CoreService.cpp @@ -292,41 +292,33 @@ namespace VeraCrypt while (!ElevatedServiceAvailable) { // Test if the user has an active "sudo" session. - // This is only done under Linux / FreeBSD by executing the command 'sudo -n uptime'. - // In case a "sudo" session is active, the result of the command contains the string 'load average'. - // Otherwise, the result contains "sudo: a password is required". - // This may not work on all OSX versions because of a bug in sudo in its version 1.7.10, - // therefore we keep the old behaviour of sending a 'dummy' password under OSX. - // See : https://superuser.com/questions/902826/why-does-sudo-n-on-mac-os-x-always-return-0 - // - // If for some reason we are getting empty output from pipe, we revert to old behavior - // We also use the old way if the user is forcing the use of dummy password for sudo - -#if defined(TC_LINUX ) || defined (TC_FREEBSD) bool authCheckDone = false; if (!Core->GetUseDummySudoPassword ()) - { - std::vector<char> buffer(128, 0); - std::string result; - - FILE* pipe = popen("sudo -n uptime 2>&1 | grep 'load average' | wc -l | tr -d '[:blank:]'", "r"); // We redirect stderr to stdout (2>&1) to be able to catch the result of the command + { + // sudo man page: "If the -l option was specified without a command, sudo, will exit + // with a value of 0 if the user is allowed to run sudo, and they authenticated successfully" + // 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. if (pipe) { - while (!feof(pipe)) - { - if (fgets(buffer.data(), 128, pipe) != nullptr) - result += buffer.data(); - } - - fflush(pipe); - pclose(pipe); + // We only care about the exit code + char buf[128]; + while (!feof(pipe)) + { + if (fgets(buf, sizeof(buf), pipe) == NULL) + break; + } + int status = pclose(pipe); pipe = NULL; - if (!result.empty() && strlen(result.c_str()) != 0) - { - authCheckDone = true; - if (result[0] == '0') // no line found with "load average" text, rerquest admin password - (*AdminPasswordCallback) (request.AdminPassword); + authCheckDone = true; + + // If exit code != 0, user does NOT have an active session => request password + if (status != 0) + { + (*AdminPasswordCallback)(request.AdminPassword); } } @@ -336,7 +328,7 @@ namespace VeraCrypt request.FastElevation = false; } } -#endif + try { request.Serialize (ServiceInputStream); @@ -353,9 +345,8 @@ namespace VeraCrypt } request.FastElevation = false; -#if defined(TC_LINUX ) || defined (TC_FREEBSD) + if(!authCheckDone) -#endif (*AdminPasswordCallback) (request.AdminPassword); } } |