diff options
author | Egor Tensin <Egor.Tensin@gmail.com> | 2016-10-14 00:00:22 +0300 |
---|---|---|
committer | Egor Tensin <Egor.Tensin@gmail.com> | 2016-10-14 00:00:22 +0300 |
commit | 69905917cf2c46fa0093df7323e5326450d1246b (patch) | |
tree | 2ec12ee6f588f7bcefab713c976ed64aa1e729ec | |
parent | rename the project (diff) | |
download | privilege-check-69905917cf2c46fa0093df7323e5326450d1246b.tar.gz privilege-check-69905917cf2c46fa0093df7323e5326450d1246b.zip |
move code from headers to .cpp files
-rw-r--r-- | src/error.cpp | 37 | ||||
-rw-r--r-- | src/error.hpp | 23 | ||||
-rw-r--r-- | src/handle.hpp | 2 | ||||
-rw-r--r-- | src/main.cpp | 5 | ||||
-rw-r--r-- | src/os.cpp | 24 | ||||
-rw-r--r-- | src/os.hpp | 16 | ||||
-rw-r--r-- | src/process.cpp | 64 | ||||
-rw-r--r-- | src/process.hpp | 47 | ||||
-rw-r--r-- | src/resource.cpp | 37 | ||||
-rw-r--r-- | src/resource.hpp | 25 | ||||
-rw-r--r-- | src/sid.cpp | 73 | ||||
-rw-r--r-- | src/sid.hpp | 56 | ||||
-rw-r--r-- | src/string.hpp | 14 | ||||
-rw-r--r-- | src/token.cpp | 167 | ||||
-rw-r--r-- | src/token.hpp | 152 |
15 files changed, 442 insertions, 300 deletions
diff --git a/src/error.cpp b/src/error.cpp new file mode 100644 index 0000000..e0b4648 --- /dev/null +++ b/src/error.cpp @@ -0,0 +1,37 @@ +// Copyright (c) 2016 Egor Tensin <Egor.Tensin@gmail.com> +// This file is part of the "Privilege check" project. +// For details, see https://github.com/egor-tensin/privilege-check. +// Distributed under the MIT License. + +#pragma once + +#include "error.hpp" + +#include <Windows.h> + +#include <exception> +#include <system_error> + +namespace error +{ + Error make(const char* function_name) + { + const auto ec = GetLastError(); + return {static_cast<int>(ec), std::system_category(), function_name}; + } + + void raise(const char* function_name) + { + throw make(function_name); + } + + void report(const std::exception& e) + { + MessageBoxA(NULL, e.what(), NULL, MB_OK); + } + + int get_code(const Error& e) + { + return e.code().value(); + } +} diff --git a/src/error.hpp b/src/error.hpp index 0eeb147..b8ba468 100644 --- a/src/error.hpp +++ b/src/error.hpp @@ -5,8 +5,6 @@ #pragma once -#include <Windows.h> - #include <exception> #include <system_error> @@ -14,24 +12,11 @@ typedef std::system_error Error; namespace error { - Error make(const char* function_name) - { - const auto ec = GetLastError(); - return {static_cast<int>(ec), std::system_category(), function_name}; - } + Error make(const char* function_name); - inline void raise(const char* function_name) - { - throw make(function_name); - } + void raise(const char* function_name); - void report(const std::exception& e) - { - MessageBoxA(NULL, e.what(), NULL, MB_OK); - } + void report(const std::exception&); - int get_code(const Error& e) - { - return e.code().value(); - } + int get_code(const Error&); } diff --git a/src/handle.hpp b/src/handle.hpp index 80b6a06..62670de 100644 --- a/src/handle.hpp +++ b/src/handle.hpp @@ -62,7 +62,7 @@ private: namespace std { - void swap(Handle& a, Handle& b) noexcept + inline void swap(Handle& a, Handle& b) noexcept { a.swap(b); } diff --git a/src/main.cpp b/src/main.cpp index 5e59ff0..d13325c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -20,6 +20,9 @@ #pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") +namespace +{ + HWND get_dialog_item(HWND wnd, int id) { const auto lbl = GetDlgItem(wnd, id); @@ -218,6 +221,8 @@ INT_PTR CALLBACK dialog_main( } } +} + int APIENTRY wWinMain( HINSTANCE instance, HINSTANCE, diff --git a/src/os.cpp b/src/os.cpp new file mode 100644 index 0000000..13fd766 --- /dev/null +++ b/src/os.cpp @@ -0,0 +1,24 @@ +// Copyright (c) 2016 Egor Tensin <Egor.Tensin@gmail.com> +// This file is part of the "Privilege check" project. +// For details, see https://github.com/egor-tensin/privilege-check. +// Distributed under the MIT License. + +#include "error.hpp" +#include "os.hpp" + +#include <Windows.h> + +namespace os +{ + OSVERSIONINFOW get_version_info() + { + OSVERSIONINFOW info; + ZeroMemory(&info, sizeof(info)); + info.dwOSVersionInfoSize = sizeof(info); + + if (!GetVersionExW(&info)) + error::raise("GetVersionExW"); + + return info; + } +} @@ -11,24 +11,14 @@ namespace os { - OSVERSIONINFOW get_version_info() - { - OSVERSIONINFOW info; - ZeroMemory(&info, sizeof(info)); - info.dwOSVersionInfoSize = sizeof(info); - - if (!GetVersionExW(&info)) - error::raise("GetVersionExW"); - - return info; - } + OSVERSIONINFOW get_version_info(); - bool is_vista_or_later(const OSVERSIONINFOW& info) + inline bool is_vista_or_later(const OSVERSIONINFOW& info) { return info.dwMajorVersion >= 6; } - bool is_vista_or_later() + inline bool is_vista_or_later() { return is_vista_or_later(get_version_info()); } diff --git a/src/process.cpp b/src/process.cpp new file mode 100644 index 0000000..94765bc --- /dev/null +++ b/src/process.cpp @@ -0,0 +1,64 @@ +// Copyright (c) 2016 Egor Tensin <Egor.Tensin@gmail.com> +// This file is part of the "Privilege check" project. +// For details, see https://github.com/egor-tensin/privilege-check. +// Distributed under the MIT License. + +#include "cmd_line.hpp" +#include "error.hpp" +#include "process.hpp" + +#include <Windows.h> +#include <shellapi.h> + +#include <array> +#include <string> + +namespace process +{ + std::wstring get_executable_path() + { + static constexpr DWORD max_path = MAX_PATH; + + std::array<wchar_t, max_path> buf; + + const auto ret = GetModuleFileNameW(NULL, buf.data(), max_path); + + if (GetLastError() != ERROR_SUCCESS) + error::raise("GetModuleFileNameW"); + + return buf.data(); + } + + void runas( + const CommandLine& cmd_line, + HWND hwnd, + int nShow) + { + static constexpr auto sep = L' '; + + const auto exe_path = cmd_line.has_argv0() + ? cmd_line.get_argv0() + : get_executable_path(); + + SHELLEXECUTEINFOW info; + ZeroMemory(&info, sizeof(info)); + info.cbSize = sizeof(info); + info.lpVerb = L"runas"; + info.lpFile = exe_path.c_str(); + const auto args = cmd_line.join_args(); + if (!args.empty()) + info.lpParameters = args.c_str(); + info.hwnd = hwnd; + info.nShow = nShow; + + if (!ShellExecuteExW(&info)) + error::raise("ShellExecuteExW"); + } + + void runas_self( + HWND hwnd, + int nShow) + { + runas(CommandLine::query(), hwnd, nShow); + } +} diff --git a/src/process.hpp b/src/process.hpp index 6439d38..c422aac 100644 --- a/src/process.hpp +++ b/src/process.hpp @@ -6,31 +6,16 @@ #pragma once #include "cmd_line.hpp" -#include "error.hpp" #include <Windows.h> -#include <shellapi.h> -#include <array> #include <string> namespace process { - std::wstring get_executable_path() - { - static constexpr DWORD max_path = MAX_PATH; - - std::array<wchar_t, max_path> buf; - - const auto ret = GetModuleFileNameW(NULL, buf.data(), max_path); - - if (GetLastError() != ERROR_SUCCESS) - error::raise("GetModuleFileNameW"); + std::wstring get_executable_path(); - return buf.data(); - } - - std::wstring get_command_line() + inline std::wstring get_command_line() { return GetCommandLine(); } @@ -38,33 +23,9 @@ namespace process void runas( const CommandLine& cmd_line, HWND hwnd = NULL, - int nShow = SW_NORMAL) - { - static constexpr auto sep = L' '; - - const auto exe_path = cmd_line.has_argv0() - ? cmd_line.get_argv0() - : get_executable_path(); - - SHELLEXECUTEINFOW info; - ZeroMemory(&info, sizeof(info)); - info.cbSize = sizeof(info); - info.lpVerb = L"runas"; - info.lpFile = exe_path.c_str(); - const auto args = cmd_line.join_args(); - if (!args.empty()) - info.lpParameters = args.c_str(); - info.hwnd = hwnd; - info.nShow = nShow; - - if (!ShellExecuteExW(&info)) - error::raise("ShellExecuteExW"); - } + int nShow = SW_NORMAL); void runas_self( HWND hwnd = NULL, - int nShow = SW_NORMAL) - { - runas(CommandLine::query(), hwnd, nShow); - } + int nShow = SW_NORMAL); } diff --git a/src/resource.cpp b/src/resource.cpp new file mode 100644 index 0000000..e8ac300 --- /dev/null +++ b/src/resource.cpp @@ -0,0 +1,37 @@ +// Copyright (c) 2016 Egor Tensin <Egor.Tensin@gmail.com> +// This file is part of the "Privilege check" project. +// For details, see https://github.com/egor-tensin/privilege-check. +// Distributed under the MIT License. + +#include "error.hpp" +#include "resource.hpp" + +#include <Windows.h> + +#include <cstddef> + +#include <string> + +namespace resource +{ + HMODULE load_exe_module() + { + const auto module = GetModuleHandle(NULL); + if (module == NULL) + error::raise("GetModuleHandle"); + return module; + } + + std::wstring load_string(unsigned int id) + { + wchar_t* s = nullptr; + + const auto ret = LoadStringW( + load_exe_module(), id, reinterpret_cast<wchar_t*>(&s), 0); + + if (ret <= 0) + error::raise("LoadStringW"); + + return {s, static_cast<std::size_t>(ret)}; + } +} diff --git a/src/resource.hpp b/src/resource.hpp index 24fc2db..0e3186c 100644 --- a/src/resource.hpp +++ b/src/resource.hpp @@ -5,32 +5,13 @@ #pragma once -#include "error.hpp" - -#include <cstddef> +#include <Windows.h> #include <string> namespace resource { - HMODULE load_exe_module() - { - const auto module = GetModuleHandle(NULL); - if (module == NULL) - error::raise("GetModuleHandle"); - return module; - } - - std::wstring load_string(unsigned int id) - { - wchar_t* s = nullptr; - - const auto ret = LoadStringW( - load_exe_module(), id, reinterpret_cast<wchar_t*>(&s), 0); - - if (ret <= 0) - error::raise("LoadStringW"); + HMODULE load_exe_module(); - return {s, static_cast<std::size_t>(ret)}; - } + std::wstring load_string(unsigned int id); } diff --git a/src/sid.cpp b/src/sid.cpp new file mode 100644 index 0000000..4a86704 --- /dev/null +++ b/src/sid.cpp @@ -0,0 +1,73 @@ +// Copyright (c) 2016 Egor Tensin <Egor.Tensin@gmail.com> +// This file is part of the "Privilege check" project. +// For details, see https://github.com/egor-tensin/privilege-check. +// Distributed under the MIT License. + +#pragma once + +#include "error.hpp" +#include "sid.hpp" + +#include <Windows.h> +#include <sddl.h> + +#include <memory> +#include <string> + +namespace sid +{ + SidBuffer well_known(WELL_KNOWN_SID_TYPE type) + { + SidBuffer buffer; + DWORD cb = static_cast<DWORD>(buffer.size()); + + if (!CreateWellKnownSid(type, NULL, buffer.data(), &cb)) + error::raise("CreateWellKnownSid"); + + return buffer; + } + + SidBuffer builtin_administrators() + { + /* + void* sid = nullptr; + SID_IDENTIFIER_AUTHORITY authority = SECURITY_NT_AUTHORITY; + + if (!AllocateAndInitializeSid( + &authority, + 2, + SECURITY_BUILTIN_DOMAIN_RID, + DOMAIN_ALIAS_RID_ADMINS, + 0, 0, 0, 0, 0, 0, + &sid)) + { + error::raise("AllocateAndInitializeSid"); + } + + return std::unique_ptr<void, FreeSid>{sid}; + */ + + return well_known(WinBuiltinAdministratorsSid); + } + + namespace + { + struct LocalDelete + { + void operator()(wchar_t* s) const + { + LocalFree(s); + } + }; + } + + std::wstring to_string(const SidBuffer& sid) + { + wchar_t* s = nullptr; + + if (!ConvertSidToStringSidW(const_cast<unsigned char*>(sid.data()), &s)) + error::raise("ConvertSidToStringSidW"); + + return std::unique_ptr<wchar_t, LocalDelete>{s}.get(); + } +} diff --git a/src/sid.hpp b/src/sid.hpp index cf905a4..c84b725 100644 --- a/src/sid.hpp +++ b/src/sid.hpp @@ -5,69 +5,21 @@ #pragma once -#include "error.hpp" - #include <Windows.h> #include <sddl.h> #include <array> -#include <memory> #include <string> constexpr DWORD max_sid_size = SECURITY_MAX_SID_SIZE; + typedef std::array<unsigned char, max_sid_size> SidBuffer; namespace sid { - SidBuffer well_known(WELL_KNOWN_SID_TYPE type) - { - SidBuffer buffer; - DWORD cb = static_cast<DWORD>(buffer.size()); - - if (!CreateWellKnownSid(type, NULL, buffer.data(), &cb)) - error::raise("CreateWellKnownSid"); - - return buffer; - } - - SidBuffer builtin_administrators() - { - /* - void* sid = nullptr; - SID_IDENTIFIER_AUTHORITY authority = SECURITY_NT_AUTHORITY; - - if (!AllocateAndInitializeSid( - &authority, - 2, - SECURITY_BUILTIN_DOMAIN_RID, - DOMAIN_ALIAS_RID_ADMINS, - 0, 0, 0, 0, 0, 0, - &sid)) - { - error::raise("AllocateAndInitializeSid"); - } - - return std::unique_ptr<void, FreeSid>{sid}; - */ - - return well_known(WinBuiltinAdministratorsSid); - } - - struct DeleteSidString - { - void operator()(wchar_t* s) const - { - LocalFree(s); - } - }; - - std::wstring to_string(const SidBuffer& sid) - { - wchar_t* s = nullptr; + SidBuffer well_known(WELL_KNOWN_SID_TYPE type); - if (!ConvertSidToStringSidW(const_cast<unsigned char*>(sid.data()), &s)) - error::raise("ConvertSidToStringSidW"); + SidBuffer builtin_administrators(); - return std::unique_ptr<wchar_t, DeleteSidString>{s}.get(); - } + std::wstring to_string(const SidBuffer&); } diff --git a/src/string.hpp b/src/string.hpp index 3841b8c..52ed518 100644 --- a/src/string.hpp +++ b/src/string.hpp @@ -18,7 +18,7 @@ namespace string { template <typename Char> - inline void ltrim(std::basic_string<Char>& s) + void ltrim(std::basic_string<Char>& s) { s.erase(s.begin(), std::find_if(s.begin(), s.end(), [] (const Char& c) { @@ -27,7 +27,7 @@ namespace string } template <typename Char> - inline void rtrim(std::basic_string<Char>& s) + void rtrim(std::basic_string<Char>& s) { s.erase(std::find_if(s.rbegin(), s.rend(), [] (const Char& c) { @@ -36,14 +36,14 @@ namespace string } template <typename Char> - inline void trim(std::basic_string<Char>& s) + void trim(std::basic_string<Char>& s) { ltrim(s); rtrim(s); } template <typename Char, typename Sep, typename InputIterator> - inline std::basic_string<Char> join( + std::basic_string<Char> join( const Sep& sep, InputIterator beg, InputIterator end) @@ -63,7 +63,7 @@ namespace string } template <typename Char, typename Sep> - inline std::basic_string<Char> join( + std::basic_string<Char> join( const Sep& sep, const std::vector<std::basic_string<Char>>& args) { @@ -112,7 +112,7 @@ namespace string }; template <typename Char, typename What, typename By> - inline void replace( + void replace( std::basic_string<Char>& s, const What& what, const By& by) @@ -136,7 +136,7 @@ namespace string } template <typename Char, typename What> - inline void prefix_with( + void prefix_with( std::basic_string<Char>& s, const What& what, const Char& by) diff --git a/src/token.cpp b/src/token.cpp new file mode 100644 index 0000000..ca08e03 --- /dev/null +++ b/src/token.cpp @@ -0,0 +1,167 @@ +// Copyright (c) 2016 Egor Tensin <Egor.Tensin@gmail.com> +// This file is part of the "Privilege check" project. +// For details, see https://github.com/egor-tensin/privilege-check. +// Distributed under the MIT License. + +#include "error.hpp" +#include "handle.hpp" +#include "os.hpp" +#include "sid.hpp" + +#include <Windows.h> + +#include <string> +#include <unordered_map> +#include <utility> +#include <vector> + +namespace token +{ + Handle open_for_process( + const Handle& process, + DWORD permissions) + { + HANDLE raw; + + if (!OpenProcessToken(process, permissions, &raw)) + error::raise("OpenProcessToken"); + + return Handle{raw}; + } + + Handle open_for_current_process( + DWORD permissions) + { + return open_for_process(Handle{GetCurrentProcess()}, permissions); + } + + bool get_linked(Handle& token) + { + if (!os::is_vista_or_later()) + return false; + + auto type = TokenElevationTypeDefault; + DWORD cb = 0; + + if (!GetTokenInformation(token, TokenElevationType, &type, sizeof(type), &cb)) + error::raise("GetTokenInformation"); + + if (type != TokenElevationTypeLimited) + return false; + + HANDLE raw; + + if (!GetTokenInformation(token, TokenLinkedToken, &raw, sizeof(raw), &cb)) + error::raise("GetTokenInformation"); + + token = Handle{raw}; + return true; + } + + Handle get_for_identification(const Handle& token) + { + HANDLE raw; + + if (!DuplicateToken(token, SecurityIdentification, &raw)) + error::raise("DuplicateToken"); + + return Handle{raw}; + } + + // + // FUNCTION: query_integrity_level() + // + // RETURN VALUE: Returns the integrity level of the current process. It is + // usually one of these values: + // + // SECURITY_MANDATORY_UNTRUSTED_RID (SID: S-1-16-0x0) + // Means untrusted level. It is used by processes started by the + // Anonymous group. Blocks most write access. + // + // SECURITY_MANDATORY_LOW_RID (SID: S-1-16-0x1000) + // Means low integrity level. It is used by Protected Mode Internet + // Explorer. Blocks write acess to most objects (such as files and + // registry keys) on the system. + // + // SECURITY_MANDATORY_MEDIUM_RID (SID: S-1-16-0x2000) + // Means medium integrity level. It is used by normal applications + // being launched while UAC is enabled. + // + // SECURITY_MANDATORY_HIGH_RID (SID: S-1-16-0x3000) + // Means high integrity level. It is used by administrative applications + // launched through elevation when UAC is enabled, or normal + // applications if UAC is disabled and the user is an administrator. + // + // SECURITY_MANDATORY_SYSTEM_RID (SID: S-1-16-0x4000) + // Means system integrity level. It is used by services and other + // system-level applications (such as Wininit, Winlogon, Smss, etc.) + // + DWORD query_integrity_level(const Handle& token) + { + DWORD cb = 0; + + if (!GetTokenInformation(token, TokenIntegrityLevel, NULL, 0, &cb)) + { + switch (GetLastError()) + { + case ERROR_INSUFFICIENT_BUFFER: + break; + default: + error::raise("GetTokenInformation"); + } + } + + std::vector<unsigned char> buf(cb); + const auto token_level = reinterpret_cast<TOKEN_MANDATORY_LABEL*>(buf.data()); + + if (!GetTokenInformation(token, TokenIntegrityLevel, token_level, cb, &cb)) + error::raise("GetTokenInformation"); + + // Integrity Level SIDs are in the form of S-1-16-0xXXXX. (e.g. + // S-1-16-0x1000 stands for low integrity level SID). There is one and + // only one subauthority. + return *GetSidSubAuthority(token_level->Label.Sid, 0); + } + + std::wstring integrity_level_to_string(DWORD level) + { + static const std::unordered_map<DWORD, const wchar_t*> names = + { + {SECURITY_MANDATORY_UNTRUSTED_RID, L"Untrusted"}, + {SECURITY_MANDATORY_LOW_RID, L"Low"}, + {SECURITY_MANDATORY_MEDIUM_RID, L"Medium"}, + {SECURITY_MANDATORY_HIGH_RID, L"High"}, + {SECURITY_MANDATORY_SYSTEM_RID, L"System"}, + }; + + static constexpr auto unknown_name = L"Unknown"; + + const auto it = names.find(level); + + if (it == names.cend()) + return unknown_name; + + return it->second; + } + + bool check_belongs(const Handle& token, const SidBuffer& sid) + { + BOOL b = FALSE; + + if (!CheckTokenMembership(token, const_cast<unsigned char*>(sid.data()), &b)) + error::raise("CheckTokenMembership"); + + return b != FALSE; + } + + bool query_elevation(const Handle& token) + { + TOKEN_ELEVATION elevation; + DWORD cb = 0; + + if (!GetTokenInformation(token, TokenElevation, &elevation, sizeof(elevation), &cb)) + error::raise("GetTokenInformation"); + + return elevation.TokenIsElevated != 0; + } +} diff --git a/src/token.hpp b/src/token.hpp index 042cd2b..509a15c 100644 --- a/src/token.hpp +++ b/src/token.hpp @@ -5,17 +5,12 @@ #pragma once -#include "error.hpp" #include "handle.hpp" -#include "os.hpp" #include "sid.hpp" #include <Windows.h> #include <string> -#include <unordered_map> -#include <utility> -#include <vector> namespace token { @@ -29,153 +24,24 @@ namespace token constexpr DWORD default_permissions = permissions::query(); // Current thread's primary impersonation token. - Handle dumb() { return Handle{NULL}; } + inline Handle dumb() { return Handle{NULL}; } Handle open_for_process( const Handle& process, - DWORD permissions = default_permissions) - { - HANDLE raw; - - if (!OpenProcessToken(process, permissions, &raw)) - error::raise("OpenProcessToken"); - - return Handle{raw}; - } + DWORD permissions = default_permissions); Handle open_for_current_process( - DWORD permissions = default_permissions) - { - return open_for_process(Handle{GetCurrentProcess()}, permissions); - } - - bool get_linked(Handle& token) - { - if (!os::is_vista_or_later()) - return false; - - auto type = TokenElevationTypeDefault; - DWORD cb = 0; - - if (!GetTokenInformation(token, TokenElevationType, &type, sizeof(type), &cb)) - error::raise("GetTokenInformation"); - - if (type != TokenElevationTypeLimited) - return false; - - HANDLE raw; - - if (!GetTokenInformation(token, TokenLinkedToken, &raw, sizeof(raw), &cb)) - error::raise("GetTokenInformation"); - - token = Handle{raw}; - return true; - } - - Handle get_for_identification(const Handle& token) - { - HANDLE raw; + DWORD permissions = default_permissions); - if (!DuplicateToken(token, SecurityIdentification, &raw)) - error::raise("DuplicateToken"); + bool get_linked(Handle& token); - return Handle{raw}; - } + Handle get_for_identification(const Handle& token); - // - // FUNCTION: query_integrity_level() - // - // RETURN VALUE: Returns the integrity level of the current process. It is - // usually one of these values: - // - // SECURITY_MANDATORY_UNTRUSTED_RID (SID: S-1-16-0x0) - // Means untrusted level. It is used by processes started by the - // Anonymous group. Blocks most write access. - // - // SECURITY_MANDATORY_LOW_RID (SID: S-1-16-0x1000) - // Means low integrity level. It is used by Protected Mode Internet - // Explorer. Blocks write acess to most objects (such as files and - // registry keys) on the system. - // - // SECURITY_MANDATORY_MEDIUM_RID (SID: S-1-16-0x2000) - // Means medium integrity level. It is used by normal applications - // being launched while UAC is enabled. - // - // SECURITY_MANDATORY_HIGH_RID (SID: S-1-16-0x3000) - // Means high integrity level. It is used by administrative applications - // launched through elevation when UAC is enabled, or normal - // applications if UAC is disabled and the user is an administrator. - // - // SECURITY_MANDATORY_SYSTEM_RID (SID: S-1-16-0x4000) - // Means system integrity level. It is used by services and other - // system-level applications (such as Wininit, Winlogon, Smss, etc.) - // - DWORD query_integrity_level(const Handle& token) - { - DWORD cb = 0; - - if (!GetTokenInformation(token, TokenIntegrityLevel, NULL, 0, &cb)) - { - switch (GetLastError()) - { - case ERROR_INSUFFICIENT_BUFFER: - break; - default: - error::raise("GetTokenInformation"); - } - } - - std::vector<unsigned char> buf(cb); - const auto token_level = reinterpret_cast<TOKEN_MANDATORY_LABEL*>(buf.data()); - - if (!GetTokenInformation(token, TokenIntegrityLevel, token_level, cb, &cb)) - error::raise("GetTokenInformation"); - - // Integrity Level SIDs are in the form of S-1-16-0xXXXX. (e.g. - // S-1-16-0x1000 stands for low integrity level SID). There is one and - // only one subauthority. - return *GetSidSubAuthority(token_level->Label.Sid, 0); - } - - std::wstring integrity_level_to_string(DWORD level) - { - static const std::unordered_map<DWORD, const wchar_t*> names = - { - {SECURITY_MANDATORY_UNTRUSTED_RID, L"Untrusted"}, - {SECURITY_MANDATORY_LOW_RID, L"Low"}, - {SECURITY_MANDATORY_MEDIUM_RID, L"Medium"}, - {SECURITY_MANDATORY_HIGH_RID, L"High"}, - {SECURITY_MANDATORY_SYSTEM_RID, L"System"}, - }; + DWORD query_integrity_level(const Handle& token); - static constexpr auto unknown_name = L"Unknown"; + std::wstring integrity_level_to_string(DWORD); - const auto it = names.find(level); + bool check_belongs(const Handle& token, const SidBuffer& sid); - if (it == names.cend()) - return unknown_name; - - return it->second; - } - - bool check_belongs(const Handle& token, const SidBuffer& sid) - { - BOOL b = FALSE; - - if (!CheckTokenMembership(token, const_cast<unsigned char*>(sid.data()), &b)) - error::raise("CheckTokenMembership"); - - return b != FALSE; - } - - bool query_elevation(const Handle& token) - { - TOKEN_ELEVATION elevation; - DWORD cb = 0; - - if (!GetTokenInformation(token, TokenElevation, &elevation, sizeof(elevation), &cb)) - error::raise("GetTokenInformation"); - - return elevation.TokenIsElevated != 0; - } + bool query_elevation(const Handle& token); } |