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