From: Noah Hilverling Date: Tue, 22 Aug 2017 08:26:23 +0000 (+0200) Subject: Add process elevation & log message if user does not have enough privileges X-Git-Tag: v2.8.0~40^2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=refs%2Fpull%2F5602%2Fhead;p=icinga2 Add process elevation & log message if user does not have enough privileges refs #5515 --- diff --git a/icinga-app/icinga.cpp b/icinga-app/icinga.cpp index 2007e8c58..f5665c983 100644 --- a/icinga-app/icinga.cpp +++ b/icinga-app/icinga.cpp @@ -40,6 +40,11 @@ # include # include # include +#else +# include +# include +# include +# include #endif /* _WIN32 */ using namespace icinga; @@ -233,6 +238,74 @@ int Main(void) return EXIT_FAILURE; } +#ifdef _WIN32 + char username[UNLEN + 1]; + DWORD usernameLen = UNLEN + 1; + GetUserName(username, &usernameLen); + + std::ifstream userFile; + userFile.open(Application::GetSysconfDir() + "/icinga2/user"); + + if (userFile && command && !Application::IsProcessElevated()) { + std::string userLine; + if (std::getline(userFile, userLine)) { + userFile.close(); + + std::vector strs; + boost::split(strs, userLine, boost::is_any_of("\\")); + + if (username != strs[1] && command->GetImpersonationLevel() == ImpersonationLevel::ImpersonateIcinga + || command->GetImpersonationLevel() == ImpersonationLevel::ImpersonateRoot) { + TCHAR szPath[MAX_PATH]; + + if (GetModuleFileName(NULL, szPath, ARRAYSIZE(szPath))) { + SHELLEXECUTEINFO sei = { sizeof(sei) }; + sei.lpVerb = _T("runas"); + sei.lpFile = "cmd.exe"; + sei.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_NOASYNC | SEE_MASK_FLAG_NO_UI; + sei.nShow = SW_SHOW; + + std::stringstream parameters; + + parameters << "/C " << "\"" << szPath << "\"" << " "; + + for (int i = 1; i < argc; i++) { + if (i != 1) + parameters << " "; + parameters << argv[i]; + } + + parameters << " & SET exitcode=%errorlevel%"; + parameters << " & pause"; + parameters << " & EXIT /B %exitcode%"; + + std::string str = parameters.str(); + LPCSTR cstr = str.c_str(); + + sei.lpParameters = cstr; + + if (!ShellExecuteEx(&sei)) { + DWORD dwError = GetLastError(); + if (dwError == ERROR_CANCELLED) + Application::Exit(0); + } else { + WaitForSingleObject(sei.hProcess, INFINITE); + + DWORD exitCode; + GetExitCodeProcess(sei.hProcess, &exitCode); + + CloseHandle(sei.hProcess); + + Application::Exit(exitCode); + } + } + } + } else { + userFile.close(); + } + } +#endif /* _WIN32 */ + #ifndef _WIN32 if (vm.count("color")) { Console::SetType(std::cout, Console_VT100); diff --git a/lib/base/application.cpp b/lib/base/application.cpp index c1c2692c8..ce4982e2a 100644 --- a/lib/base/application.cpp +++ b/lib/base/application.cpp @@ -44,6 +44,10 @@ #include #endif /* __linux__ */ +#ifdef _WIN32 +#include +#endif /* _win32 */ + using namespace icinga; REGISTER_TYPE(Application); @@ -780,6 +784,40 @@ BOOL WINAPI Application::CtrlHandler(DWORD type) SetConsoleCtrlHandler(NULL, FALSE); return TRUE; } + +bool Application::IsProcessElevated(void) { + BOOL fIsElevated = FALSE; + DWORD dwError = ERROR_SUCCESS; + HANDLE hToken = NULL; + + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) + dwError = GetLastError(); + else { + TOKEN_ELEVATION elevation; + DWORD dwSize; + + if (!GetTokenInformation(hToken, TokenElevation, &elevation, sizeof(elevation), &dwSize)) + dwError = GetLastError(); + else + fIsElevated = elevation.TokenIsElevated; + } + + if (hToken) { + CloseHandle(hToken); + hToken = NULL; + } + + if (ERROR_SUCCESS != dwError) { + LPSTR mBuf = NULL; + if (!FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), mBuf, 0, NULL)) + BOOST_THROW_EXCEPTION(std::runtime_error("Failed to format error message, last error was: " + dwError)); + else + BOOST_THROW_EXCEPTION(std::runtime_error(mBuf)); + } + + return fIsElevated; +} #endif /* _WIN32 */ /** diff --git a/lib/base/application.hpp b/lib/base/application.hpp index 5c1469e12..bd04bbd02 100644 --- a/lib/base/application.hpp +++ b/lib/base/application.hpp @@ -126,6 +126,10 @@ public: static String GetRunAsGroup(void); static void DeclareRunAsGroup(const String& group); +#ifdef _WIN32 + static bool IsProcessElevated(void); +#endif /* _WIN32 */ + static int GetRLimitFiles(void); static int GetDefaultRLimitFiles(void); static void DeclareRLimitFiles(int limit); diff --git a/lib/cli/daemonutility.cpp b/lib/cli/daemonutility.cpp index e89b40a9a..c6748947e 100644 --- a/lib/cli/daemonutility.cpp +++ b/lib/cli/daemonutility.cpp @@ -106,11 +106,16 @@ bool DaemonUtility::ValidateConfigFiles(const std::vector& configs, if (!configs.empty()) { for (const String& configPath : configs) { - Expression *expression = ConfigCompiler::CompileFile(configPath, String(), "_etc"); - success = ExecuteExpression(expression); - delete expression; - if (!success) - return false; + try { + Expression *expression = ConfigCompiler::CompileFile(configPath, String(), "_etc"); + success = ExecuteExpression(expression); + delete expression; + if (!success) + return false; + } catch (const std::exception& ex) { + Log(LogCritical, "cli", "Could not compile config files: " + DiagnosticInformation(ex, false)); + Application::Exit(1); + } } } @@ -178,7 +183,13 @@ bool DaemonUtility::LoadConfigFiles(const std::vector& configs, } ConfigCompilerContext::GetInstance()->FinishObjectsFile(); - ScriptGlobal::WriteToFile(varsfile); + + try { + ScriptGlobal::WriteToFile(varsfile); + } catch (const std::exception& ex) { + Log(LogCritical, "cli", "Could not write vars file: " + DiagnosticInformation(ex, false)); + Application::Exit(1); + } return true; } diff --git a/lib/config/configcompilercontext.cpp b/lib/config/configcompilercontext.cpp index 251354126..fcb9c13d5 100644 --- a/lib/config/configcompilercontext.cpp +++ b/lib/config/configcompilercontext.cpp @@ -22,6 +22,7 @@ #include "base/json.hpp" #include "base/netstring.hpp" #include "base/exception.hpp" +#include "base/application.hpp" using namespace icinga; @@ -39,7 +40,12 @@ void ConfigCompilerContext::OpenObjectsFile(const String& filename) m_ObjectsPath = filename; std::fstream *fp = new std::fstream(); - m_ObjectsTempFile = Utility::CreateTempFile(filename + ".XXXXXX", 0600, *fp); + try { + m_ObjectsTempFile = Utility::CreateTempFile(filename + ".XXXXXX", 0600, *fp); + } catch (const std::exception& ex) { + Log(LogCritical, "cli", "Could not create temporary objects file: " + DiagnosticInformation(ex, false)); + Application::Exit(1); + } if (!*fp) BOOST_THROW_EXCEPTION(std::runtime_error("Could not open '" + m_ObjectsTempFile + "' file"));