[Windows] Add an AccessToken class to base/win.
This CL adds an AccessToken class to base/win to query properties of a
Windows access token. This is to remove the repeated use of the
GetTokenInformation API as well as removing requirements for including
the Windows headers.
Bug: 1270309
Change-Id: Ic49fee5faa7e3f3d61994de1d38ec2921de3ea4c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3301649
Reviewed-by: Will Harris <wfh@chromium.org>
Commit-Queue: James Forshaw <forshaw@chromium.org>
Cr-Commit-Position: refs/heads/main@{#946260}
NOKEYCHECK=True
GitOrigin-RevId: 158c5fad3ef830e95f1eedb702878697e4dd0154
diff --git a/policy/win/sandbox_win.cc b/policy/win/sandbox_win.cc
index 2db3ac6..ba68235 100644
--- a/policy/win/sandbox_win.cc
+++ b/policy/win/sandbox_win.cc
@@ -286,23 +286,16 @@
BlocklistAddOneDll(kTroublesomeDlls[ix], true, policy);
}
+DWORD GetSessionId() {
+ DWORD session_id;
+ CHECK(::ProcessIdToSessionId(::GetCurrentProcessId(), &session_id));
+ return session_id;
+}
+
// Returns the object path prepended with the current logon session.
std::wstring PrependWindowsSessionPath(const wchar_t* object) {
// Cache this because it can't change after process creation.
- static DWORD s_session_id = 0;
- if (s_session_id == 0) {
- HANDLE token;
- DWORD session_id_length;
- DWORD session_id = 0;
-
- CHECK(::OpenProcessToken(::GetCurrentProcess(), TOKEN_QUERY, &token));
- CHECK(::GetTokenInformation(token, TokenSessionId, &session_id,
- sizeof(session_id), &session_id_length));
- CloseHandle(token);
- if (session_id)
- s_session_id = session_id;
- }
-
+ static DWORD s_session_id = GetSessionId();
return base::StringPrintf(L"\\Sessions\\%lu%ls", s_session_id, object);
}
diff --git a/win/src/acl.cc b/win/src/acl.cc
index 4c70d03..f43d757 100644
--- a/win/src/acl.cc
+++ b/win/src/acl.cc
@@ -15,35 +15,13 @@
#include "base/check.h"
#include "base/memory/free_deleter.h"
#include "base/notreached.h"
+#include "base/win/access_token.h"
#include "base/win/scoped_localalloc.h"
namespace sandbox {
namespace {
-bool GetDefaultDacl(
- HANDLE token,
- std::unique_ptr<TOKEN_DEFAULT_DACL, base::FreeDeleter>* default_dacl) {
- if (!token)
- return false;
-
- DCHECK(default_dacl);
-
- unsigned long length = 0;
- ::GetTokenInformation(token, TokenDefaultDacl, nullptr, 0, &length);
- if (length == 0) {
- NOTREACHED();
- return false;
- }
-
- TOKEN_DEFAULT_DACL* acl =
- reinterpret_cast<TOKEN_DEFAULT_DACL*>(malloc(length));
- default_dacl->reset(acl);
-
- return !!::GetTokenInformation(token, TokenDefaultDacl, default_dacl->get(),
- length, &length);
-}
-
ACCESS_MODE ConvertAccessMode(SecurityAccessMode access_mode) {
switch (access_mode) {
case SecurityAccessMode::kGrant:
@@ -61,25 +39,21 @@
return NOT_USED_ACCESS;
}
-bool AddSidToDacl(const base::win::Sid& sid,
- ACL* old_dacl,
- SecurityAccessMode access_mode,
- ACCESS_MASK access,
- ACL** new_dacl) {
- EXPLICIT_ACCESS new_access = {0};
+absl::optional<base::win::ScopedLocalAllocTyped<ACL>> AddSidToDacl(
+ const base::win::Sid& sid,
+ ACL* old_dacl,
+ SecurityAccessMode access_mode,
+ ACCESS_MASK access) {
+ EXPLICIT_ACCESS new_access = {};
new_access.grfAccessMode = ConvertAccessMode(access_mode);
new_access.grfAccessPermissions = access;
new_access.grfInheritance = NO_INHERITANCE;
-
- new_access.Trustee.pMultipleTrustee = nullptr;
- new_access.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
- new_access.Trustee.TrusteeForm = TRUSTEE_IS_SID;
- new_access.Trustee.ptstrName = reinterpret_cast<LPWSTR>(sid.GetPSID());
-
- if (ERROR_SUCCESS != ::SetEntriesInAcl(1, &new_access, old_dacl, new_dacl))
- return false;
-
- return true;
+ ::BuildTrusteeWithSid(&new_access.Trustee, sid.GetPSID());
+ ACL* new_dacl = nullptr;
+ if (ERROR_SUCCESS != ::SetEntriesInAcl(1, &new_access, old_dacl, &new_dacl))
+ return absl::nullopt;
+ DCHECK(::IsValidAcl(new_dacl));
+ return base::win::TakeLocalAlloc(new_dacl);
}
SE_OBJECT_TYPE ConvertObjectType(SecurityObjectType object_type) {
@@ -123,33 +97,41 @@
return absl::nullopt;
}
-} // namespace
-
bool AddSidToDefaultDacl(HANDLE token,
+ const base::win::AccessToken& query_token,
const base::win::Sid& sid,
SecurityAccessMode access_mode,
ACCESS_MASK access) {
if (!token)
return false;
- std::unique_ptr<TOKEN_DEFAULT_DACL, base::FreeDeleter> default_dacl;
- if (!GetDefaultDacl(token, &default_dacl))
+ absl::optional<base::win::AccessToken::Dacl> dacl = query_token.DefaultDacl();
+ if (!dacl)
+ return false;
+ auto new_dacl = AddSidToDacl(sid, dacl->GetAcl(), access_mode, access);
+ if (!new_dacl)
return false;
- ACL* new_dacl_ptr = nullptr;
- if (!AddSidToDacl(sid, default_dacl->DefaultDacl, access_mode, access,
- &new_dacl_ptr)) {
- return false;
- }
-
- auto new_dacl = base::win::TakeLocalAlloc(new_dacl_ptr);
TOKEN_DEFAULT_DACL new_token_dacl = {0};
- new_token_dacl.DefaultDacl = new_dacl.get();
-
+ new_token_dacl.DefaultDacl = new_dacl->get();
return !!::SetTokenInformation(token, TokenDefaultDacl, &new_token_dacl,
sizeof(new_token_dacl));
}
+} // namespace
+
+bool AddSidToDefaultDacl(HANDLE token,
+ const base::win::Sid& sid,
+ SecurityAccessMode access_mode,
+ ACCESS_MASK access) {
+ absl::optional<base::win::AccessToken> query_token =
+ base::win::AccessToken::FromToken(token);
+ if (!query_token)
+ return false;
+
+ return AddSidToDefaultDacl(token, *query_token, sid, access_mode, access);
+}
+
bool AddSidToDefaultDacl(HANDLE token,
base::win::WellKnownSid known_sid,
SecurityAccessMode access_mode,
@@ -161,38 +143,25 @@
}
bool RevokeLogonSidFromDefaultDacl(HANDLE token) {
- char logon_sid_buffer[sizeof(TOKEN_GROUPS) + SECURITY_MAX_SID_SIZE];
- DWORD size = sizeof(logon_sid_buffer);
+ absl::optional<base::win::AccessToken> query_token =
+ base::win::AccessToken::FromToken(token);
+ if (!query_token)
+ return false;
+ absl::optional<base::win::Sid> logon_sid = query_token->LogonId();
+ if (!logon_sid)
+ return ::GetLastError() == ERROR_NOT_FOUND;
- if (!::GetTokenInformation(token, TokenLogonSid, logon_sid_buffer, size,
- &size)) {
- // If no logon sid, there's nothing to revoke.
- if (::GetLastError() == ERROR_NOT_FOUND)
- return true;
- return false;
- }
- TOKEN_GROUPS* logon_sid_ptr =
- reinterpret_cast<TOKEN_GROUPS*>(logon_sid_buffer);
- if (logon_sid_ptr->GroupCount < 1) {
- ::SetLastError(ERROR_INVALID_TOKEN);
- return false;
- }
- absl::optional<base::win::Sid> logon_sid =
- base::win::Sid::FromPSID(logon_sid_ptr->Groups[0].Sid);
- if (!logon_sid) {
- ::SetLastError(ERROR_INVALID_SID);
- return false;
- }
- return AddSidToDefaultDacl(token, *logon_sid, SecurityAccessMode::kRevoke, 0);
+ return AddSidToDefaultDacl(token, *query_token, *logon_sid,
+ SecurityAccessMode::kRevoke, 0);
}
bool AddUserSidToDefaultDacl(HANDLE token, ACCESS_MASK access) {
- absl::optional<base::win::Sid> user_sid = base::win::Sid::FromToken(token);
- if (!user_sid)
+ absl::optional<base::win::AccessToken> query_token =
+ base::win::AccessToken::FromToken(token);
+ if (!query_token)
return false;
-
- return AddSidToDefaultDacl(token, *user_sid, SecurityAccessMode::kGrant,
- access);
+ return AddSidToDefaultDacl(token, *query_token, query_token->User(),
+ SecurityAccessMode::kGrant, access);
}
bool AddKnownSidToObject(HANDLE object,
@@ -214,14 +183,13 @@
}
auto descriptor = base::win::TakeLocalAlloc(descriptor_ptr);
- PACL new_dacl_ptr = nullptr;
- if (!AddSidToDacl(sid, old_dacl, access_mode, access, &new_dacl_ptr))
+ auto new_dacl = AddSidToDacl(sid, old_dacl, access_mode, access);
+ if (!new_dacl)
return false;
- auto new_dacl = base::win::TakeLocalAlloc(new_dacl_ptr);
return ::SetSecurityInfo(object, native_object_type,
DACL_SECURITY_INFORMATION, nullptr, nullptr,
- new_dacl.get(), nullptr) == ERROR_SUCCESS;
+ new_dacl->get(), nullptr) == ERROR_SUCCESS;
}
bool AddKnownSidToObject(HANDLE object,
diff --git a/win/src/app_container_test.cc b/win/src/app_container_test.cc
index 5a166fe..d942eab 100644
--- a/win/src/app_container_test.cc
+++ b/win/src/app_container_test.cc
@@ -28,6 +28,7 @@
#include "base/task/thread_pool.h"
#include "base/test/task_environment.h"
#include "base/test/test_timeouts.h"
+#include "base/win/access_token.h"
#include "base/win/scoped_handle.h"
#include "base/win/scoped_localalloc.h"
#include "base/win/scoped_process_information.h"
@@ -35,7 +36,6 @@
#include "base/win/windows_version.h"
#include "sandbox/win/src/app_container_base.h"
#include "sandbox/win/src/sandbox_factory.h"
-#include "sandbox/win/src/win_utils.h"
#include "sandbox/win/tests/common/controller.h"
#include "sandbox/win/tests/common/test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -68,78 +68,55 @@
base::RandUint64());
}
-const char* TokenTypeToName(TOKEN_TYPE token_type) {
- return token_type == ::TokenPrimary ? "Primary Token" : "Impersonation Token";
+const char* TokenTypeToName(bool impersonation) {
+ return impersonation ? "Impersonation Token" : "Primary Token";
}
-void CheckToken(HANDLE token,
- TOKEN_TYPE token_type,
+void CheckToken(const absl::optional<base::win::AccessToken>& token,
+ bool impersonation,
PSECURITY_CAPABILITIES security_capabilities,
- BOOL restricted) {
- ASSERT_EQ(restricted, ::IsTokenRestricted(token))
- << TokenTypeToName(token_type);
-
- DWORD appcontainer;
- DWORD return_length;
- ASSERT_TRUE(::GetTokenInformation(token, ::TokenIsAppContainer, &appcontainer,
- sizeof(appcontainer), &return_length))
- << TokenTypeToName(token_type);
- ASSERT_TRUE(appcontainer) << TokenTypeToName(token_type);
- TOKEN_TYPE token_type_real;
- ASSERT_TRUE(::GetTokenInformation(token, ::TokenType, &token_type_real,
- sizeof(token_type_real), &return_length))
- << TokenTypeToName(token_type);
- ASSERT_EQ(token_type_real, token_type) << TokenTypeToName(token_type);
- if (token_type == ::TokenImpersonation) {
- SECURITY_IMPERSONATION_LEVEL imp_level;
- ASSERT_TRUE(::GetTokenInformation(token, ::TokenImpersonationLevel,
- &imp_level, sizeof(imp_level),
- &return_length))
- << TokenTypeToName(token_type);
- ASSERT_EQ(imp_level, ::SecurityImpersonation)
- << TokenTypeToName(token_type);
+ bool restricted) {
+ ASSERT_TRUE(token);
+ EXPECT_EQ(restricted, token->IsRestricted())
+ << TokenTypeToName(impersonation);
+ EXPECT_TRUE(token->IsAppContainer()) << TokenTypeToName(impersonation);
+ EXPECT_EQ(token->IsImpersonation(), impersonation)
+ << TokenTypeToName(impersonation);
+ if (impersonation) {
+ EXPECT_FALSE(token->IsIdentification()) << TokenTypeToName(impersonation);
}
- absl::optional<base::win::Sid> package_sid = GetTokenAppContainerSid(token);
- ASSERT_TRUE(package_sid) << TokenTypeToName(token_type);
- EXPECT_TRUE(::EqualSid(security_capabilities->AppContainerSid,
- package_sid->GetPSID()))
- << TokenTypeToName(token_type);
+ absl::optional<base::win::Sid> package_sid = token->AppContainerSid();
+ ASSERT_TRUE(package_sid) << TokenTypeToName(impersonation);
+ EXPECT_TRUE(package_sid->Equal(security_capabilities->AppContainerSid))
+ << TokenTypeToName(impersonation);
- absl::optional<std::vector<SidAndAttributes>> capability_groups =
- GetTokenGroups(token, ::TokenCapabilities);
- ASSERT_TRUE(capability_groups) << TokenTypeToName(token_type);
- const std::vector<SidAndAttributes>& capabilities = *capability_groups;
-
+ std::vector<base::win::AccessToken::Group> capabilities =
+ token->Capabilities();
ASSERT_EQ(capabilities.size(), security_capabilities->CapabilityCount)
- << TokenTypeToName(token_type);
+ << TokenTypeToName(impersonation);
for (size_t index = 0; index < capabilities.size(); ++index) {
EXPECT_EQ(capabilities[index].GetAttributes(),
security_capabilities->Capabilities[index].Attributes)
- << TokenTypeToName(token_type);
- EXPECT_TRUE(::EqualSid(capabilities[index].GetPSID(),
- security_capabilities->Capabilities[index].Sid))
- << TokenTypeToName(token_type);
+ << TokenTypeToName(impersonation);
+ EXPECT_TRUE(capabilities[index].GetSid().Equal(
+ security_capabilities->Capabilities[index].Sid))
+ << TokenTypeToName(impersonation);
}
}
void CheckProcessToken(HANDLE process,
PSECURITY_CAPABILITIES security_capabilities,
bool restricted) {
- HANDLE token_handle;
- ASSERT_TRUE(::OpenProcessToken(process, TOKEN_ALL_ACCESS, &token_handle));
- base::win::ScopedHandle token(token_handle);
- CheckToken(token_handle, ::TokenPrimary, security_capabilities, restricted);
+ CheckToken(base::win::AccessToken::FromProcess(process), false,
+ security_capabilities, restricted);
}
void CheckThreadToken(HANDLE thread,
PSECURITY_CAPABILITIES security_capabilities,
bool restricted) {
- HANDLE token_handle;
- ASSERT_TRUE(::OpenThreadToken(thread, TOKEN_ALL_ACCESS, TRUE, &token_handle));
- base::win::ScopedHandle token(token_handle);
- CheckToken(token_handle, ::TokenImpersonation, security_capabilities,
- restricted);
+ CheckToken(base::win::AccessToken::FromThread(thread), true,
+ security_capabilities, restricted);
}
// Check for LPAC using an access check. We could query for a security attribute
diff --git a/win/src/integrity_level_test.cc b/win/src/integrity_level_test.cc
index a4788af..0fa2627 100644
--- a/win/src/integrity_level_test.cc
+++ b/win/src/integrity_level_test.cc
@@ -7,12 +7,14 @@
#include <atlsecurity.h>
#include "base/process/process_info.h"
+#include "base/win/access_token.h"
#include "base/win/windows_version.h"
#include "sandbox/win/src/sandbox.h"
#include "sandbox/win/src/sandbox_factory.h"
#include "sandbox/win/src/sandbox_policy.h"
#include "sandbox/win/tests/common/controller.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace sandbox {
@@ -29,29 +31,12 @@
}
SBOX_TESTS_COMMAND int CheckIntegrityLevel(int argc, wchar_t** argv) {
- ATL::CAccessToken token;
- if (!token.GetEffectiveToken(TOKEN_READ))
+ absl::optional<base::win::AccessToken> token =
+ base::win::AccessToken::FromEffective();
+ if (!token)
return SBOX_TEST_FAILED;
- char* buffer[100];
- DWORD buf_size = 100;
- if (!::GetTokenInformation(token.GetHandle(), TokenIntegrityLevel,
- reinterpret_cast<void*>(buffer), buf_size,
- &buf_size))
- return SBOX_TEST_FAILED;
-
- TOKEN_MANDATORY_LABEL* label =
- reinterpret_cast<TOKEN_MANDATORY_LABEL*>(buffer);
-
- PSID sid_low = nullptr;
- if (!::ConvertStringSidToSid(L"S-1-16-4096", &sid_low))
- return SBOX_TEST_FAILED;
-
- bool is_low_sid = ::EqualSid(label->Label.Sid, sid_low);
-
- ::LocalFree(sid_low);
-
- if (is_low_sid)
+ if (token->IntegrityLevel() == SECURITY_MANDATORY_LOW_RID)
return SBOX_TEST_SUCCEEDED;
return SBOX_TEST_DENIED;
diff --git a/win/src/restricted_token.cc b/win/src/restricted_token.cc
index 16c96d4..7977565 100644
--- a/win/src/restricted_token.cc
+++ b/win/src/restricted_token.cc
@@ -9,25 +9,15 @@
#include <stddef.h>
#include <memory>
+#include <unordered_set>
#include <vector>
#include "base/logging.h"
+#include "base/win/access_token.h"
#include "sandbox/win/src/acl.h"
-#include "sandbox/win/src/win_utils.h"
namespace {
-// Wrapper for utility version to unwrap ScopedHandle.
-std::unique_ptr<BYTE[]> GetTokenInfo(const base::win::ScopedHandle& token,
- TOKEN_INFORMATION_CLASS info_class,
- DWORD* error) {
- std::unique_ptr<BYTE[]> buffer;
- *error = sandbox::GetTokenInformation(token.Get(), info_class, &buffer);
- if (*error != ERROR_SUCCESS)
- return nullptr;
- return buffer;
-}
-
LUID ConvertToLuid(const CHROME_LUID& luid) {
LUID ret;
memcpy(&ret, &luid, sizeof(luid));
@@ -82,6 +72,11 @@
}
}
effective_token_.Set(temp_token);
+ absl::optional<base::win::AccessToken> query_token =
+ base::win::AccessToken::FromToken(effective_token_.Get());
+ if (!query_token)
+ return ERROR_NO_TOKEN;
+ query_token_.swap(query_token);
init_ = true;
return ERROR_SUCCESS;
@@ -178,21 +173,12 @@
return err_code;
HANDLE impersonation_token_handle;
- if (!::DuplicateToken(restricted_token.Get(), SecurityImpersonation,
- &impersonation_token_handle)) {
+ if (!::DuplicateTokenEx(restricted_token.Get(), TOKEN_ALL_ACCESS, nullptr,
+ SecurityImpersonation, TokenImpersonation,
+ &impersonation_token_handle)) {
return ::GetLastError();
}
- base::win::ScopedHandle impersonation_token(impersonation_token_handle);
-
- HANDLE token_handle;
- if (!::DuplicateHandle(::GetCurrentProcess(), impersonation_token.Get(),
- ::GetCurrentProcess(), &token_handle, TOKEN_ALL_ACCESS,
- false, // Don't inherit.
- 0)) {
- return ::GetLastError();
- }
-
- token->Set(token_handle);
+ token->Set(impersonation_token_handle);
return ERROR_SUCCESS;
}
@@ -202,30 +188,19 @@
if (!init_)
return ERROR_NO_TOKEN;
- DWORD error;
- std::unique_ptr<BYTE[]> buffer =
- GetTokenInfo(effective_token_, TokenGroups, &error);
-
- if (!buffer)
- return error;
-
- TOKEN_GROUPS* token_groups = reinterpret_cast<TOKEN_GROUPS*>(buffer.get());
-
// Build the list of the deny only group SIDs
- for (unsigned int i = 0; i < token_groups->GroupCount; ++i) {
- if ((token_groups->Groups[i].Attributes & SE_GROUP_INTEGRITY) == 0 &&
- (token_groups->Groups[i].Attributes & SE_GROUP_LOGON_ID) == 0) {
- bool should_ignore = false;
- for (const base::win::Sid& sid : exceptions) {
- if (sid.Equal(token_groups->Groups[i].Sid)) {
- should_ignore = true;
- break;
- }
+ for (const base::win::AccessToken::Group& group : query_token_->Groups()) {
+ if (group.IsIntegrity() || group.IsLogonId())
+ continue;
+ bool should_ignore = false;
+ for (const base::win::Sid& sid : exceptions) {
+ if (sid == group.GetSid()) {
+ should_ignore = true;
+ break;
}
- if (!should_ignore) {
- sids_for_deny_only_.push_back(
- *base::win::Sid::FromPSID(token_groups->Groups[i].Sid));
- }
+ }
+ if (!should_ignore) {
+ sids_for_deny_only_.push_back(group.GetSid().Clone());
}
}
@@ -253,12 +228,7 @@
if (!init_)
return ERROR_NO_TOKEN;
- absl::optional<base::win::Sid> user = base::win::Sid::CurrentUser();
- if (!user)
- return ERROR_INVALID_SID;
-
- sids_for_deny_only_.push_back(std::move(*user));
-
+ sids_for_deny_only_.push_back(query_token_->User());
return ERROR_SUCCESS;
}
@@ -267,32 +237,13 @@
DCHECK(init_);
if (!init_)
return ERROR_NO_TOKEN;
-
- DWORD error;
- std::unique_ptr<BYTE[]> buffer =
- GetTokenInfo(effective_token_, TokenPrivileges, &error);
-
- if (!buffer)
- return error;
-
- TOKEN_PRIVILEGES* token_privileges =
- reinterpret_cast<TOKEN_PRIVILEGES*>(buffer.get());
-
+ std::unordered_set<std::wstring> privilege_set(exceptions.begin(),
+ exceptions.end());
// Build the list of privileges to disable
- for (unsigned int i = 0; i < token_privileges->PrivilegeCount; ++i) {
- bool should_ignore = false;
- for (const std::wstring& name : exceptions) {
- LUID luid = {};
- ::LookupPrivilegeValue(nullptr, name.c_str(), &luid);
- if (token_privileges->Privileges[i].Luid.HighPart == luid.HighPart &&
- token_privileges->Privileges[i].Luid.LowPart == luid.LowPart) {
- should_ignore = true;
- break;
- }
- }
- if (!should_ignore) {
- privileges_to_disable_.push_back(
- ConvertToChromeLuid(token_privileges->Privileges[i].Luid));
+ for (const base::win::AccessToken::Privilege& privilege :
+ query_token_->Privileges()) {
+ if (privilege_set.count(privilege.GetName()) == 0) {
+ privileges_to_disable_.push_back(privilege.GetLuid());
}
}
@@ -334,30 +285,9 @@
if (!init_)
return ERROR_NO_TOKEN;
- DWORD error;
- std::unique_ptr<BYTE[]> buffer =
- GetTokenInfo(effective_token_, TokenGroups, &error);
-
- if (!buffer)
- return error;
-
- TOKEN_GROUPS* token_groups = reinterpret_cast<TOKEN_GROUPS*>(buffer.get());
-
- PSID logon_sid_ptr = nullptr;
- for (unsigned int i = 0; i < token_groups->GroupCount; ++i) {
- if ((token_groups->Groups[i].Attributes & SE_GROUP_LOGON_ID) != 0) {
- logon_sid_ptr = token_groups->Groups[i].Sid;
- break;
- }
- }
-
- if (logon_sid_ptr) {
- absl::optional<base::win::Sid> logon_sid =
- base::win::Sid::FromPSID(logon_sid_ptr);
- if (!logon_sid)
- return ERROR_INVALID_SID;
+ absl::optional<base::win::Sid> logon_sid = query_token_->LogonId();
+ if (logon_sid)
sids_to_restrict_.push_back(std::move(*logon_sid));
- }
return ERROR_SUCCESS;
}
@@ -365,12 +295,7 @@
DCHECK(init_);
if (!init_)
return ERROR_NO_TOKEN;
-
- absl::optional<base::win::Sid> user = base::win::Sid::CurrentUser();
- if (!user)
- return ERROR_INVALID_SID;
- sids_to_restrict_.push_back(std::move(*user));
-
+ sids_to_restrict_.push_back(query_token_->User());
return ERROR_SUCCESS;
}
@@ -384,23 +309,10 @@
if (ERROR_SUCCESS != error)
return error;
- std::unique_ptr<BYTE[]> buffer =
- GetTokenInfo(effective_token_, TokenGroups, &error);
-
- if (!buffer)
- return error;
-
- TOKEN_GROUPS* token_groups = reinterpret_cast<TOKEN_GROUPS*>(buffer.get());
-
- // Build the list of restricting sids from all groups.
- for (unsigned int i = 0; i < token_groups->GroupCount; ++i) {
- if ((token_groups->Groups[i].Attributes & SE_GROUP_INTEGRITY) == 0) {
- absl::optional<base::win::Sid> sid =
- base::win::Sid::FromPSID(token_groups->Groups[i].Sid);
- if (!sid)
- return ERROR_INVALID_SID;
- AddRestrictingSid(*sid);
- }
+ for (const base::win::AccessToken::Group& group : query_token_->Groups()) {
+ if (group.IsIntegrity())
+ continue;
+ AddRestrictingSid(group.GetSid());
}
return ERROR_SUCCESS;
diff --git a/win/src/restricted_token.h b/win/src/restricted_token.h
index 5345161..71ac545 100644
--- a/win/src/restricted_token.h
+++ b/win/src/restricted_token.h
@@ -10,12 +10,14 @@
#include <string>
#include <tuple>
+#include "base/win/access_token.h"
#include "base/win/scoped_handle.h"
#include "base/win/sid.h"
#include "base/win/windows_types.h"
#include "sandbox/win/src/acl.h"
#include "sandbox/win/src/restricted_token_utils.h"
#include "sandbox/win/src/security_level.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace sandbox {
@@ -181,8 +183,8 @@
// the error.
DWORD AddRestrictingSidAllSids();
- // Sets the token integrity level. This is only valid on Vista. The integrity
- // level cannot be higher than your current integrity level.
+ // Sets the token integrity level. The integrity level cannot be higher than
+ // your current integrity level.
DWORD SetIntegrityLevel(IntegrityLevel integrity_level);
// Set a flag which indicates the created token should have a locked down
@@ -213,7 +215,9 @@
sids_for_default_dacl_;
// The token to restrict. Can only be set in a constructor.
base::win::ScopedHandle effective_token_;
- // The token integrity level. Only valid on Vista.
+ // The token in a form for querying.
+ absl::optional<base::win::AccessToken> query_token_;
+ // The token integrity level.
IntegrityLevel integrity_level_;
// Tells if the object is initialized or not (if Init() has been called)
bool init_;
diff --git a/win/src/restricted_token_test.cc b/win/src/restricted_token_test.cc
index e788858..5e99ae8 100644
--- a/win/src/restricted_token_test.cc
+++ b/win/src/restricted_token_test.cc
@@ -8,13 +8,14 @@
#include <string>
#include "base/strings/stringprintf.h"
+#include "base/win/access_token.h"
#include "base/win/scoped_handle.h"
#include "sandbox/win/src/sandbox.h"
#include "sandbox/win/src/sandbox_factory.h"
#include "sandbox/win/src/target_services.h"
-#include "sandbox/win/src/win_utils.h"
#include "sandbox/win/tests/common/controller.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace sandbox {
@@ -128,19 +129,12 @@
// Opens a the process token and checks if it's restricted.
SBOX_TESTS_COMMAND int RestrictedTokenTest_IsRestricted(int argc,
wchar_t** argv) {
- HANDLE token_handle;
- if (!::OpenProcessToken(::GetCurrentProcess(), TOKEN_QUERY, &token_handle))
+ absl::optional<base::win::AccessToken> token =
+ base::win::AccessToken::FromCurrentProcess();
+ if (!token)
return SBOX_TEST_FIRST_ERROR;
- base::win::ScopedHandle token(token_handle);
-
- std::unique_ptr<BYTE[]> groups;
- if (GetTokenInformation(token_handle, TokenRestrictedSids, &groups) !=
- ERROR_SUCCESS) {
- return SBOX_TEST_SECOND_ERROR;
- }
-
- auto* token_groups = reinterpret_cast<PTOKEN_GROUPS>(groups.get());
- return token_groups->GroupCount > 0 ? SBOX_TEST_SUCCEEDED : SBOX_TEST_FAILED;
+ return token->RestrictedSids().size() > 0 ? SBOX_TEST_SUCCEEDED
+ : SBOX_TEST_FAILED;
}
TEST(RestrictedTokenTest, OpenLowPrivilegedProcess) {
diff --git a/win/src/restricted_token_unittest.cc b/win/src/restricted_token_unittest.cc
index 534d5e0..e0dd7da 100644
--- a/win/src/restricted_token_unittest.cc
+++ b/win/src/restricted_token_unittest.cc
@@ -8,6 +8,7 @@
#include <vector>
+#include "base/win/access_token.h"
#include "base/win/atl.h"
#include "base/win/scoped_handle.h"
#include "base/win/sid.h"
@@ -15,6 +16,7 @@
#include "sandbox/win/src/acl.h"
#include "sandbox/win/src/security_capabilities.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace sandbox {
@@ -83,29 +85,6 @@
ASSERT_FALSE(logon_sid_found);
}
-bool GetVariableTokenInformation(HANDLE token,
- TOKEN_INFORMATION_CLASS information_class,
- std::vector<char>* information) {
- DWORD return_length;
- if (!::GetTokenInformation(token, information_class, nullptr, 0,
- &return_length)) {
- if (::GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
- return false;
- }
- }
-
- information->resize(return_length);
- return !!::GetTokenInformation(token, information_class, information->data(),
- return_length, &return_length);
-}
-
-bool GetVariableTokenInformation(const base::win::ScopedHandle& token,
- TOKEN_INFORMATION_CLASS information_class,
- std::vector<char>* information) {
- return GetVariableTokenInformation(token.Get(), information_class,
- information);
-}
-
void CheckDaclForPackageSid(const base::win::ScopedHandle& token,
PSECURITY_CAPABILITIES security_capabilities,
bool package_sid_required) {
@@ -147,71 +126,43 @@
}
}
-void CheckLowBoxToken(const base::win::ScopedHandle& token,
- TOKEN_TYPE token_type,
+void CheckLowBoxToken(const base::win::ScopedHandle& lowbox_token,
+ bool impersonation,
PSECURITY_CAPABILITIES security_capabilities) {
- DWORD appcontainer;
- DWORD return_length;
- ASSERT_TRUE(::GetTokenInformation(token.Get(), ::TokenIsAppContainer,
- &appcontainer, sizeof(appcontainer),
- &return_length));
- ASSERT_TRUE(appcontainer);
- TOKEN_TYPE token_type_real;
- ASSERT_TRUE(::GetTokenInformation(token.Get(), ::TokenType, &token_type_real,
- sizeof(token_type_real), &return_length));
- ASSERT_EQ(token_type_real, token_type);
- if (token_type == ::TokenImpersonation) {
- SECURITY_IMPERSONATION_LEVEL imp_level;
- ASSERT_TRUE(::GetTokenInformation(token.Get(), ::TokenImpersonationLevel,
- &imp_level, sizeof(imp_level),
- &return_length));
- ASSERT_EQ(imp_level, ::SecurityImpersonation);
- }
+ auto token = base::win::AccessToken::FromToken(lowbox_token.Get());
+ ASSERT_TRUE(token);
+ EXPECT_TRUE(token->IsAppContainer());
+ EXPECT_EQ(impersonation, token->IsImpersonation());
+ EXPECT_FALSE(token->IsIdentification());
+ auto package_sid = token->AppContainerSid();
+ ASSERT_TRUE(package_sid);
+ EXPECT_TRUE(package_sid->Equal(security_capabilities->AppContainerSid));
- std::vector<char> package_sid_buf;
- ASSERT_TRUE(GetVariableTokenInformation(token, ::TokenAppContainerSid,
- &package_sid_buf));
- PTOKEN_APPCONTAINER_INFORMATION package_sid =
- reinterpret_cast<PTOKEN_APPCONTAINER_INFORMATION>(package_sid_buf.data());
- EXPECT_TRUE(::EqualSid(security_capabilities->AppContainerSid,
- package_sid->TokenAppContainer));
-
- std::vector<char> capabilities_buf;
- ASSERT_TRUE(GetVariableTokenInformation(token, ::TokenCapabilities,
- &capabilities_buf));
- PTOKEN_GROUPS capabilities =
- reinterpret_cast<PTOKEN_GROUPS>(capabilities_buf.data());
- ASSERT_EQ(capabilities->GroupCount, security_capabilities->CapabilityCount);
- for (DWORD index = 0; index < capabilities->GroupCount; ++index) {
- EXPECT_EQ(capabilities->Groups[index].Attributes,
+ auto capabilities = token->Capabilities();
+ ASSERT_EQ(capabilities.size(), security_capabilities->CapabilityCount);
+ for (size_t index = 0; index < capabilities.size(); ++index) {
+ EXPECT_EQ(capabilities[index].GetAttributes(),
security_capabilities->Capabilities[index].Attributes);
- EXPECT_TRUE(::EqualSid(capabilities->Groups[index].Sid,
- security_capabilities->Capabilities[index].Sid));
+ EXPECT_TRUE(capabilities[index].GetSid().Equal(
+ security_capabilities->Capabilities[index].Sid));
}
- CheckDaclForPackageSid(token, security_capabilities, true);
+ CheckDaclForPackageSid(lowbox_token, security_capabilities, true);
}
// Checks if a sid is in the restricting list of the restricted token.
// Asserts if it's not the case. If count is a positive number, the number of
// elements in the restricting sids list has to be equal.
-void CheckRestrictingSid(HANDLE restricted_token, ATL::CSid sid, int count) {
- std::vector<char> memory;
- ASSERT_TRUE(GetVariableTokenInformation(restricted_token,
- ::TokenRestrictedSids, &memory));
- PTOKEN_GROUPS groups = reinterpret_cast<PTOKEN_GROUPS>(memory.data());
- ATL::CTokenGroups atl_groups(*groups);
-
+void CheckRestrictingSid(const base::win::AccessToken& token,
+ const base::win::Sid& sid,
+ int count) {
+ auto restricted_sids = token.RestrictedSids();
if (count >= 0)
- ASSERT_EQ(static_cast<unsigned>(count), atl_groups.GetCount());
-
- ATL::CSid::CSidArray sids;
- ATL::CAtlArray<DWORD> attributes;
- atl_groups.GetSidsAndAttributes(&sids, &attributes);
+ ASSERT_EQ(static_cast<unsigned>(count), restricted_sids.size());
bool present = false;
- for (unsigned int i = 0; i < sids.GetCount(); ++i) {
- if (sids[i] == sid) {
+ for (const base::win::AccessToken::Group& group : restricted_sids) {
+ if (group.GetSid() == sid) {
present = true;
break;
}
@@ -220,10 +171,18 @@
ASSERT_TRUE(present);
}
-void CheckRestrictingSid(const ATL::CAccessToken& restricted_token,
- ATL::CSid sid,
+void CheckRestrictingSid(const base::win::AccessToken& token,
+ base::win::WellKnownSid known_sid,
int count) {
- CheckRestrictingSid(restricted_token.GetHandle(), sid, count);
+ CheckRestrictingSid(token, *base::win::Sid::FromKnownSid(known_sid), count);
+}
+
+void CheckRestrictingSid(HANDLE restricted_token,
+ base::win::WellKnownSid known_sid,
+ int count) {
+ auto token = base::win::AccessToken::FromToken(restricted_token);
+ ASSERT_TRUE(token);
+ CheckRestrictingSid(*token, known_sid, count);
}
} // namespace
@@ -238,54 +197,31 @@
// Tests the initialization with nullptr as parameter.
TEST(RestrictedTokenTest, DefaultInit) {
// Get the current process token.
- HANDLE token_handle = INVALID_HANDLE_VALUE;
- ASSERT_TRUE(::OpenProcessToken(::GetCurrentProcess(), TOKEN_ALL_ACCESS,
- &token_handle));
-
- ASSERT_NE(INVALID_HANDLE_VALUE, token_handle);
-
- ATL::CAccessToken access_token;
- access_token.Attach(token_handle);
+ absl::optional<base::win::AccessToken> access_token =
+ base::win::AccessToken::FromCurrentProcess();
+ ASSERT_TRUE(access_token);
// Create the token using the current token.
RestrictedToken token_default;
ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token_default.Init(nullptr));
// Get the handle to the restricted token.
-
base::win::ScopedHandle restricted_token_handle;
ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
token_default.GetRestrictedToken(&restricted_token_handle));
- ATL::CAccessToken restricted_token;
- restricted_token.Attach(restricted_token_handle.Take());
-
- ATL::CSid sid_user_restricted;
- ATL::CSid sid_user_default;
- ATL::CSid sid_owner_restricted;
- ATL::CSid sid_owner_default;
- ASSERT_TRUE(restricted_token.GetUser(&sid_user_restricted));
- ASSERT_TRUE(access_token.GetUser(&sid_user_default));
- ASSERT_TRUE(restricted_token.GetOwner(&sid_owner_restricted));
- ASSERT_TRUE(access_token.GetOwner(&sid_owner_default));
-
+ auto restricted_token =
+ base::win::AccessToken::FromToken(restricted_token_handle.Get());
+ ASSERT_TRUE(restricted_token);
// Check if both token have the same owner and user.
- ASSERT_EQ(sid_user_restricted, sid_user_default);
- ASSERT_EQ(sid_owner_restricted, sid_owner_default);
+ EXPECT_EQ(restricted_token->User(), access_token->User());
+ EXPECT_EQ(restricted_token->Owner(), access_token->Owner());
}
// Tests the initialization with a custom token as parameter.
TEST(RestrictedTokenTest, CustomInit) {
- // Get the current process token.
- HANDLE token_handle = INVALID_HANDLE_VALUE;
- ASSERT_TRUE(::OpenProcessToken(::GetCurrentProcess(), TOKEN_ALL_ACCESS,
- &token_handle));
-
- ASSERT_NE(INVALID_HANDLE_VALUE, token_handle);
-
- ATL::CAccessToken access_token;
- access_token.Attach(token_handle);
-
+ CAccessToken access_token;
+ ASSERT_TRUE(access_token.GetProcessToken(TOKEN_ALL_ACCESS));
// Change the primary group.
access_token.SetPrimaryGroup(ATL::Sids::World());
@@ -293,23 +229,18 @@
RestrictedToken token;
ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
token.Init(access_token.GetHandle()));
-
- // Get the handle to the restricted token.
-
base::win::ScopedHandle restricted_token_handle;
ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
token.GetRestrictedToken(&restricted_token_handle));
+ auto restricted_token =
+ base::win::AccessToken::FromToken(restricted_token_handle.Get());
+ ASSERT_TRUE(restricted_token);
- ATL::CAccessToken restricted_token;
- restricted_token.Attach(restricted_token_handle.Take());
-
- ATL::CSid sid_restricted;
ATL::CSid sid_default;
- ASSERT_TRUE(restricted_token.GetPrimaryGroup(&sid_restricted));
ASSERT_TRUE(access_token.GetPrimaryGroup(&sid_default));
-
- // Check if both token have the same owner.
- ASSERT_EQ(sid_restricted, sid_default);
+ // Check if both token have the same primary grou.
+ ASSERT_TRUE(restricted_token->PrimaryGroup().Equal(
+ const_cast<SID*>(sid_default.GetPSID())));
}
// Verifies that the token created by the object are valid.
@@ -324,25 +255,20 @@
ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
token.GetRestrictedToken(&restricted_token));
- ASSERT_TRUE(::IsTokenRestricted(restricted_token.Get()));
-
- DWORD length = 0;
- TOKEN_TYPE type;
- ASSERT_TRUE(::GetTokenInformation(restricted_token.Get(), ::TokenType, &type,
- sizeof(type), &length));
-
- ASSERT_EQ(type, TokenPrimary);
+ auto primary = base::win::AccessToken::FromToken(restricted_token.Get());
+ ASSERT_TRUE(primary);
+ EXPECT_TRUE(primary->IsRestricted());
+ EXPECT_FALSE(primary->IsImpersonation());
base::win::ScopedHandle impersonation_token;
ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
token.GetRestrictedTokenForImpersonation(&impersonation_token));
-
- ASSERT_TRUE(::IsTokenRestricted(impersonation_token.Get()));
-
- ASSERT_TRUE(::GetTokenInformation(impersonation_token.Get(), ::TokenType,
- &type, sizeof(type), &length));
-
- ASSERT_EQ(type, TokenImpersonation);
+ auto impersonation =
+ base::win::AccessToken::FromToken(impersonation_token.Get());
+ ASSERT_TRUE(impersonation);
+ ASSERT_TRUE(impersonation->IsRestricted());
+ ASSERT_TRUE(impersonation->IsImpersonation());
+ ASSERT_FALSE(impersonation->IsIdentification());
}
// Verifies that the token created has "Restricted" in its default dacl.
@@ -377,23 +303,17 @@
token.AddSidForDenyOnly(base::win::WellKnownSid::kWorld));
ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
token.GetRestrictedToken(&token_handle));
-
- ATL::CAccessToken restricted_token;
- restricted_token.Attach(token_handle.Take());
-
- ATL::CTokenGroups groups;
- ASSERT_TRUE(restricted_token.GetGroups(&groups));
-
- ATL::CSid::CSidArray sids;
- ATL::CAtlArray<DWORD> attributes;
- groups.GetSidsAndAttributes(&sids, &attributes);
-
- for (unsigned int i = 0; i < sids.GetCount(); i++) {
- if (ATL::Sids::World() == sids[i]) {
- ASSERT_EQ(static_cast<DWORD>(SE_GROUP_USE_FOR_DENY_ONLY),
- attributes[i] & SE_GROUP_USE_FOR_DENY_ONLY);
+ auto restricted_token = base::win::AccessToken::FromToken(token_handle.Get());
+ ASSERT_TRUE(restricted_token);
+ auto sid = base::win::Sid::FromKnownSid(base::win::WellKnownSid::kWorld);
+ bool found_sid = false;
+ for (const auto& group : restricted_token->Groups()) {
+ if (sid == group.GetSid()) {
+ ASSERT_TRUE(group.IsDenyOnly());
+ found_sid = true;
}
}
+ ASSERT_TRUE(found_sid);
}
// Tests the method "AddAllSidsForDenyOnly".
@@ -405,25 +325,18 @@
ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.AddAllSidsForDenyOnly({}));
ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
token.GetRestrictedToken(&token_handle));
-
- ATL::CAccessToken restricted_token;
- restricted_token.Attach(token_handle.Take());
-
- ATL::CTokenGroups groups;
- ASSERT_TRUE(restricted_token.GetGroups(&groups));
-
- ATL::CSid::CSidArray sids;
- ATL::CAtlArray<DWORD> attributes;
- groups.GetSidsAndAttributes(&sids, &attributes);
-
+ auto restricted_token = base::win::AccessToken::FromToken(token_handle.Get());
+ ASSERT_TRUE(restricted_token);
+ bool found_sid = false;
// Verify that all sids are really gone.
- for (unsigned int i = 0; i < sids.GetCount(); i++) {
- if ((attributes[i] & SE_GROUP_LOGON_ID) == 0 &&
- (attributes[i] & SE_GROUP_INTEGRITY) == 0) {
- ASSERT_EQ(static_cast<DWORD>(SE_GROUP_USE_FOR_DENY_ONLY),
- attributes[i] & SE_GROUP_USE_FOR_DENY_ONLY);
- }
+ for (const auto& group : restricted_token->Groups()) {
+ if (group.IsLogonId() || group.IsIntegrity())
+ continue;
+ ASSERT_TRUE(group.IsDenyOnly());
+ found_sid = true;
}
+ // Check we at least found one SID.
+ ASSERT_TRUE(found_sid);
}
// Tests the method "AddAllSidsForDenyOnly" using an exception list.
@@ -432,8 +345,9 @@
base::win::ScopedHandle token_handle;
std::vector<base::win::Sid> sids_exception;
- sids_exception.push_back(
- *base::win::Sid::FromKnownSid(base::win::WellKnownSid::kWorld));
+ auto sid = base::win::Sid::FromKnownSid(base::win::WellKnownSid::kWorld);
+ ASSERT_TRUE(sid);
+ sids_exception.push_back(sid->Clone());
ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.Init(nullptr));
ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
@@ -441,28 +355,23 @@
ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
token.GetRestrictedToken(&token_handle));
- ATL::CAccessToken restricted_token;
- restricted_token.Attach(token_handle.Take());
+ auto restricted_token = base::win::AccessToken::FromToken(token_handle.Get());
+ ASSERT_TRUE(restricted_token);
- ATL::CTokenGroups groups;
- ASSERT_TRUE(restricted_token.GetGroups(&groups));
-
- ATL::CSid::CSidArray sids;
- ATL::CAtlArray<DWORD> attributes;
- groups.GetSidsAndAttributes(&sids, &attributes);
-
+ bool found_sid = false;
// Verify that all sids are really gone.
- for (unsigned int i = 0; i < sids.GetCount(); i++) {
- if ((attributes[i] & SE_GROUP_LOGON_ID) == 0 &&
- (attributes[i] & SE_GROUP_INTEGRITY) == 0) {
- if (ATL::Sids::World() == sids[i]) {
- ASSERT_EQ(0u, attributes[i] & SE_GROUP_USE_FOR_DENY_ONLY);
- } else {
- ASSERT_EQ(static_cast<DWORD>(SE_GROUP_USE_FOR_DENY_ONLY),
- attributes[i] & SE_GROUP_USE_FOR_DENY_ONLY);
- }
+ for (const auto& group : restricted_token->Groups()) {
+ if (group.IsLogonId() || group.IsIntegrity())
+ continue;
+ if (sid == group.GetSid()) {
+ ASSERT_FALSE(group.IsDenyOnly());
+ // Check we at least found one SID.
+ found_sid = true;
+ } else {
+ ASSERT_TRUE(group.IsDenyOnly());
}
}
+ ASSERT_TRUE(found_sid);
}
// Tests test method AddOwnerSidForDenyOnly.
@@ -474,40 +383,15 @@
ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.AddUserSidForDenyOnly());
ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
token.GetRestrictedToken(&token_handle));
-
- ATL::CAccessToken restricted_token;
- restricted_token.Attach(token_handle.Take());
-
- ATL::CTokenGroups groups;
- ASSERT_TRUE(restricted_token.GetGroups(&groups));
-
- ATL::CSid::CSidArray sids;
- ATL::CAtlArray<DWORD> attributes;
- groups.GetSidsAndAttributes(&sids, &attributes);
-
- ATL::CSid user_sid;
- ASSERT_TRUE(restricted_token.GetUser(&user_sid));
-
- for (unsigned int i = 0; i < sids.GetCount(); ++i) {
- if (user_sid == sids[i]) {
- ASSERT_EQ(static_cast<DWORD>(SE_GROUP_USE_FOR_DENY_ONLY),
- attributes[i] & SE_GROUP_USE_FOR_DENY_ONLY);
- }
- }
+ auto restricted_token = base::win::AccessToken::FromToken(token_handle.Get());
+ ASSERT_TRUE(restricted_token);
+ EXPECT_TRUE(restricted_token->UserGroup().IsDenyOnly());
}
// Tests test method AddOwnerSidForDenyOnly with a custom effective token.
TEST(RestrictedTokenTest, DenyOwnerSidCustom) {
- // Get the current process token.
- HANDLE access_handle = INVALID_HANDLE_VALUE;
- ASSERT_TRUE(::OpenProcessToken(::GetCurrentProcess(), TOKEN_ALL_ACCESS,
- &access_handle));
-
- ASSERT_NE(INVALID_HANDLE_VALUE, access_handle);
-
- ATL::CAccessToken access_token;
- access_token.Attach(access_handle);
-
+ CAccessToken access_token;
+ ASSERT_TRUE(access_token.GetProcessToken(TOKEN_ALL_ACCESS));
RestrictedToken token;
base::win::ScopedHandle token_handle;
ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
@@ -515,26 +399,9 @@
ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.AddUserSidForDenyOnly());
ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
token.GetRestrictedToken(&token_handle));
-
- ATL::CAccessToken restricted_token;
- restricted_token.Attach(token_handle.Take());
-
- ATL::CTokenGroups groups;
- ASSERT_TRUE(restricted_token.GetGroups(&groups));
-
- ATL::CSid::CSidArray sids;
- ATL::CAtlArray<DWORD> attributes;
- groups.GetSidsAndAttributes(&sids, &attributes);
-
- ATL::CSid user_sid;
- ASSERT_TRUE(restricted_token.GetUser(&user_sid));
-
- for (unsigned int i = 0; i < sids.GetCount(); ++i) {
- if (user_sid == sids[i]) {
- ASSERT_EQ(static_cast<DWORD>(SE_GROUP_USE_FOR_DENY_ONLY),
- attributes[i] & SE_GROUP_USE_FOR_DENY_ONLY);
- }
- }
+ auto restricted_token = base::win::AccessToken::FromToken(token_handle.Get());
+ ASSERT_TRUE(restricted_token);
+ EXPECT_TRUE(restricted_token->UserGroup().IsDenyOnly());
}
// Tests the method DeleteAllPrivileges.
@@ -546,14 +413,9 @@
ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), token.DeleteAllPrivileges({}));
ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
token.GetRestrictedToken(&token_handle));
-
- ATL::CAccessToken restricted_token;
- restricted_token.Attach(token_handle.Take());
-
- ATL::CTokenPrivileges privileges;
- ASSERT_TRUE(restricted_token.GetPrivileges(&privileges));
-
- ASSERT_EQ(0u, privileges.GetCount());
+ auto restricted_token = base::win::AccessToken::FromToken(token_handle.Get());
+ ASSERT_TRUE(restricted_token);
+ EXPECT_TRUE(restricted_token->Privileges().empty());
}
// Tests the method DeleteAllPrivileges with an exception list.
@@ -570,22 +432,11 @@
ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
token.GetRestrictedToken(&token_handle));
- ATL::CAccessToken restricted_token;
- restricted_token.Attach(token_handle.Take());
-
- ATL::CTokenPrivileges privileges;
- ASSERT_TRUE(restricted_token.GetPrivileges(&privileges));
-
- ATL::CTokenPrivileges::CNames privilege_names;
- ATL::CTokenPrivileges::CAttributes privilege_name_attributes;
- privileges.GetNamesAndAttributes(&privilege_names,
- &privilege_name_attributes);
-
- ASSERT_EQ(1u, privileges.GetCount());
-
- for (unsigned int i = 0; i < privileges.GetCount(); ++i) {
- ASSERT_EQ(privilege_names[i], SE_CHANGE_NOTIFY_NAME);
- }
+ auto restricted_token = base::win::AccessToken::FromToken(token_handle.Get());
+ ASSERT_TRUE(restricted_token);
+ auto privileges = restricted_token->Privileges();
+ ASSERT_EQ(1U, privileges.size());
+ EXPECT_EQ(privileges[0].GetName(), SE_CHANGE_NOTIFY_NAME);
}
// Tests the method DeletePrivilege.
@@ -598,20 +449,10 @@
token.DeletePrivilege(SE_CHANGE_NOTIFY_NAME));
ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
token.GetRestrictedToken(&token_handle));
-
- ATL::CAccessToken restricted_token;
- restricted_token.Attach(token_handle.Take());
-
- ATL::CTokenPrivileges privileges;
- ASSERT_TRUE(restricted_token.GetPrivileges(&privileges));
-
- ATL::CTokenPrivileges::CNames privilege_names;
- ATL::CTokenPrivileges::CAttributes privilege_name_attributes;
- privileges.GetNamesAndAttributes(&privilege_names,
- &privilege_name_attributes);
-
- for (unsigned int i = 0; i < privileges.GetCount(); ++i) {
- ASSERT_NE(privilege_names[i], SE_CHANGE_NOTIFY_NAME);
+ auto restricted_token = base::win::AccessToken::FromToken(token_handle.Get());
+ ASSERT_TRUE(restricted_token);
+ for (const auto& priv : restricted_token->Privileges()) {
+ ASSERT_NE(priv.GetName(), SE_CHANGE_NOTIFY_NAME);
}
}
@@ -626,10 +467,9 @@
ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
token.GetRestrictedToken(&token_handle));
- ATL::CAccessToken restricted_token;
- restricted_token.Attach(token_handle.Take());
-
- CheckRestrictingSid(restricted_token, ATL::Sids::World(), 1);
+ auto restricted_token = base::win::AccessToken::FromToken(token_handle.Get());
+ ASSERT_TRUE(restricted_token);
+ CheckRestrictingSid(*restricted_token, base::win::WellKnownSid::kWorld, 1);
}
// Tests the method AddRestrictingSidCurrentUser.
@@ -643,26 +483,15 @@
ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
token.GetRestrictedToken(&token_handle));
- ATL::CAccessToken restricted_token;
- restricted_token.Attach(token_handle.Take());
- ATL::CSid user;
- restricted_token.GetUser(&user);
-
- CheckRestrictingSid(restricted_token, user, 1);
+ auto restricted_token = base::win::AccessToken::FromToken(token_handle.Get());
+ ASSERT_TRUE(restricted_token);
+ CheckRestrictingSid(*restricted_token, restricted_token->User(), 1);
}
// Tests the method AddRestrictingSidCurrentUser with a custom effective token.
TEST(RestrictedTokenTest, AddRestrictingSidCurrentUserCustom) {
- // Get the current process token.
- HANDLE access_handle = INVALID_HANDLE_VALUE;
- ASSERT_TRUE(::OpenProcessToken(::GetCurrentProcess(), TOKEN_ALL_ACCESS,
- &access_handle));
-
- ASSERT_NE(INVALID_HANDLE_VALUE, access_handle);
-
- ATL::CAccessToken access_token;
- access_token.Attach(access_handle);
-
+ CAccessToken access_token;
+ ASSERT_TRUE(access_token.GetProcessToken(TOKEN_ALL_ACCESS));
RestrictedToken token;
base::win::ScopedHandle token_handle;
ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
@@ -672,12 +501,9 @@
ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
token.GetRestrictedToken(&token_handle));
- ATL::CAccessToken restricted_token;
- restricted_token.Attach(token_handle.Take());
- ATL::CSid user;
- restricted_token.GetUser(&user);
-
- CheckRestrictingSid(restricted_token, user, 1);
+ auto restricted_token = base::win::AccessToken::FromToken(token_handle.Get());
+ ASSERT_TRUE(restricted_token);
+ CheckRestrictingSid(*restricted_token, restricted_token->User(), 1);
}
// Tests the method AddRestrictingSidLogonSession.
@@ -691,12 +517,15 @@
ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
token.GetRestrictedToken(&token_handle));
- ATL::CAccessToken restricted_token;
- restricted_token.Attach(token_handle.Take());
- ATL::CSid session;
- restricted_token.GetLogonSid(&session);
+ auto restricted_token = base::win::AccessToken::FromToken(token_handle.Get());
+ ASSERT_TRUE(restricted_token);
+ auto session = restricted_token->LogonId();
+ if (!session) {
+ ASSERT_EQ(static_cast<DWORD>(ERROR_NOT_FOUND), ::GetLastError());
+ return;
+ }
- CheckRestrictingSid(restricted_token, session, 1);
+ CheckRestrictingSid(*restricted_token, *session, 1);
}
// Tests adding a lot of restricting sids.
@@ -714,17 +543,9 @@
ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
token.GetRestrictedToken(&token_handle));
- ATL::CAccessToken restricted_token;
- restricted_token.Attach(token_handle.Take());
- ATL::CSid session;
- restricted_token.GetLogonSid(&session);
-
- std::vector<char> memory;
- ASSERT_TRUE(GetVariableTokenInformation(restricted_token.GetHandle(),
- ::TokenRestrictedSids, &memory));
- PTOKEN_GROUPS groups = reinterpret_cast<PTOKEN_GROUPS>(memory.data());
- ATL::CTokenGroups atl_groups(*groups);
- ASSERT_EQ(3u, atl_groups.GetCount());
+ auto restricted_token = base::win::AccessToken::FromToken(token_handle.Get());
+ ASSERT_TRUE(restricted_token);
+ ASSERT_EQ(3u, restricted_token->RestrictedSids().size());
}
// Tests the method "AddRestrictingSidAllSids".
@@ -738,27 +559,17 @@
ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS),
token.GetRestrictedToken(&token_handle));
- ATL::CAccessToken restricted_token;
- restricted_token.Attach(token_handle.Take());
-
- ATL::CTokenGroups groups;
- ASSERT_TRUE(restricted_token.GetGroups(&groups));
-
- ATL::CSid::CSidArray sids;
- ATL::CAtlArray<DWORD> attributes;
- groups.GetSidsAndAttributes(&sids, &attributes);
+ auto restricted_token = base::win::AccessToken::FromToken(token_handle.Get());
+ ASSERT_TRUE(restricted_token);
+ auto groups = restricted_token->Groups();
// Verify that all group sids are in the restricting sid list.
- for (unsigned int i = 0; i < sids.GetCount(); i++) {
- if ((attributes[i] & SE_GROUP_INTEGRITY) == 0) {
- CheckRestrictingSid(restricted_token, sids[i], -1);
- }
+ for (const auto& group : groups) {
+ if (!group.IsIntegrity())
+ CheckRestrictingSid(*restricted_token, group.GetSid(), -1);
}
- // Verify that the user is in the restricting sid list.
- ATL::CSid user;
- restricted_token.GetUser(&user);
- CheckRestrictingSid(restricted_token, user, -1);
+ CheckRestrictingSid(*restricted_token, restricted_token->User(), -1);
}
// Checks the error code when the object is initialized twice.
@@ -802,7 +613,7 @@
CreateLowBoxToken(nullptr, PRIMARY, &caps_no_capabilities, nullptr,
0, &token));
ASSERT_TRUE(token.IsValid());
- CheckLowBoxToken(token, ::TokenPrimary, &caps_no_capabilities);
+ CheckLowBoxToken(token, false, &caps_no_capabilities);
ASSERT_TRUE(ReplacePackageSidInDacl(token.Get(), SecurityObjectType::kKernel,
*package_sid, TOKEN_ALL_ACCESS));
@@ -812,7 +623,7 @@
CreateLowBoxToken(nullptr, IMPERSONATION, &caps_no_capabilities,
nullptr, 0, &token));
ASSERT_TRUE(token.IsValid());
- CheckLowBoxToken(token, ::TokenImpersonation, &caps_no_capabilities);
+ CheckLowBoxToken(token, true, &caps_no_capabilities);
auto capabilities = base::win::Sid::FromKnownCapabilityVector(
{base::win::WellKnownCapability::kInternetClient,
@@ -823,7 +634,7 @@
CreateLowBoxToken(nullptr, PRIMARY, &caps_with_capabilities,
nullptr, 0, &token));
ASSERT_TRUE(token.IsValid());
- CheckLowBoxToken(token, ::TokenPrimary, &caps_with_capabilities);
+ CheckLowBoxToken(token, false, &caps_with_capabilities);
RestrictedToken restricted_token;
base::win::ScopedHandle token_handle;
@@ -837,8 +648,8 @@
CreateLowBoxToken(token_handle.Get(), PRIMARY,
&caps_with_capabilities, nullptr, 0, &token));
ASSERT_TRUE(token.IsValid());
- CheckLowBoxToken(token, ::TokenPrimary, &caps_with_capabilities);
- CheckRestrictingSid(token.Get(), ATL::Sids::World(), 1);
+ CheckLowBoxToken(token, false, &caps_with_capabilities);
+ CheckRestrictingSid(token.Get(), base::win::WellKnownSid::kWorld, 1);
auto caps_for_handles_sid =
base::win::Sid::FromSddlString(L"S-1-15-2-1-2-3-4-5-6-8");
diff --git a/win/src/target_process.cc b/win/src/target_process.cc
index 5490cfb..d8fb758 100644
--- a/win/src/target_process.cc
+++ b/win/src/target_process.cc
@@ -15,6 +15,7 @@
#include "base/memory/free_deleter.h"
#include "base/numerics/safe_conversions.h"
+#include "base/win/access_token.h"
#include "base/win/security_util.h"
#include "base/win/startup_information.h"
#include "base/win/windows_version.h"
@@ -50,41 +51,16 @@
}
}
-absl::optional<base::win::Sid> GetTokenAppContainerSid(HANDLE token_handle) {
- std::vector<char> app_container_info(sizeof(TOKEN_APPCONTAINER_INFORMATION) +
- SECURITY_MAX_SID_SIZE);
- DWORD return_length;
-
- if (!::GetTokenInformation(
- token_handle, TokenAppContainerSid, app_container_info.data(),
- base::checked_cast<DWORD>(app_container_info.size()),
- &return_length)) {
- return absl::nullopt;
- }
-
- PTOKEN_APPCONTAINER_INFORMATION info =
- reinterpret_cast<PTOKEN_APPCONTAINER_INFORMATION>(
- app_container_info.data());
- if (!info->TokenAppContainer)
- return absl::nullopt;
- return base::win::Sid::FromPSID(info->TokenAppContainer);
-}
-
-absl::optional<base::win::Sid> GetProcessAppContainerSid(HANDLE process) {
- HANDLE token_handle;
- if (!::OpenProcessToken(process, TOKEN_QUERY, &token_handle))
- return absl::nullopt;
- base::win::ScopedHandle process_token(token_handle);
-
- return GetTokenAppContainerSid(process_token.Get());
-}
-
bool GetAppContainerImpersonationToken(
HANDLE process,
HANDLE initial_token,
const std::vector<base::win::Sid>& capabilities,
base::win::ScopedHandle* impersonation_token) {
- auto app_container_sid = GetProcessAppContainerSid(process);
+ absl::optional<base::win::AccessToken> token =
+ base::win::AccessToken::FromProcess(process);
+ if (!token)
+ return false;
+ auto app_container_sid = token->AppContainerSid();
if (!app_container_sid)
return false;
SecurityCapabilities security_caps(*app_container_sid, capabilities);
diff --git a/win/src/win_utils.cc b/win/src/win_utils.cc
index 1db7750..c8d0702 100644
--- a/win/src/win_utils.cc
+++ b/win/src/win_utils.cc
@@ -4,6 +4,8 @@
#include "sandbox/win/src/win_utils.h"
+#include <windows.h>
+
#include <psapi.h>
#include <stddef.h>
#include <stdint.h>
@@ -543,26 +545,6 @@
return base_address;
}
-DWORD GetTokenInformation(HANDLE token,
- TOKEN_INFORMATION_CLASS info_class,
- std::unique_ptr<BYTE[]>* buffer) {
- // Get the required buffer size.
- DWORD size = 0;
- ::GetTokenInformation(token, info_class, nullptr, 0, &size);
- if (!size) {
- return ::GetLastError();
- }
-
- auto temp_buffer = std::make_unique<BYTE[]>(size);
- if (!::GetTokenInformation(token, info_class, temp_buffer.get(), size,
- &size)) {
- return ::GetLastError();
- }
-
- *buffer = std::move(temp_buffer);
- return ERROR_SUCCESS;
-}
-
} // namespace sandbox
void ResolveNTFunctionPtr(const char* name, void* ptr) {
diff --git a/win/src/win_utils.h b/win/src/win_utils.h
index 8998853..6f54d20 100644
--- a/win/src/win_utils.h
+++ b/win/src/win_utils.h
@@ -5,8 +5,6 @@
#ifndef SANDBOX_WIN_SRC_WIN_UTILS_H_
#define SANDBOX_WIN_SRC_WIN_UTILS_H_
-#include <windows.h>
-
#include <stdlib.h>
#include <memory>
@@ -115,12 +113,6 @@
// the base address. This should only be called on new, suspended processes.
void* GetProcessBaseAddress(HANDLE process);
-// Calls GetTokenInformation with the desired |info_class| and returns a
-// |buffer| and the Win32 error code.
-DWORD GetTokenInformation(HANDLE token,
- TOKEN_INFORMATION_CLASS info_class,
- std::unique_ptr<BYTE[]>* buffer);
-
} // namespace sandbox
// Resolves a function name in NTDLL to a function pointer. The second parameter
diff --git a/win/tests/common/test_utils.cc b/win/tests/common/test_utils.cc
index 5aeffd7..a59ec9c 100644
--- a/win/tests/common/test_utils.cc
+++ b/win/tests/common/test_utils.cc
@@ -4,6 +4,8 @@
#include "sandbox/win/tests/common/test_utils.h"
+#include <windows.h>
+
#include <stddef.h>
#include <winioctl.h>
@@ -47,7 +49,7 @@
REPARSE_DATA_BUFFER* data = reinterpret_cast<REPARSE_DATA_BUFFER*>(buffer);
- data->ReparseTag = 0xa0000003;
+ data->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
memcpy(data->MountPointReparseBuffer.PathBuffer, target, size_target + 2);
data->MountPointReparseBuffer.SubstituteNameLength = size_target;
data->MountPointReparseBuffer.PrintNameOffset = size_target + 2;
@@ -67,7 +69,7 @@
bool DeleteReparsePoint(HANDLE source) {
DWORD returned;
REPARSE_DATA_BUFFER data = {0};
- data.ReparseTag = 0xa0000003;
+ data.ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
if (!DeviceIoControl(source, FSCTL_DELETE_REPARSE_POINT, &data, 8, NULL, 0,
&returned, NULL)) {
return false;
@@ -76,78 +78,4 @@
return true;
}
-SidAndAttributes::SidAndAttributes(const SID_AND_ATTRIBUTES& sid_and_attributes)
- : attributes_(sid_and_attributes.Attributes),
- sid_(*base::win::Sid::FromPSID(sid_and_attributes.Sid)) {}
-
-PSID SidAndAttributes::GetPSID() const {
- return sid_.GetPSID();
-}
-
-DWORD SidAndAttributes::GetAttributes() const {
- return attributes_;
-}
-
-absl::optional<base::win::Sid> GetTokenAppContainerSid(HANDLE token) {
- std::vector<char> app_container_info(sizeof(TOKEN_APPCONTAINER_INFORMATION) +
- SECURITY_MAX_SID_SIZE);
- DWORD return_length;
-
- if (!::GetTokenInformation(
- token, TokenAppContainerSid, app_container_info.data(),
- base::checked_cast<DWORD>(app_container_info.size()),
- &return_length)) {
- return absl::nullopt;
- }
-
- PTOKEN_APPCONTAINER_INFORMATION info =
- reinterpret_cast<PTOKEN_APPCONTAINER_INFORMATION>(
- app_container_info.data());
- if (!info->TokenAppContainer)
- return absl::nullopt;
- return base::win::Sid::FromPSID(info->TokenAppContainer);
-}
-
-absl::optional<std::vector<SidAndAttributes>> GetTokenGroups(
- HANDLE token,
- TOKEN_INFORMATION_CLASS information_class) {
- if (information_class != ::TokenCapabilities &&
- information_class != ::TokenGroups &&
- information_class != ::TokenRestrictedSids) {
- return absl::nullopt;
- }
-
- absl::optional<std::vector<char>> groups_buf =
- GetVariableTokenInformation(token, information_class);
- if (!groups_buf)
- return absl::nullopt;
-
- PTOKEN_GROUPS groups = reinterpret_cast<PTOKEN_GROUPS>(groups_buf->data());
- std::vector<SidAndAttributes> token_groups;
- token_groups.reserve(groups->GroupCount);
- for (DWORD index = 0; index < groups->GroupCount; ++index) {
- token_groups.push_back(groups->Groups[index]);
- }
-
- return token_groups;
-}
-
-absl::optional<std::vector<char>> GetVariableTokenInformation(
- HANDLE token,
- TOKEN_INFORMATION_CLASS information_class) {
- DWORD return_length;
- if (!::GetTokenInformation(token, information_class, nullptr, 0,
- &return_length)) {
- if (::GetLastError() != ERROR_INSUFFICIENT_BUFFER)
- return absl::nullopt;
- }
-
- std::vector<char> information(return_length);
- if (!::GetTokenInformation(token, information_class, information.data(),
- return_length, &return_length)) {
- return absl::nullopt;
- }
- return information;
-}
-
} // namespace sandbox
diff --git a/win/tests/common/test_utils.h b/win/tests/common/test_utils.h
index a9e62ac..f0322b6 100644
--- a/win/tests/common/test_utils.h
+++ b/win/tests/common/test_utils.h
@@ -5,13 +5,7 @@
#ifndef SANDBOX_WIN_TESTS_COMMON_TEST_UTILS_H_
#define SANDBOX_WIN_TESTS_COMMON_TEST_UTILS_H_
-#include <windows.h>
-
-#include <memory>
-#include <vector>
-
-#include "base/win/sid.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "base/win/windows_types.h"
namespace sandbox {
@@ -23,33 +17,6 @@
// succeeds, false otherwise.
bool DeleteReparsePoint(HANDLE source);
-// Class to hold a single Sid with attributes for a group list.
-class SidAndAttributes {
- public:
- SidAndAttributes(const SID_AND_ATTRIBUTES& sid_and_attributes);
-
- PSID GetPSID() const;
- DWORD GetAttributes() const;
-
- private:
- DWORD attributes_;
- base::win::Sid sid_;
-};
-
-// Get the App Container sid for a token.
-absl::optional<base::win::Sid> GetTokenAppContainerSid(HANDLE token);
-
-// Get the a list of groups from a token. |information_class| can be one of
-// TokenGroups, TokenRestrictedSids or TokenCapabilities.
-absl::optional<std::vector<SidAndAttributes>> GetTokenGroups(
- HANDLE token,
- TOKEN_INFORMATION_CLASS information_class);
-
-// Get a variable length property from a token.
-absl::optional<std::vector<char>> GetVariableTokenInformation(
- HANDLE token,
- TOKEN_INFORMATION_CLASS information_class);
-
} // namespace sandbox
#endif // SANDBOX_WIN_TESTS_COMMON_TEST_UTILS_H_