• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2021 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/security_util.h"
6 
7 // clang-format off
8 #include <windows.h>  // Must be in front of other Windows header files.
9 // clang-format on
10 
11 #include <aclapi.h>
12 #include <sddl.h>
13 
14 #include <utility>
15 
16 #include "base/files/file_util.h"
17 #include "base/files/scoped_temp_dir.h"
18 #include "base/strings/string_number_conversions_win.h"
19 #include "base/test/test_file_util.h"
20 #include "base/win/scoped_handle.h"
21 #include "base/win/scoped_localalloc.h"
22 #include "base/win/sid.h"
23 #include "testing/gtest/include/gtest/gtest.h"
24 
25 namespace base {
26 namespace win {
27 
28 namespace {
29 
30 constexpr wchar_t kBaseDacl[] = L"D:P(A;;FA;;;WD)";
31 constexpr wchar_t kTest1Dacl[] = L"D:PAI(A;;FR;;;AU)(A;;FA;;;WD)";
32 constexpr wchar_t kTest2Dacl[] = L"D:PAI(A;;FA;;;BA)(A;;FA;;;AU)(A;;FA;;;WD)";
33 constexpr wchar_t kTest1DenyDacl[] = L"D:PAI(D;;FR;;;LG)(A;;FA;;;WD)";
34 constexpr wchar_t kTest1DaclNoInherit[] = L"D:P(A;;FR;;;AU)(A;;FA;;;WD)";
35 constexpr wchar_t kTest2DaclNoInherit[] =
36     L"D:P(A;;FA;;;BA)(A;;FA;;;AU)(A;;FA;;;WD)";
37 
38 constexpr wchar_t kBaseDirDacl[] = L"D:P(A;OICI;FA;;;WD)";
39 constexpr wchar_t kTest1InheritedDacl[] = L"D:(A;ID;FA;;;WD)";
40 constexpr wchar_t kBaseDir2Dacl[] = L"D:PAI(A;OICI;FR;;;AU)(A;OICI;FA;;;WD)";
41 constexpr wchar_t kTest2InheritedDacl[] = L"D:AI(A;ID;FR;;;AU)(A;ID;FA;;;WD)";
42 constexpr wchar_t kBaseDir2DaclNoInherit[] =
43     L"D:P(A;OICI;FR;;;AU)(A;OICI;FA;;;WD)";
44 constexpr wchar_t kTest2InheritedDaclNoInherit[] = L"D:P(A;;FA;;;WD)";
45 constexpr wchar_t kTest3InheritedDacl[] = L"D:(A;ID;FR;;;AU)(A;ID;FA;;;WD)";
46 
47 constexpr wchar_t kNoWriteDacDacl[] = L"D:(D;;WD;;;OW)(A;;FRSD;;;WD)";
48 
49 constexpr wchar_t kAuthenticatedUsersSid[] = L"AU";
50 constexpr wchar_t kLocalGuestSid[] = L"LG";
51 
52 }  // namespace
53 
TEST(SecurityUtilTest,GrantAccessToPathErrorCase)54 TEST(SecurityUtilTest, GrantAccessToPathErrorCase) {
55   ScopedTempDir temp_dir;
56   auto sids = Sid::FromSddlStringVector({kAuthenticatedUsersSid});
57   ASSERT_TRUE(sids);
58   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
59   FilePath path = temp_dir.GetPath().Append(L"test");
60   EXPECT_FALSE(
61       GrantAccessToPath(path, *sids, FILE_GENERIC_READ, NO_INHERITANCE, true));
62   EXPECT_FALSE(
63       GrantAccessToPath(path, *sids, FILE_GENERIC_READ, NO_INHERITANCE, false));
64   ASSERT_TRUE(CreateWithDacl(path, kBaseDacl, false));
65   EXPECT_TRUE(
66       GrantAccessToPath(path, *sids, FILE_GENERIC_READ, NO_INHERITANCE, true));
67   EXPECT_TRUE(
68       GrantAccessToPath(path, *sids, FILE_GENERIC_READ, NO_INHERITANCE, false));
69   std::vector<Sid> large_sid_list;
70   while (large_sid_list.size() < 0x10000) {
71     auto sid = Sid::FromSddlString(L"S-1-5-1234-" +
72                                    NumberToWString(large_sid_list.size()));
73     ASSERT_TRUE(sid);
74     large_sid_list.emplace_back(std::move(*sid));
75   }
76   EXPECT_FALSE(GrantAccessToPath(path, large_sid_list, FILE_GENERIC_READ,
77                                  NO_INHERITANCE, false));
78   path = temp_dir.GetPath().Append(L"test_nowritedac");
79   ASSERT_TRUE(CreateWithDacl(path, kNoWriteDacDacl, false));
80   EXPECT_FALSE(
81       GrantAccessToPath(path, *sids, FILE_GENERIC_READ, NO_INHERITANCE, true));
82   EXPECT_FALSE(
83       GrantAccessToPath(path, *sids, FILE_GENERIC_READ, NO_INHERITANCE, false));
84 }
85 
TEST(SecurityUtilTest,GrantAccessToPathFile)86 TEST(SecurityUtilTest, GrantAccessToPathFile) {
87   ScopedTempDir temp_dir;
88   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
89   FilePath path = temp_dir.GetPath().Append(L"test");
90   ASSERT_TRUE(CreateWithDacl(path, kBaseDacl, false));
91   EXPECT_EQ(kBaseDacl, GetFileDacl(path));
92   auto sids = Sid::FromSddlStringVector({kAuthenticatedUsersSid});
93   ASSERT_TRUE(sids);
94   EXPECT_TRUE(
95       GrantAccessToPath(path, *sids, FILE_GENERIC_READ, NO_INHERITANCE, true));
96   EXPECT_EQ(kTest1Dacl, GetFileDacl(path));
97   auto sids2 = Sid::FromSddlStringVector({L"S-1-5-11", L"BA"});
98   ASSERT_TRUE(sids2);
99   EXPECT_TRUE(
100       GrantAccessToPath(path, *sids2, GENERIC_ALL, NO_INHERITANCE, true));
101   EXPECT_EQ(kTest2Dacl, GetFileDacl(path));
102 }
103 
TEST(SecurityUtilTest,GrantAccessToPathFileNoInherit)104 TEST(SecurityUtilTest, GrantAccessToPathFileNoInherit) {
105   ScopedTempDir temp_dir;
106   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
107   FilePath path = temp_dir.GetPath().Append(L"test");
108   ASSERT_TRUE(CreateWithDacl(path, kBaseDacl, false));
109   EXPECT_EQ(kBaseDacl, GetFileDacl(path));
110   EXPECT_TRUE(
111       GrantAccessToPath(path, {}, FILE_GENERIC_READ, NO_INHERITANCE, false));
112   EXPECT_EQ(kBaseDacl, GetFileDacl(path));
113   auto sids = Sid::FromSddlStringVector({kAuthenticatedUsersSid});
114   ASSERT_TRUE(sids);
115   EXPECT_TRUE(
116       GrantAccessToPath(path, *sids, FILE_GENERIC_READ, NO_INHERITANCE, false));
117   EXPECT_EQ(kTest1DaclNoInherit, GetFileDacl(path));
118   auto sids2 = Sid::FromSddlStringVector({L"S-1-5-11", L"BA"});
119   ASSERT_TRUE(sids2);
120   EXPECT_TRUE(
121       GrantAccessToPath(path, *sids2, GENERIC_ALL, NO_INHERITANCE, false));
122   EXPECT_EQ(kTest2DaclNoInherit, GetFileDacl(path));
123 }
124 
TEST(SecurityUtilTest,DenyAccessToPathFile)125 TEST(SecurityUtilTest, DenyAccessToPathFile) {
126   ScopedTempDir temp_dir;
127   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
128   FilePath path = temp_dir.GetPath().Append(L"test");
129   ASSERT_TRUE(CreateWithDacl(path, kBaseDacl, false));
130   EXPECT_EQ(kBaseDacl, GetFileDacl(path));
131   EXPECT_TRUE(
132       DenyAccessToPath(path, {}, FILE_GENERIC_READ, NO_INHERITANCE, true));
133   EXPECT_EQ(kBaseDacl, GetFileDacl(path));
134   auto sids = Sid::FromSddlStringVector({kLocalGuestSid});
135   ASSERT_TRUE(sids);
136   EXPECT_TRUE(
137       DenyAccessToPath(path, *sids, FILE_GENERIC_READ, NO_INHERITANCE, true));
138   EXPECT_EQ(kTest1DenyDacl, GetFileDacl(path));
139 }
140 
TEST(SecurityUtilTest,DenyAccessToPathFileMultiple)141 TEST(SecurityUtilTest, DenyAccessToPathFileMultiple) {
142   ScopedTempDir temp_dir;
143   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
144   FilePath path = temp_dir.GetPath().Append(L"test");
145   ASSERT_TRUE(CreateWithDacl(path, kBaseDacl, false));
146   EXPECT_EQ(kBaseDacl, GetFileDacl(path));
147   auto sids = Sid::FromSddlStringVector({kLocalGuestSid});
148   ASSERT_TRUE(sids);
149   EXPECT_TRUE(
150       DenyAccessToPath(path, *sids, FILE_GENERIC_READ, NO_INHERITANCE, true));
151   // Verify setting same ACE on same file does not change the ACL.
152   EXPECT_TRUE(
153       DenyAccessToPath(path, *sids, FILE_GENERIC_READ, NO_INHERITANCE, true));
154   EXPECT_TRUE(
155       DenyAccessToPath(path, *sids, FILE_GENERIC_READ, NO_INHERITANCE, true));
156   EXPECT_EQ(kTest1DenyDacl, GetFileDacl(path));
157 }
158 
TEST(SecurityUtilTest,GrantAccessToPathDirectory)159 TEST(SecurityUtilTest, GrantAccessToPathDirectory) {
160   ScopedTempDir temp_dir;
161   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
162   FilePath path = temp_dir.GetPath().Append(L"testdir");
163   ASSERT_TRUE(CreateWithDacl(path, kBaseDirDacl, true));
164   EXPECT_EQ(kBaseDirDacl, GetFileDacl(path));
165   FilePath file_path = path.Append(L"test");
166   File file(file_path, File::FLAG_CREATE_ALWAYS | File::FLAG_WRITE);
167   ASSERT_TRUE(file.IsValid());
168   file.Close();
169   EXPECT_EQ(kTest1InheritedDacl, GetFileDacl(file_path));
170   auto sids = Sid::FromSddlStringVector({kAuthenticatedUsersSid});
171   ASSERT_TRUE(sids);
172   EXPECT_TRUE(GrantAccessToPath(path, *sids, FILE_GENERIC_READ,
173                                 OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE,
174                                 true));
175   EXPECT_EQ(kBaseDir2Dacl, GetFileDacl(path));
176   EXPECT_EQ(kTest2InheritedDacl, GetFileDacl(file_path));
177 }
178 
TEST(SecurityUtilTest,GrantAccessToPathDirectoryNoInherit)179 TEST(SecurityUtilTest, GrantAccessToPathDirectoryNoInherit) {
180   ScopedTempDir temp_dir;
181   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
182   FilePath path = temp_dir.GetPath().Append(L"testdir");
183   ASSERT_TRUE(CreateWithDacl(path, kBaseDirDacl, true));
184   EXPECT_EQ(kBaseDirDacl, GetFileDacl(path));
185   FilePath file_path = path.Append(L"test");
186   File file(file_path, File::FLAG_CREATE_ALWAYS | File::FLAG_WRITE);
187   ASSERT_TRUE(file.IsValid());
188   file.Close();
189   EXPECT_EQ(kTest1InheritedDacl, GetFileDacl(file_path));
190   auto sids = Sid::FromSddlStringVector({kAuthenticatedUsersSid});
191   ASSERT_TRUE(sids);
192   EXPECT_TRUE(GrantAccessToPath(path, *sids, FILE_GENERIC_READ,
193                                 OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE,
194                                 false));
195   EXPECT_EQ(kBaseDir2DaclNoInherit, GetFileDacl(path));
196   EXPECT_EQ(kTest2InheritedDaclNoInherit, GetFileDacl(file_path));
197 
198   FilePath file_path2 = path.Append(L"test2");
199   File file2(file_path2, File::FLAG_CREATE_ALWAYS | File::FLAG_WRITE);
200   ASSERT_TRUE(file2.IsValid());
201   file2.Close();
202   EXPECT_EQ(kTest3InheritedDacl, GetFileDacl(file_path2));
203 }
204 
TEST(SecurityUtilTest,CloneSidVector)205 TEST(SecurityUtilTest, CloneSidVector) {
206   std::vector<Sid> sids =
207       Sid::FromKnownSidVector({WellKnownSid::kNull, WellKnownSid::kWorld});
208   std::vector<Sid> clone = CloneSidVector(sids);
209   ASSERT_EQ(sids.size(), clone.size());
210   for (size_t index = 0; index < sids.size(); ++index) {
211     ASSERT_EQ(sids[index], clone[index]);
212     ASSERT_NE(sids[index].GetPSID(), clone[index].GetPSID());
213   }
214   ASSERT_EQ(CloneSidVector(std::vector<Sid>()).size(), 0U);
215 }
216 
TEST(SecurityUtilTest,AppendSidVector)217 TEST(SecurityUtilTest, AppendSidVector) {
218   std::vector<Sid> sids =
219       Sid::FromKnownSidVector({WellKnownSid::kNull, WellKnownSid::kWorld});
220 
221   std::vector<Sid> total_sids;
222   AppendSidVector(total_sids, sids);
223   EXPECT_EQ(total_sids.size(), sids.size());
224 
225   std::vector<Sid> sids2 = Sid::FromKnownSidVector(
226       {WellKnownSid::kCreatorOwner, WellKnownSid::kNetwork});
227   AppendSidVector(total_sids, sids2);
228   EXPECT_EQ(total_sids.size(), sids.size() + sids2.size());
229 
230   auto sid_interator = total_sids.cbegin();
231   for (size_t index = 0; index < sids.size(); ++index) {
232     ASSERT_EQ(*sid_interator, sids[index]);
233     ASSERT_NE(sid_interator->GetPSID(), sids[index].GetPSID());
234     sid_interator++;
235   }
236   for (size_t index = 0; index < sids2.size(); ++index) {
237     ASSERT_EQ(*sid_interator, sids2[index]);
238     ASSERT_NE(sid_interator->GetPSID(), sids2[index].GetPSID());
239     sid_interator++;
240   }
241 }
242 
TEST(SecurityUtilTest,GetGrantedAccess)243 TEST(SecurityUtilTest, GetGrantedAccess) {
244   EXPECT_FALSE(GetGrantedAccess(nullptr));
245   ScopedHandle handle(::CreateMutexEx(nullptr, nullptr, 0, MUTEX_MODIFY_STATE));
246   EXPECT_EQ(GetGrantedAccess(handle.get()), DWORD{MUTEX_MODIFY_STATE});
247   handle.Set(::CreateMutexEx(nullptr, nullptr, 0, READ_CONTROL));
248   EXPECT_EQ(GetGrantedAccess(handle.get()), DWORD{READ_CONTROL});
249   handle.Set(::CreateMutexEx(nullptr, nullptr, 0, GENERIC_ALL));
250   EXPECT_EQ(GetGrantedAccess(handle.get()), DWORD{MUTEX_ALL_ACCESS});
251 }
252 
253 }  // namespace win
254 }  // namespace base
255