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