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