Commit eba36b24 authored by James Forshaw's avatar James Forshaw Committed by Commit Bot

Reland "Implemented changes to Sid class for AC support."

This is a reland of 251a3311, possible now
that the Creators Update SDK (10.0.15036) is now required when building
Chrome.

Original change's description:
> Implemented changes to Sid class for AC support.
> 
> This CL implements changes to the sandbox Sid class to support the creation
> of Capability Sid objects. It also contains a few refactoring efforts to
> cleanup up older code.
> 
> Bug: 760977
> Cq-Include-Trybots: master.tryserver.chromium.win:win10_chromium_x64_rel_ng
> Change-Id: Id9c05b8017abb81896c1bc30f23599441812d1fd
> Reviewed-on: https://chromium-review.googlesource.com/649026
> Commit-Queue: James Forshaw <forshaw@chromium.org>
> Reviewed-by: Will Harris <wfh@chromium.org>
> Reviewed-by: Penny MacNeil <pennymac@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#501229}

Bug: 760977
Change-Id: I4d3f61190f8f34bc638cf2c48646bfc66a6508af
Cq-Include-Trybots: master.tryserver.chromium.win:win10_chromium_x64_rel_ng
Reviewed-on: https://chromium-review.googlesource.com/691114Reviewed-by: default avatarWill Harris <wfh@chromium.org>
Commit-Queue: Bruce Dawson <brucedawson@chromium.org>
Cr-Commit-Position: refs/heads/master@{#505430}
parent ced8acfc
......@@ -48,8 +48,7 @@ bool AddSidToDacl(const Sid& sid, ACL* old_dacl, ACCESS_MODE access_mode,
new_access.Trustee.pMultipleTrustee = NULL;
new_access.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE;
new_access.Trustee.TrusteeForm = TRUSTEE_IS_SID;
new_access.Trustee.ptstrName = reinterpret_cast<LPWSTR>(
const_cast<SID*>(sid.GetPSID()));
new_access.Trustee.ptstrName = reinterpret_cast<LPWSTR>(sid.GetPSID());
if (ERROR_SUCCESS != ::SetEntriesInAcl(1, &new_access, old_dacl, new_dacl))
return false;
......
......@@ -92,8 +92,7 @@ DWORD RestrictedToken::GetRestrictedToken(
for (unsigned int i = 0; i < sids_for_deny_only_.size() ; ++i) {
deny_only_array[i].Attributes = SE_GROUP_USE_FOR_DENY_ONLY;
deny_only_array[i].Sid =
const_cast<SID*>(sids_for_deny_only_[i].GetPSID());
deny_only_array[i].Sid = sids_for_deny_only_[i].GetPSID();
}
}
......@@ -103,8 +102,7 @@ DWORD RestrictedToken::GetRestrictedToken(
for (unsigned int i = 0; i < restrict_size; ++i) {
sids_to_restrict_array[i].Attributes = 0;
sids_to_restrict_array[i].Sid =
const_cast<SID*>(sids_to_restrict_[i].GetPSID());
sids_to_restrict_array[i].Sid = sids_to_restrict_[i].GetPSID();
}
}
......@@ -242,8 +240,8 @@ DWORD RestrictedToken::AddAllSidsForDenyOnly(std::vector<Sid> *exceptions) {
bool should_ignore = false;
if (exceptions) {
for (unsigned int j = 0; j < exceptions->size(); ++j) {
if (::EqualSid(const_cast<SID*>((*exceptions)[j].GetPSID()),
token_groups->Groups[i].Sid)) {
if (::EqualSid((*exceptions)[j].GetPSID(),
token_groups->Groups[i].Sid)) {
should_ignore = true;
break;
}
......
......@@ -4,23 +4,123 @@
#include "sandbox/win/src/sid.h"
#include <sddl.h>
#include "base/logging.h"
#include "base/win/windows_version.h"
namespace sandbox {
Sid::Sid(const SID *sid) {
::CopySid(SECURITY_MAX_SID_SIZE, sid_, const_cast<SID*>(sid));
namespace {
typedef decltype(
::DeriveCapabilitySidsFromName) DeriveCapabilitySidsFromNameFunc;
class SidArray {
public:
SidArray() : count_(0), sids_(nullptr) {}
~SidArray() {
if (sids_) {
for (size_t index = 0; index < count_; ++index) {
::LocalFree(sids_[index]);
}
::LocalFree(sids_);
}
}
DWORD count() { return count_; }
PSID* sids() { return sids_; }
PDWORD count_ptr() { return &count_; }
PSID** sids_ptr() { return &sids_; }
private:
DWORD count_;
PSID* sids_;
};
const wchar_t* WellKnownCapabilityToName(WellKnownCapabilities capability) {
switch (capability) {
case kInternetClient:
return L"internetClient";
case kInternetClientServer:
return L"internetClientServer";
case kRegistryRead:
return L"registryRead";
case kLpacCryptoServices:
return L"lpacCryptoServices";
case kEnterpriseAuthentication:
return L"enterpriseAuthentication";
case kPrivateNetworkClientServer:
return L"privateNetworkClientServer";
default:
return nullptr;
}
}
} // namespace
Sid::Sid() : sid_() {}
Sid::Sid(PSID sid) : sid_() {
::CopySid(SECURITY_MAX_SID_SIZE, sid_, sid);
}
Sid::Sid(const SID* sid) : sid_() {
::CopySid(SECURITY_MAX_SID_SIZE, sid_, const_cast<SID*>(sid));
}
Sid::Sid(WELL_KNOWN_SID_TYPE type) {
DWORD size_sid = SECURITY_MAX_SID_SIZE;
BOOL result = ::CreateWellKnownSid(type, NULL, sid_, &size_sid);
BOOL result = ::CreateWellKnownSid(type, nullptr, sid_, &size_sid);
DCHECK(result);
(void)result;
}
const SID *Sid::GetPSID() const {
return reinterpret_cast<SID*>(const_cast<BYTE*>(sid_));
Sid Sid::FromKnownCapability(WellKnownCapabilities capability) {
return Sid::FromNamedCapability(WellKnownCapabilityToName(capability));
}
Sid Sid::FromNamedCapability(const wchar_t* capability_name) {
DeriveCapabilitySidsFromNameFunc* derive_capablity_sids =
(DeriveCapabilitySidsFromNameFunc*)GetProcAddress(
GetModuleHandle(L"kernelbase"), "DeriveCapabilitySidsFromName");
if (!derive_capablity_sids)
return Sid();
if (capability_name == nullptr || ::wcslen(capability_name) == 0)
return Sid();
SidArray capability_group_sids;
SidArray capability_sids;
if (!derive_capablity_sids(capability_name, capability_group_sids.sids_ptr(),
capability_group_sids.count_ptr(),
capability_sids.sids_ptr(),
capability_sids.count_ptr())) {
return Sid();
}
if (capability_sids.count() < 1)
return Sid();
return Sid(capability_sids.sids()[0]);
}
Sid Sid::FromSddlString(const wchar_t* sddl_sid) {
PSID converted_sid;
if (!::ConvertStringSidToSid(sddl_sid, &converted_sid))
return Sid();
return Sid(converted_sid);
}
PSID Sid::GetPSID() const {
return const_cast<BYTE*>(sid_);
}
bool Sid::IsValid() const {
return !!::IsValidSid(GetPSID());
}
} // namespace sandbox
......@@ -9,18 +9,41 @@
namespace sandbox {
enum WellKnownCapabilities {
kInternetClient,
kInternetClientServer,
kRegistryRead,
kLpacCryptoServices,
kEnterpriseAuthentication,
kPrivateNetworkClientServer,
kMaxWellKnownCapability
};
// This class is used to hold and generate SIDS.
class Sid {
public:
// Constructors initializing the object with the SID passed.
// This is a converting constructor. It is not explicit.
Sid(const SID *sid);
Sid(PSID sid);
Sid(const SID* sid);
Sid(WELL_KNOWN_SID_TYPE type);
// Create a Sid from an AppContainer capability name. The name can be
// completely arbitrary.
static Sid FromNamedCapability(const wchar_t* capability_name);
// Create a Sid from a known capability enumeration value.
static Sid FromKnownCapability(WellKnownCapabilities capability);
// Create a Sid from a SDDL format string, such as S-1-1-0.
static Sid FromSddlString(const wchar_t* sddl_sid);
// Returns sid_.
const SID *GetPSID() const;
PSID GetPSID() const;
// Gets whether the sid is valid.
bool IsValid() const;
private:
Sid();
BYTE sid_[SECURITY_MAX_SID_SIZE];
};
......
......@@ -7,65 +7,129 @@
#define _ATL_NO_EXCEPTIONS
#include <atlbase.h>
#include <atlsecurity.h>
#include <sddl.h>
#include "base/win/windows_version.h"
#include "sandbox/win/src/sid.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace sandbox {
// Calls ::EqualSid. This function exists only to simplify the calls to
// ::EqualSid by removing the need to cast the input params.
BOOL EqualSid(const SID *sid1, const SID *sid2) {
return ::EqualSid(const_cast<SID*>(sid1), const_cast<SID*>(sid2));
namespace {
bool EqualSid(const Sid& sid, const ATL::CSid& compare_sid) {
if (!sid.IsValid())
return false;
return !!::EqualSid(sid.GetPSID(), const_cast<SID*>(compare_sid.GetPSID()));
}
bool EqualSid(const Sid& sid, const wchar_t* sddl_sid) {
PSID compare_sid;
if (!sid.IsValid())
return false;
if (!::ConvertStringSidToSid(sddl_sid, &compare_sid))
return false;
bool equal = !!::EqualSid(sid.GetPSID(), compare_sid);
::LocalFree(compare_sid);
return equal;
}
struct CapabilityTestEntry {
WellKnownCapabilities capability_;
const wchar_t* capability_name_;
const wchar_t* sddl_sid_;
};
}
// Tests the creation if a Sid
// Tests the creation of a Sid.
TEST(SidTest, Constructors) {
ATL::CSid sid_world = ATL::Sids::World();
SID *sid_world_pointer = const_cast<SID*>(sid_world.GetPSID());
PSID sid_world_pointer = const_cast<SID*>(sid_world.GetPSID());
// Check the SID* constructor
// Check the SID* constructor.
Sid sid_sid_star(sid_world_pointer);
ASSERT_TRUE(EqualSid(sid_world_pointer, sid_sid_star.GetPSID()));
ASSERT_TRUE(EqualSid(sid_sid_star, sid_world));
// Check the copy constructor
// Check the copy constructor.
Sid sid_copy(sid_sid_star);
ASSERT_TRUE(EqualSid(sid_world_pointer, sid_copy.GetPSID()));
ASSERT_TRUE(EqualSid(sid_copy, sid_world));
Sid sid_sddl = Sid::FromSddlString(L"S-1-1-0");
ASSERT_TRUE(sid_sddl.IsValid());
ASSERT_TRUE(EqualSid(sid_sddl, sid_world));
Sid sid_sddl_invalid = Sid::FromSddlString(L"X-1-1-0");
ASSERT_FALSE(sid_sddl_invalid.IsValid());
Sid sid_sddl_empty = Sid::FromSddlString(L"");
ASSERT_FALSE(sid_sddl_empty.IsValid());
// Note that the WELL_KNOWN_SID_TYPE constructor is tested in the GetPSID
// test.
// test. AppContainer related constructors are tested in AppContainer.
}
// Tests the method GetPSID
TEST(SidTest, GetPSID) {
// Check for non-null result;
ASSERT_NE(static_cast<SID*>(NULL), Sid(::WinLocalSid).GetPSID());
ASSERT_NE(static_cast<SID*>(NULL), Sid(::WinCreatorOwnerSid).GetPSID());
ASSERT_NE(static_cast<SID*>(NULL), Sid(::WinBatchSid).GetPSID());
ASSERT_NE(nullptr, Sid(::WinLocalSid).GetPSID());
ASSERT_NE(nullptr, Sid(::WinCreatorOwnerSid).GetPSID());
ASSERT_NE(nullptr, Sid(::WinBatchSid).GetPSID());
ASSERT_TRUE(EqualSid(Sid(::WinNullSid).GetPSID(),
ATL::Sids::Null().GetPSID()));
ASSERT_TRUE(EqualSid(Sid(::WinNullSid), ATL::Sids::Null()));
ASSERT_TRUE(EqualSid(Sid(::WinWorldSid).GetPSID(),
ATL::Sids::World().GetPSID()));
ASSERT_TRUE(EqualSid(Sid(::WinWorldSid), ATL::Sids::World()));
ASSERT_TRUE(EqualSid(Sid(::WinDialupSid).GetPSID(),
ATL::Sids::Dialup().GetPSID()));
ASSERT_TRUE(EqualSid(Sid(::WinDialupSid), ATL::Sids::Dialup()));
ASSERT_TRUE(EqualSid(Sid(::WinNetworkSid).GetPSID(),
ATL::Sids::Network().GetPSID()));
ASSERT_TRUE(EqualSid(Sid(::WinNetworkSid), ATL::Sids::Network()));
ASSERT_TRUE(EqualSid(Sid(::WinBuiltinAdministratorsSid).GetPSID(),
ATL::Sids::Admins().GetPSID()));
ASSERT_TRUE(
EqualSid(Sid(::WinBuiltinAdministratorsSid), ATL::Sids::Admins()));
ASSERT_TRUE(EqualSid(Sid(::WinBuiltinUsersSid).GetPSID(),
ATL::Sids::Users().GetPSID()));
ASSERT_TRUE(EqualSid(Sid(::WinBuiltinUsersSid), ATL::Sids::Users()));
ASSERT_TRUE(EqualSid(Sid(::WinBuiltinGuestsSid).GetPSID(),
ATL::Sids::Guests().GetPSID()));
ASSERT_TRUE(EqualSid(Sid(::WinBuiltinGuestsSid), ATL::Sids::Guests()));
ASSERT_TRUE(EqualSid(Sid(::WinProxySid), ATL::Sids::Proxy()));
}
ASSERT_TRUE(EqualSid(Sid(::WinProxySid).GetPSID(),
ATL::Sids::Proxy().GetPSID()));
TEST(SidTest, AppContainer) {
const CapabilityTestEntry capabilities[] = {
{kInternetClient, L"internetClient", L"S-1-15-3-1"},
{kInternetClientServer, L"internetClientServer", L"S-1-15-3-2"},
{kRegistryRead, L"registryRead",
L"S-1-15-3-1024-1065365936-1281604716-3511738428-"
"1654721687-432734479-3232135806-4053264122-3456934681"},
{kLpacCryptoServices, L"lpacCryptoServices",
L"S-1-15-3-1024-3203351429-2120443784-2872670797-"
"1918958302-2829055647-4275794519-765664414-2751773334"},
{kEnterpriseAuthentication, L"enterpriseAuthentication", L"S-1-15-3-8"},
{kPrivateNetworkClientServer, L"privateNetworkClientServer",
L"S-1-15-3-3"}};
// No support for AppContainer less than Win10 RS2.
if (base::win::GetVersion() < base::win::VERSION_WIN10_RS2)
return;
Sid sid_nullptr = Sid::FromNamedCapability(nullptr);
EXPECT_FALSE(sid_nullptr.IsValid());
Sid sid_empty = Sid::FromNamedCapability(L"");
EXPECT_FALSE(sid_empty.IsValid());
WellKnownCapabilities invalid_well_known =
static_cast<WellKnownCapabilities>(kMaxWellKnownCapability + 1);
Sid sid_invalid_well_known = Sid::FromKnownCapability(invalid_well_known);
EXPECT_FALSE(sid_invalid_well_known.IsValid());
for (auto capability : capabilities) {
EXPECT_TRUE(EqualSid(Sid::FromNamedCapability(capability.capability_name_),
capability.sddl_sid_))
<< "Named Capability: " << capability.sddl_sid_;
EXPECT_TRUE(EqualSid(Sid::FromKnownCapability(capability.capability_),
capability.sddl_sid_))
<< "Known Capability: " << capability.sddl_sid_;
}
}
} // namespace sandbox
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment