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