From 80cc18f6678e96dd3dfe8abc6f444069ec39c982 Mon Sep 17 00:00:00 2001 From: Mounir IDRASSI Date: Sun, 3 Nov 2019 15:35:53 +0100 Subject: Linux/FreeBSD: Fix regression causing admin password to be requested too many times in some cases --- src/Core/Unix/CoreService.cpp | 72 ++++++++++++++++++++++++------------------- 1 file changed, 40 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/src/Core/Unix/CoreService.cpp b/src/Core/Unix/CoreService.cpp index 5eca15de..b02bd211 100644 --- a/src/Core/Unix/CoreService.cpp +++ b/src/Core/Unix/CoreService.cpp @@ -289,43 +289,51 @@ namespace VeraCrypt request.FastElevation = !ElevatedServiceAvailable; request.ApplicationExecutablePath = Core->GetApplicationExecutablePath(); - // 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 defined(TC_LINUX ) || defined (TC_FREEBSD) - - // Set to false to force the 'WarningEvent' to be raised in case of and elevation exception. - request.FastElevation = false; - - std::vector buffer(128, 0); - std::string result; - - FILE* pipe = popen("sudo -n uptime 2>&1 | grep 'load average' | wc -l", "r"); // We redirect stderr to stdout (2>&1) to be able to catch the result of the command - if (pipe) + while (!ElevatedServiceAvailable) { - while (!feof(pipe)) + // 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 + +#if defined(TC_LINUX ) || defined (TC_FREEBSD) + + std::vector buffer(128, 0); + std::string result; + bool authCheckDone = false; + + FILE* pipe = popen("sudo -n uptime 2>&1 | grep 'load average' | wc -l", "r"); // We redirect stderr to stdout (2>&1) to be able to catch the result of the command + if (pipe) { - if (fgets(buffer.data(), 128, pipe) != nullptr) - result += buffer.data(); + while (!feof(pipe)) + { + if (fgets(buffer.data(), 128, pipe) != nullptr) + result += buffer.data(); + } + + fflush(pipe); + 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); + } } - fflush(pipe); - pclose(pipe); - pipe = NULL; - - if (!result.empty() && strlen(result.c_str()) != 0 && !memcmp(result.c_str(), "0", 1)) + if (authCheckDone) { - (*AdminPasswordCallback) (request.AdminPassword); + // Set to false to force the 'WarningEvent' to be raised in case of and elevation exception. + request.FastElevation = false; } - } -#endif - while (!ElevatedServiceAvailable) - { +#endif try { request.Serialize (ServiceInputStream); @@ -432,7 +440,7 @@ namespace VeraCrypt vector adminPassword (request.AdminPassword.size() + 1); int timeout = 6000; - // 'request.FastElevation' is always false under Linux / FreeBSD + // 'request.FastElevation' is always false under Linux / FreeBSD when "sudo -n" works properly if (request.FastElevation) { string dummyPassword = "dummy\n"; -- cgit v1.2.3