• 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 #ifdef UNSAFE_BUFFERS_BUILD
6 // TODO(crbug.com/40284755): Remove this and spanify to fix the errors.
7 #pragma allow_unsafe_buffers
8 #endif
9 
10 #include "base/win/sid.h"
11 
12 // clang-format off
13 #include <windows.h>  // Must be in front of other Windows header files.
14 // clang-format on
15 
16 #include <sddl.h>
17 #include <stdint.h>
18 #include <stdlib.h>
19 
20 #include <iterator>
21 #include <map>
22 #include <utility>
23 
24 #include "base/check.h"
25 #include "base/no_destructor.h"
26 #include "base/rand_util.h"
27 #include "base/ranges/algorithm.h"
28 #include "base/strings/string_util_win.h"
29 #include "base/win/scoped_handle.h"
30 #include "base/win/scoped_localalloc.h"
31 #include "base/win/windows_version.h"
32 #include "third_party/boringssl/src/include/openssl/sha.h"
33 
34 namespace base::win {
35 
36 namespace {
37 
38 template <typename Iterator>
FromSubAuthorities(const SID_IDENTIFIER_AUTHORITY & identifier_authority,size_t sub_authority_count,Iterator sub_authorities)39 Sid FromSubAuthorities(const SID_IDENTIFIER_AUTHORITY& identifier_authority,
40                        size_t sub_authority_count,
41                        Iterator sub_authorities) {
42   DCHECK(sub_authority_count <= SID_MAX_SUB_AUTHORITIES);
43   BYTE sid_buffer[SECURITY_MAX_SID_SIZE];
44   SID* sid = reinterpret_cast<SID*>(sid_buffer);
45   sid->Revision = SID_REVISION;
46   sid->SubAuthorityCount = static_cast<UCHAR>(sub_authority_count);
47   sid->IdentifierAuthority = identifier_authority;
48   for (size_t index = 0; index < sub_authority_count; ++index) {
49     sid->SubAuthority[index] = static_cast<DWORD>(*sub_authorities++);
50   }
51   DCHECK(::IsValidSid(sid));
52   return *Sid::FromPSID(sid);
53 }
54 
FromSubAuthorities(const SID_IDENTIFIER_AUTHORITY & identifier_authority,std::initializer_list<int32_t> sub_authorities)55 Sid FromSubAuthorities(const SID_IDENTIFIER_AUTHORITY& identifier_authority,
56                        std::initializer_list<int32_t> sub_authorities) {
57   return FromSubAuthorities(identifier_authority, sub_authorities.size(),
58                             sub_authorities.begin());
59 }
60 
FromNtAuthority(std::initializer_list<int32_t> sub_authorities)61 Sid FromNtAuthority(std::initializer_list<int32_t> sub_authorities) {
62   return FromSubAuthorities(SECURITY_NT_AUTHORITY, sub_authorities);
63 }
64 
WellKnownCapabilityToRid(WellKnownCapability capability)65 int32_t WellKnownCapabilityToRid(WellKnownCapability capability) {
66   switch (capability) {
67     case WellKnownCapability::kInternetClient:
68       return SECURITY_CAPABILITY_INTERNET_CLIENT;
69     case WellKnownCapability::kInternetClientServer:
70       return SECURITY_CAPABILITY_INTERNET_CLIENT_SERVER;
71     case WellKnownCapability::kPrivateNetworkClientServer:
72       return SECURITY_CAPABILITY_PRIVATE_NETWORK_CLIENT_SERVER;
73     case WellKnownCapability::kPicturesLibrary:
74       return SECURITY_CAPABILITY_PICTURES_LIBRARY;
75     case WellKnownCapability::kVideosLibrary:
76       return SECURITY_CAPABILITY_VIDEOS_LIBRARY;
77     case WellKnownCapability::kMusicLibrary:
78       return SECURITY_CAPABILITY_MUSIC_LIBRARY;
79     case WellKnownCapability::kDocumentsLibrary:
80       return SECURITY_CAPABILITY_DOCUMENTS_LIBRARY;
81     case WellKnownCapability::kEnterpriseAuthentication:
82       return SECURITY_CAPABILITY_ENTERPRISE_AUTHENTICATION;
83     case WellKnownCapability::kSharedUserCertificates:
84       return SECURITY_CAPABILITY_SHARED_USER_CERTIFICATES;
85     case WellKnownCapability::kRemovableStorage:
86       return SECURITY_CAPABILITY_REMOVABLE_STORAGE;
87     case WellKnownCapability::kAppointments:
88       return SECURITY_CAPABILITY_APPOINTMENTS;
89     case WellKnownCapability::kContacts:
90       return SECURITY_CAPABILITY_CONTACTS;
91   }
92 }
93 
94 }  // namespace
95 
Sid(const void * sid,size_t length)96 Sid::Sid(const void* sid, size_t length)
97     : sid_(static_cast<const char*>(sid),
98            static_cast<const char*>(sid) + length) {
99   DCHECK(::IsValidSid(GetPSID()));
100 }
101 
FromKnownCapability(WellKnownCapability capability)102 Sid Sid::FromKnownCapability(WellKnownCapability capability) {
103   int32_t capability_rid = WellKnownCapabilityToRid(capability);
104   return FromSubAuthorities(SECURITY_APP_PACKAGE_AUTHORITY,
105                             {SECURITY_CAPABILITY_BASE_RID, capability_rid});
106 }
107 
FromNamedCapability(const std::wstring & capability_name)108 Sid Sid::FromNamedCapability(const std::wstring& capability_name) {
109   static const base::NoDestructor<std::map<std::wstring, WellKnownCapability>>
110       known_capabilities(
111           {{L"INTERNETCLIENT", WellKnownCapability::kInternetClient},
112            {L"INTERNETCLIENTSERVER",
113             WellKnownCapability::kInternetClientServer},
114            {L"PRIVATENETWORKCLIENTSERVER",
115             WellKnownCapability::kPrivateNetworkClientServer},
116            {L"PICTURESLIBRARY", WellKnownCapability::kPicturesLibrary},
117            {L"VIDEOSLIBRARY", WellKnownCapability::kVideosLibrary},
118            {L"MUSICLIBRARY", WellKnownCapability::kMusicLibrary},
119            {L"DOCUMENTSLIBRARY", WellKnownCapability::kDocumentsLibrary},
120            {L"ENTERPRISEAUTHENTICATION",
121             WellKnownCapability::kEnterpriseAuthentication},
122            {L"SHAREDUSERCERTIFICATES",
123             WellKnownCapability::kSharedUserCertificates},
124            {L"REMOVABLESTORAGE", WellKnownCapability::kRemovableStorage},
125            {L"APPOINTMENTS", WellKnownCapability::kAppointments},
126            {L"CONTACTS", WellKnownCapability::kContacts}});
127 
128   std::wstring cap_upper = base::ToUpperASCII(capability_name);
129   auto known_cap = known_capabilities->find(cap_upper);
130   if (known_cap != known_capabilities->end()) {
131     return FromKnownCapability(known_cap->second);
132   }
133   static_assert((SHA256_DIGEST_LENGTH / sizeof(DWORD)) ==
134                 SECURITY_APP_PACKAGE_RID_COUNT);
135   DWORD rids[(SHA256_DIGEST_LENGTH / sizeof(DWORD)) + 2];
136   rids[0] = SECURITY_CAPABILITY_BASE_RID;
137   rids[1] = SECURITY_CAPABILITY_APP_RID;
138 
139   SHA256(reinterpret_cast<const uint8_t*>(cap_upper.c_str()),
140          cap_upper.size() * sizeof(wchar_t),
141          reinterpret_cast<uint8_t*>(&rids[2]));
142   return FromSubAuthorities(SECURITY_APP_PACKAGE_AUTHORITY, std::size(rids),
143                             rids);
144 }
145 
FromKnownSid(WellKnownSid type)146 Sid Sid::FromKnownSid(WellKnownSid type) {
147   switch (type) {
148     case WellKnownSid::kNull:
149       return FromSubAuthorities(SECURITY_NULL_SID_AUTHORITY,
150                                 {SECURITY_NULL_RID});
151     case WellKnownSid::kWorld:
152       return FromSubAuthorities(SECURITY_WORLD_SID_AUTHORITY,
153                                 {SECURITY_WORLD_RID});
154     case WellKnownSid::kCreatorOwner:
155       return FromSubAuthorities(SECURITY_CREATOR_SID_AUTHORITY,
156                                 {SECURITY_CREATOR_OWNER_RID});
157     case WellKnownSid::kCreatorOwnerRights:
158       return FromSubAuthorities(SECURITY_CREATOR_SID_AUTHORITY,
159                                 {SECURITY_CREATOR_OWNER_RIGHTS_RID});
160     case WellKnownSid::kNetwork:
161       return FromNtAuthority({SECURITY_NETWORK_RID});
162     case WellKnownSid::kBatch:
163       return FromNtAuthority({SECURITY_BATCH_RID});
164     case WellKnownSid::kInteractive:
165       return FromNtAuthority({SECURITY_INTERACTIVE_RID});
166     case WellKnownSid::kService:
167       return FromNtAuthority({SECURITY_SERVICE_RID});
168     case WellKnownSid::kAnonymous:
169       return FromNtAuthority({SECURITY_ANONYMOUS_LOGON_RID});
170     case WellKnownSid::kSelf:
171       return FromNtAuthority({SECURITY_PRINCIPAL_SELF_RID});
172     case WellKnownSid::kAuthenticatedUser:
173       return FromNtAuthority({SECURITY_AUTHENTICATED_USER_RID});
174     case WellKnownSid::kRestricted:
175       return FromNtAuthority({SECURITY_RESTRICTED_CODE_RID});
176     case WellKnownSid::kWriteRestricted:
177       return FromNtAuthority({SECURITY_WRITE_RESTRICTED_CODE_RID});
178     case WellKnownSid::kLocalSystem:
179       return FromNtAuthority({SECURITY_LOCAL_SYSTEM_RID});
180     case WellKnownSid::kLocalService:
181       return FromNtAuthority({SECURITY_LOCAL_SERVICE_RID});
182     case WellKnownSid::kNetworkService:
183       return FromNtAuthority({SECURITY_NETWORK_SERVICE_RID});
184     case WellKnownSid::kBuiltinAdministrators:
185       return FromNtAuthority(
186           {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS});
187     case WellKnownSid::kBuiltinUsers:
188       return FromNtAuthority(
189           {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_USERS});
190     case WellKnownSid::kBuiltinGuests:
191       return FromNtAuthority(
192           {SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_GUESTS});
193     case WellKnownSid::kUntrustedLabel:
194       return FromIntegrityLevel(SECURITY_MANDATORY_UNTRUSTED_RID);
195     case WellKnownSid::kLowLabel:
196       return FromIntegrityLevel(SECURITY_MANDATORY_LOW_RID);
197     case WellKnownSid::kMediumLabel:
198       return FromIntegrityLevel(SECURITY_MANDATORY_MEDIUM_RID);
199     case WellKnownSid::kHighLabel:
200       return FromIntegrityLevel(SECURITY_MANDATORY_HIGH_RID);
201     case WellKnownSid::kSystemLabel:
202       return FromIntegrityLevel(SECURITY_MANDATORY_SYSTEM_RID);
203     case WellKnownSid::kAllApplicationPackages:
204       return FromSubAuthorities(SECURITY_APP_PACKAGE_AUTHORITY,
205                                 {SECURITY_APP_PACKAGE_BASE_RID,
206                                  SECURITY_BUILTIN_PACKAGE_ANY_PACKAGE});
207     case WellKnownSid::kAllRestrictedApplicationPackages:
208       return FromSubAuthorities(
209           SECURITY_APP_PACKAGE_AUTHORITY,
210           {SECURITY_APP_PACKAGE_BASE_RID,
211            SECURITY_BUILTIN_PACKAGE_ANY_RESTRICTED_PACKAGE});
212   }
213 }
214 
FromSddlString(const std::wstring & sddl_sid)215 std::optional<Sid> Sid::FromSddlString(const std::wstring& sddl_sid) {
216   PSID psid = nullptr;
217   if (!::ConvertStringSidToSid(sddl_sid.c_str(), &psid)) {
218     return std::nullopt;
219   }
220   auto psid_alloc = TakeLocalAlloc(psid);
221   return FromPSID(psid_alloc.get());
222 }
223 
FromPSID(PSID sid)224 std::optional<Sid> Sid::FromPSID(PSID sid) {
225   DCHECK(sid);
226   if (!sid || !::IsValidSid(sid))
227     return std::nullopt;
228   return Sid(sid, ::GetLengthSid(sid));
229 }
230 
GenerateRandomSid()231 Sid Sid::GenerateRandomSid() {
232   DWORD sub_authorities[4] = {};
233   RandBytes(as_writable_byte_span(sub_authorities));
234   return FromSubAuthorities(SECURITY_NULL_SID_AUTHORITY,
235                             std::size(sub_authorities), sub_authorities);
236 }
237 
FromIntegrityLevel(DWORD integrity_level)238 Sid Sid::FromIntegrityLevel(DWORD integrity_level) {
239   return FromSubAuthorities(SECURITY_MANDATORY_LABEL_AUTHORITY, 1,
240                             &integrity_level);
241 }
242 
FromSddlStringVector(const std::vector<std::wstring> & sddl_sids)243 std::optional<std::vector<Sid>> Sid::FromSddlStringVector(
244     const std::vector<std::wstring>& sddl_sids) {
245   std::vector<Sid> converted_sids;
246   converted_sids.reserve(sddl_sids.size());
247   for (const std::wstring& sddl_sid : sddl_sids) {
248     std::optional<Sid> sid = FromSddlString(sddl_sid);
249     if (!sid)
250       return std::nullopt;
251     converted_sids.push_back(std::move(*sid));
252   }
253   return converted_sids;
254 }
255 
FromNamedCapabilityVector(const std::vector<std::wstring> & capability_names)256 std::vector<Sid> Sid::FromNamedCapabilityVector(
257     const std::vector<std::wstring>& capability_names) {
258   std::vector<Sid> sids;
259   ranges::transform(capability_names, std::back_inserter(sids),
260                     FromNamedCapability);
261   return sids;
262 }
263 
FromKnownCapabilityVector(const std::vector<WellKnownCapability> & capabilities)264 std::vector<Sid> Sid::FromKnownCapabilityVector(
265     const std::vector<WellKnownCapability>& capabilities) {
266   std::vector<Sid> sids;
267   ranges::transform(capabilities, std::back_inserter(sids),
268                     FromKnownCapability);
269   return sids;
270 }
271 
FromKnownSidVector(const std::vector<WellKnownSid> & known_sids)272 std::vector<Sid> Sid::FromKnownSidVector(
273     const std::vector<WellKnownSid>& known_sids) {
274   std::vector<Sid> sids;
275   ranges::transform(known_sids, std::back_inserter(sids), FromKnownSid);
276   return sids;
277 }
278 
Sid(WellKnownSid known_sid)279 Sid::Sid(WellKnownSid known_sid) : Sid(FromKnownSid(known_sid)) {}
Sid(WellKnownCapability known_capability)280 Sid::Sid(WellKnownCapability known_capability)
281     : Sid(FromKnownCapability(known_capability)) {}
282 Sid::Sid(Sid&& sid) = default;
283 Sid& Sid::operator=(Sid&&) = default;
284 Sid::~Sid() = default;
285 
GetPSID() const286 PSID Sid::GetPSID() const {
287   DCHECK(!sid_.empty());
288   return const_cast<char*>(sid_.data());
289 }
290 
ToSddlString() const291 std::optional<std::wstring> Sid::ToSddlString() const {
292   LPWSTR sid = nullptr;
293   if (!::ConvertSidToStringSid(GetPSID(), &sid))
294     return std::nullopt;
295   auto sid_ptr = TakeLocalAlloc(sid);
296   return sid_ptr.get();
297 }
298 
Clone() const299 Sid Sid::Clone() const {
300   return Sid(sid_.data(), sid_.size());
301 }
302 
Equal(PSID sid) const303 bool Sid::Equal(PSID sid) const {
304   return !!::EqualSid(GetPSID(), sid);
305 }
306 
operator ==(const Sid & sid) const307 bool Sid::operator==(const Sid& sid) const {
308   return Equal(sid.GetPSID());
309 }
310 
operator !=(const Sid & sid) const311 bool Sid::operator!=(const Sid& sid) const {
312   return !(operator==(sid));
313 }
314 
315 }  // namespace base::win
316