• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2022 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "base/win/access_control_list.h"
6 
7 #include <windows.h>
8 
9 #include <sddl.h>
10 
11 #include <string>
12 #include <vector>
13 
14 #include "base/check.h"
15 #include "base/strings/string_number_conversions_win.h"
16 #include "base/win/scoped_localalloc.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18 
19 namespace base::win {
20 
21 namespace {
22 
23 constexpr wchar_t kFromPACLTest[] = L"(D;;FX;;;SY)(A;;GA;;;WD)";
24 constexpr wchar_t kNullAcl[] = L"NO_ACCESS_CONTROL";
25 constexpr wchar_t kEvent[] = L"(A;;0x1f0003;;;WD)";
26 constexpr wchar_t kEventWithSystemInherit[] =
27     L"(D;OICI;DC;;;SY)(A;;0x1f0003;;;WD)";
28 constexpr wchar_t kEventSystemOnlyInherit[] = L"(D;OICI;DC;;;SY)";
29 constexpr wchar_t kEventReadControl[] = L"(A;;RC;;;WD)";
30 constexpr wchar_t kEventReadControlModify[] = L"(A;;DCRC;;;WD)";
31 constexpr wchar_t kUntrustedLabel[] = L"(ML;;;;;S-1-16-0)";
32 constexpr wchar_t kSystemLabel[] = L"(ML;;;;;SI)";
33 constexpr wchar_t kSystemLabelInherit[] = L"(ML;OICI;;;;SI)";
34 constexpr wchar_t kSystemLabelPolicy[] = L"(ML;;NWNRNX;;;SI)";
35 constexpr wchar_t kSystemLabelInheritPolicy[] = L"(ML;OICI;NWNRNX;;;SI)";
36 constexpr wchar_t kDaclPrefix[] = L"D:";
37 constexpr wchar_t kSaclPrefix[] = L"S:";
38 
ConvertSddlToAcl(const wchar_t * sddl)39 std::vector<char> ConvertSddlToAcl(const wchar_t* sddl) {
40   std::wstring sddl_dacl = kDaclPrefix;
41   sddl_dacl += sddl;
42   PSECURITY_DESCRIPTOR sd = nullptr;
43   CHECK(::ConvertStringSecurityDescriptorToSecurityDescriptor(
44       sddl_dacl.c_str(), SDDL_REVISION_1, &sd, nullptr));
45   auto sd_ptr = TakeLocalAlloc(sd);
46   CHECK(sd_ptr);
47   BOOL present = FALSE;
48   BOOL defaulted = FALSE;
49   PACL dacl = nullptr;
50   CHECK(::GetSecurityDescriptorDacl(sd_ptr.get(), &present, &dacl, &defaulted));
51   CHECK(present);
52   char* dacl_ptr = reinterpret_cast<char*>(dacl);
53   return std::vector<char>(dacl_ptr, dacl_ptr + dacl->AclSize);
54 }
55 
ConvertAclToSddl(const AccessControlList & acl,bool label=false)56 std::wstring ConvertAclToSddl(const AccessControlList& acl,
57                               bool label = false) {
58   SECURITY_DESCRIPTOR sd = {};
59   CHECK(::InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION));
60   if (label) {
61     CHECK(::SetSecurityDescriptorSacl(&sd, TRUE, acl.get(), FALSE));
62   } else {
63     CHECK(::SetSecurityDescriptorDacl(&sd, TRUE, acl.get(), FALSE));
64   }
65   LPWSTR sddl_str = nullptr;
66   CHECK(::ConvertSecurityDescriptorToStringSecurityDescriptor(
67       &sd, SDDL_REVISION_1,
68       label ? LABEL_SECURITY_INFORMATION : DACL_SECURITY_INFORMATION, &sddl_str,
69       nullptr));
70   auto sddl_str_ptr = TakeLocalAlloc(sddl_str);
71   std::wstring ret = sddl_str_ptr.get();
72   CHECK(ret.substr(0, 2) == (label ? kSaclPrefix : kDaclPrefix));
73   return ret.substr(2);
74 }
75 }  // namespace
76 
TEST(AccessControlListTest,FromPACL)77 TEST(AccessControlListTest, FromPACL) {
78   auto null_acl = AccessControlList::FromPACL(nullptr);
79   ASSERT_TRUE(null_acl);
80   EXPECT_TRUE(null_acl->is_null());
81   EXPECT_EQ(null_acl->get(), nullptr);
82   EXPECT_EQ(ConvertAclToSddl(*null_acl), kNullAcl);
83 
84   ACL dummy_acl = {};
85   auto invalid_acl = AccessControlList::FromPACL(&dummy_acl);
86   DWORD error = ::GetLastError();
87   EXPECT_FALSE(invalid_acl);
88   EXPECT_EQ(error, DWORD{ERROR_INVALID_ACL});
89 
90   std::vector<char> compare_acl = ConvertSddlToAcl(kFromPACLTest);
91   ASSERT_FALSE(compare_acl.empty());
92   auto test_acl =
93       AccessControlList::FromPACL(reinterpret_cast<ACL*>(compare_acl.data()));
94   ASSERT_TRUE(test_acl);
95   EXPECT_EQ(ConvertAclToSddl(*test_acl), kFromPACLTest);
96 }
97 
TEST(AccessControlListTest,FromMandatoryLabel)98 TEST(AccessControlListTest, FromMandatoryLabel) {
99   auto acl = AccessControlList::FromMandatoryLabel(0, 0, 0);
100   ASSERT_TRUE(acl);
101   EXPECT_EQ(ConvertAclToSddl(*acl, true), kUntrustedLabel);
102   acl = AccessControlList::FromMandatoryLabel(SECURITY_MANDATORY_SYSTEM_RID, 0,
103                                               0);
104   ASSERT_TRUE(acl);
105   EXPECT_EQ(ConvertAclToSddl(*acl, true), kSystemLabel);
106   acl = AccessControlList::FromMandatoryLabel(
107       SECURITY_MANDATORY_SYSTEM_RID, OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE,
108       0);
109   ASSERT_TRUE(acl);
110   EXPECT_EQ(ConvertAclToSddl(*acl, true), kSystemLabelInherit);
111   acl = AccessControlList::FromMandatoryLabel(
112       SECURITY_MANDATORY_SYSTEM_RID, 0,
113       SYSTEM_MANDATORY_LABEL_NO_WRITE_UP | SYSTEM_MANDATORY_LABEL_NO_READ_UP |
114           SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP);
115   ASSERT_TRUE(acl);
116   EXPECT_EQ(ConvertAclToSddl(*acl, true), kSystemLabelPolicy);
117   acl = AccessControlList::FromMandatoryLabel(
118       SECURITY_MANDATORY_SYSTEM_RID, OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE,
119       SYSTEM_MANDATORY_LABEL_NO_WRITE_UP | SYSTEM_MANDATORY_LABEL_NO_READ_UP |
120           SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP);
121   ASSERT_TRUE(acl);
122   EXPECT_EQ(ConvertAclToSddl(*acl, true), kSystemLabelInheritPolicy);
123 }
124 
TEST(AccessControlListTest,Empty)125 TEST(AccessControlListTest, Empty) {
126   AccessControlList acl;
127   EXPECT_FALSE(acl.is_null());
128   ACL* acl_ptr = acl.get();
129   ASSERT_NE(acl_ptr, nullptr);
130   EXPECT_EQ(acl_ptr->AceCount, 0);
131   EXPECT_EQ(acl_ptr->AclSize, sizeof(ACL));
132   EXPECT_EQ(acl_ptr->AclRevision, ACL_REVISION);
133   EXPECT_TRUE(ConvertAclToSddl(acl).empty());
134   AccessControlList acl_clone = acl.Clone();
135   EXPECT_NE(acl.get(), acl_clone.get());
136   EXPECT_TRUE(ConvertAclToSddl(acl_clone).empty());
137 }
138 
TEST(AccessControlListTest,ExplicitAccessEntry)139 TEST(AccessControlListTest, ExplicitAccessEntry) {
140   constexpr DWORD FakeAccess = 0x12345678U;
141   constexpr DWORD FakeInherit = 0x87654321U;
142   Sid sid(WellKnownSid::kWorld);
143   ExplicitAccessEntry ace(sid, SecurityAccessMode::kGrant, FakeAccess,
144                           FakeInherit);
145   EXPECT_EQ(sid, ace.sid());
146   EXPECT_EQ(SecurityAccessMode::kGrant, ace.mode());
147   EXPECT_EQ(FakeAccess, ace.access_mask());
148   EXPECT_EQ(FakeInherit, ace.inheritance());
149   ExplicitAccessEntry ace_clone = ace.Clone();
150   EXPECT_EQ(ace.sid(), ace_clone.sid());
151   EXPECT_NE(ace.sid().GetPSID(), ace_clone.sid().GetPSID());
152   EXPECT_EQ(ace.mode(), ace_clone.mode());
153   EXPECT_EQ(ace.access_mask(), ace_clone.access_mask());
154   EXPECT_EQ(ace.inheritance(), ace_clone.inheritance());
155   ExplicitAccessEntry ace_known(WellKnownSid::kSelf,
156                                 SecurityAccessMode::kRevoke, ~FakeAccess,
157                                 ~FakeInherit);
158   EXPECT_EQ(Sid(WellKnownSid::kSelf), ace_known.sid());
159   EXPECT_EQ(SecurityAccessMode::kRevoke, ace_known.mode());
160   EXPECT_EQ(~FakeAccess, ace_known.access_mask());
161   EXPECT_EQ(~FakeInherit, ace_known.inheritance());
162 }
163 
TEST(AccessControlListTest,SetEntries)164 TEST(AccessControlListTest, SetEntries) {
165   AccessControlList acl;
166   std::vector<ExplicitAccessEntry> ace_list;
167   EXPECT_TRUE(acl.SetEntries(ace_list));
168   EXPECT_EQ(ConvertAclToSddl(acl), L"");
169   ace_list.emplace_back(Sid(WellKnownSid::kWorld), SecurityAccessMode::kGrant,
170                         EVENT_ALL_ACCESS, 0);
171   EXPECT_TRUE(acl.SetEntries(ace_list));
172   EXPECT_EQ(ConvertAclToSddl(acl), kEvent);
173   ace_list.emplace_back(Sid(WellKnownSid::kLocalSystem),
174                         SecurityAccessMode::kDeny, EVENT_MODIFY_STATE,
175                         CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE);
176   EXPECT_TRUE(acl.SetEntries(ace_list));
177   EXPECT_EQ(ConvertAclToSddl(acl), kEventWithSystemInherit);
178   ace_list.emplace_back(Sid(WellKnownSid::kWorld), SecurityAccessMode::kRevoke,
179                         EVENT_MODIFY_STATE, 0);
180   EXPECT_TRUE(acl.SetEntries(ace_list));
181   EXPECT_EQ(ConvertAclToSddl(acl), kEventSystemOnlyInherit);
182   AccessControlList acl_clone = acl.Clone();
183   EXPECT_NE(acl.get(), acl_clone.get());
184   EXPECT_EQ(ConvertAclToSddl(acl_clone), kEventSystemOnlyInherit);
185 }
186 
TEST(AccessControlListTest,SetEntry)187 TEST(AccessControlListTest, SetEntry) {
188   AccessControlList acl;
189   EXPECT_TRUE(acl.SetEntry(Sid(WellKnownSid::kWorld),
190                            SecurityAccessMode::kGrant, READ_CONTROL, 0));
191   EXPECT_EQ(ConvertAclToSddl(acl), kEventReadControl);
192   EXPECT_TRUE(acl.SetEntry(Sid(WellKnownSid::kWorld),
193                            SecurityAccessMode::kGrant, EVENT_MODIFY_STATE, 0));
194   EXPECT_EQ(ConvertAclToSddl(acl), kEventReadControlModify);
195   EXPECT_TRUE(acl.SetEntry(Sid(WellKnownSid::kWorld), SecurityAccessMode::kSet,
196                            EVENT_ALL_ACCESS, 0));
197   EXPECT_EQ(ConvertAclToSddl(acl), kEvent);
198   EXPECT_TRUE(acl.SetEntry(Sid(WellKnownSid::kLocalSystem),
199                            SecurityAccessMode::kDeny, EVENT_MODIFY_STATE,
200                            CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE));
201   EXPECT_EQ(ConvertAclToSddl(acl), kEventWithSystemInherit);
202   EXPECT_TRUE(acl.SetEntry(Sid(WellKnownSid::kWorld),
203                            SecurityAccessMode::kRevoke, EVENT_ALL_ACCESS, 0));
204   EXPECT_EQ(ConvertAclToSddl(acl), kEventSystemOnlyInherit);
205 }
206 
TEST(AccessControlListTest,SetEntriesError)207 TEST(AccessControlListTest, SetEntriesError) {
208   AccessControlList acl;
209   std::vector<ExplicitAccessEntry> ace_list;
210   ace_list.emplace_back(Sid(WellKnownSid::kWorld), SecurityAccessMode::kGrant,
211                         EVENT_ALL_ACCESS, 0);
212   EXPECT_TRUE(acl.SetEntries(ace_list));
213   EXPECT_EQ(ConvertAclToSddl(acl), kEvent);
214   // ACL has a maximum capacity of 2^16-1 bytes or 2^16-1 ACEs. Force a fail.
215   while (ace_list.size() < 0x10000) {
216     auto sid =
217         Sid::FromSddlString(L"S-1-5-1234-" + NumberToWString(ace_list.size()));
218     ASSERT_TRUE(sid);
219     ace_list.emplace_back(*sid, SecurityAccessMode::kGrant, GENERIC_ALL, 0);
220   }
221   ::SetLastError(0);
222   bool result = acl.SetEntries(ace_list);
223   DWORD error = ::GetLastError();
224   EXPECT_FALSE(result);
225   EXPECT_EQ(error, DWORD{ERROR_INVALID_PARAMETER});
226 }
227 
TEST(AccessControlListTest,Clear)228 TEST(AccessControlListTest, Clear) {
229   AccessControlList acl;
230   EXPECT_TRUE(acl.SetEntry(Sid(WellKnownSid::kWorld),
231                            SecurityAccessMode::kGrant, READ_CONTROL, 0));
232   EXPECT_EQ(acl.get()->AceCount, 1);
233   acl.Clear();
234   ASSERT_NE(acl.get(), nullptr);
235   EXPECT_EQ(acl.get()->AceCount, 0);
236 }
237 
238 }  // namespace base::win
239