aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--src/error.cpp37
-rw-r--r--src/error.hpp23
-rw-r--r--src/handle.hpp2
-rw-r--r--src/main.cpp5
-rw-r--r--src/os.cpp24
-rw-r--r--src/os.hpp16
-rw-r--r--src/process.cpp64
-rw-r--r--src/process.hpp47
-rw-r--r--src/resource.cpp37
-rw-r--r--src/resource.hpp25
-rw-r--r--src/sid.cpp73
-rw-r--r--src/sid.hpp56
-rw-r--r--src/string.hpp14
-rw-r--r--src/token.cpp167
-rw-r--r--src/token.hpp152
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;
+ }
+}
diff --git a/src/os.hpp b/src/os.hpp
index 7aeaf54..c9a89a1 100644
--- a/src/os.hpp
+++ b/src/os.hpp
@@ -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);
}