sid.cc 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. // Copyright 2021 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "base/win/sid.h"
  5. #include <windows.h>
  6. #include <sddl.h>
  7. #include <stdlib.h>
  8. #include <iterator>
  9. #include <utility>
  10. #include "base/check.h"
  11. #include "base/notreached.h"
  12. #include "base/rand_util.h"
  13. #include "base/win/scoped_handle.h"
  14. #include "base/win/scoped_localalloc.h"
  15. #include "base/win/windows_version.h"
  16. namespace base {
  17. namespace win {
  18. namespace {
  19. absl::optional<long> // NOLINT(runtime/int)
  20. WellKnownCapabilityToRid(WellKnownCapability capability) {
  21. switch (capability) {
  22. case WellKnownCapability::kInternetClient:
  23. return SECURITY_CAPABILITY_INTERNET_CLIENT;
  24. case WellKnownCapability::kInternetClientServer:
  25. return SECURITY_CAPABILITY_INTERNET_CLIENT_SERVER;
  26. case WellKnownCapability::kPrivateNetworkClientServer:
  27. return SECURITY_CAPABILITY_PRIVATE_NETWORK_CLIENT_SERVER;
  28. case WellKnownCapability::kPicturesLibrary:
  29. return SECURITY_CAPABILITY_PICTURES_LIBRARY;
  30. case WellKnownCapability::kVideosLibrary:
  31. return SECURITY_CAPABILITY_VIDEOS_LIBRARY;
  32. case WellKnownCapability::kMusicLibrary:
  33. return SECURITY_CAPABILITY_MUSIC_LIBRARY;
  34. case WellKnownCapability::kDocumentsLibrary:
  35. return SECURITY_CAPABILITY_DOCUMENTS_LIBRARY;
  36. case WellKnownCapability::kEnterpriseAuthentication:
  37. return SECURITY_CAPABILITY_ENTERPRISE_AUTHENTICATION;
  38. case WellKnownCapability::kSharedUserCertificates:
  39. return SECURITY_CAPABILITY_SHARED_USER_CERTIFICATES;
  40. case WellKnownCapability::kRemovableStorage:
  41. return SECURITY_CAPABILITY_REMOVABLE_STORAGE;
  42. case WellKnownCapability::kAppointments:
  43. return SECURITY_CAPABILITY_APPOINTMENTS;
  44. case WellKnownCapability::kContacts:
  45. return SECURITY_CAPABILITY_CONTACTS;
  46. }
  47. return absl::nullopt;
  48. }
  49. absl::optional<WELL_KNOWN_SID_TYPE> WellKnownSidToEnum(WellKnownSid sid) {
  50. switch (sid) {
  51. case WellKnownSid::kNull:
  52. return WinNullSid;
  53. case WellKnownSid::kWorld:
  54. return WinWorldSid;
  55. case WellKnownSid::kCreatorOwner:
  56. return WinCreatorOwnerSid;
  57. case WellKnownSid::kNetwork:
  58. return WinNetworkSid;
  59. case WellKnownSid::kBatch:
  60. return WinBatchSid;
  61. case WellKnownSid::kInteractive:
  62. return WinInteractiveSid;
  63. case WellKnownSid::kService:
  64. return WinServiceSid;
  65. case WellKnownSid::kAnonymous:
  66. return WinAnonymousSid;
  67. case WellKnownSid::kSelf:
  68. return WinSelfSid;
  69. case WellKnownSid::kAuthenticatedUser:
  70. return WinAuthenticatedUserSid;
  71. case WellKnownSid::kRestricted:
  72. return WinRestrictedCodeSid;
  73. case WellKnownSid::kLocalSystem:
  74. return WinLocalSystemSid;
  75. case WellKnownSid::kLocalService:
  76. return WinLocalServiceSid;
  77. case WellKnownSid::kNetworkService:
  78. return WinNetworkServiceSid;
  79. case WellKnownSid::kBuiltinAdministrators:
  80. return WinBuiltinAdministratorsSid;
  81. case WellKnownSid::kBuiltinUsers:
  82. return WinBuiltinUsersSid;
  83. case WellKnownSid::kBuiltinGuests:
  84. return WinBuiltinGuestsSid;
  85. case WellKnownSid::kUntrustedLabel:
  86. return WinUntrustedLabelSid;
  87. case WellKnownSid::kLowLabel:
  88. return WinLowLabelSid;
  89. case WellKnownSid::kMediumLabel:
  90. return WinMediumLabelSid;
  91. case WellKnownSid::kHighLabel:
  92. return WinHighLabelSid;
  93. case WellKnownSid::kSystemLabel:
  94. return WinSystemLabelSid;
  95. case WellKnownSid::kWriteRestricted:
  96. return WinWriteRestrictedCodeSid;
  97. case WellKnownSid::kCreatorOwnerRights:
  98. return WinCreatorOwnerRightsSid;
  99. case WellKnownSid::kAllApplicationPackages:
  100. return WinBuiltinAnyPackageSid;
  101. case WellKnownSid::kAllRestrictedApplicationPackages:
  102. // This should be handled by FromKnownSid.
  103. NOTREACHED();
  104. break;
  105. }
  106. return absl::nullopt;
  107. }
  108. absl::optional<Sid> FromSubAuthorities(
  109. PSID_IDENTIFIER_AUTHORITY identifier_authority,
  110. BYTE sub_authority_count,
  111. PDWORD sub_authorities) {
  112. BYTE sid[SECURITY_MAX_SID_SIZE];
  113. if (!::InitializeSid(sid, identifier_authority, sub_authority_count))
  114. return absl::nullopt;
  115. for (DWORD index = 0; index < sub_authority_count; ++index) {
  116. PDWORD sub_authority = ::GetSidSubAuthority(sid, index);
  117. *sub_authority = sub_authorities[index];
  118. }
  119. return Sid::FromPSID(sid);
  120. }
  121. template <typename T>
  122. absl::optional<std::vector<Sid>> FromVector(
  123. const std::vector<T>& values,
  124. absl::optional<Sid> (*create_sid)(T)) {
  125. std::vector<Sid> converted_sids;
  126. converted_sids.reserve(values.size());
  127. for (T value : values) {
  128. auto sid = create_sid(value);
  129. if (!sid)
  130. return absl::nullopt;
  131. converted_sids.push_back(std::move(*sid));
  132. }
  133. return converted_sids;
  134. }
  135. } // namespace
  136. Sid::Sid(const void* sid, size_t length)
  137. : sid_(static_cast<const char*>(sid),
  138. static_cast<const char*>(sid) + length) {
  139. DCHECK(::IsValidSid(GetPSID()));
  140. }
  141. absl::optional<Sid> Sid::FromKnownCapability(WellKnownCapability capability) {
  142. absl::optional<long> capability_rid = // NOLINT(runtime/int)
  143. WellKnownCapabilityToRid(capability);
  144. if (!capability_rid)
  145. return absl::nullopt;
  146. SID_IDENTIFIER_AUTHORITY capability_authority = {
  147. SECURITY_APP_PACKAGE_AUTHORITY};
  148. DWORD sub_authorities[] = {SECURITY_CAPABILITY_BASE_RID,
  149. static_cast<DWORD>(*capability_rid)};
  150. return FromSubAuthorities(&capability_authority, std::size(sub_authorities),
  151. sub_authorities);
  152. }
  153. absl::optional<Sid> Sid::FromNamedCapability(const wchar_t* capability_name) {
  154. DCHECK_GE(GetVersion(), Version::WIN10);
  155. if (!capability_name || !*capability_name)
  156. return absl::nullopt;
  157. typedef decltype(
  158. ::DeriveCapabilitySidsFromName)* DeriveCapabilitySidsFromNameFunc;
  159. static const DeriveCapabilitySidsFromNameFunc derive_capability_sids =
  160. []() -> DeriveCapabilitySidsFromNameFunc {
  161. HMODULE module = GetModuleHandle(L"api-ms-win-security-base-l1-2-2.dll");
  162. if (!module)
  163. return nullptr;
  164. return reinterpret_cast<DeriveCapabilitySidsFromNameFunc>(
  165. ::GetProcAddress(module, "DeriveCapabilitySidsFromName"));
  166. }();
  167. if (!derive_capability_sids)
  168. return absl::nullopt;
  169. // Pre-reserve some space for SID deleters.
  170. std::vector<ScopedLocalAlloc> deleter_list;
  171. deleter_list.reserve(16);
  172. PSID* capability_groups = nullptr;
  173. DWORD capability_group_count = 0;
  174. PSID* capability_sids = nullptr;
  175. DWORD capability_sid_count = 0;
  176. if (!derive_capability_sids(capability_name, &capability_groups,
  177. &capability_group_count, &capability_sids,
  178. &capability_sid_count)) {
  179. return absl::nullopt;
  180. }
  181. deleter_list.emplace_back(capability_groups);
  182. deleter_list.emplace_back(capability_sids);
  183. for (DWORD i = 0; i < capability_group_count; ++i) {
  184. deleter_list.emplace_back(capability_groups[i]);
  185. }
  186. for (DWORD i = 0; i < capability_sid_count; ++i) {
  187. deleter_list.emplace_back(capability_sids[i]);
  188. }
  189. if (capability_sid_count < 1)
  190. return absl::nullopt;
  191. return FromPSID(capability_sids[0]);
  192. }
  193. absl::optional<Sid> Sid::FromKnownSid(WellKnownSid type) {
  194. if (type == WellKnownSid::kAllRestrictedApplicationPackages) {
  195. SID_IDENTIFIER_AUTHORITY package_authority = {
  196. SECURITY_APP_PACKAGE_AUTHORITY};
  197. DWORD sub_authorities[] = {SECURITY_APP_PACKAGE_BASE_RID,
  198. SECURITY_BUILTIN_PACKAGE_ANY_RESTRICTED_PACKAGE};
  199. return FromSubAuthorities(&package_authority, 2, sub_authorities);
  200. }
  201. BYTE sid[SECURITY_MAX_SID_SIZE];
  202. DWORD size_sid = SECURITY_MAX_SID_SIZE;
  203. absl::optional<WELL_KNOWN_SID_TYPE> known_sid = WellKnownSidToEnum(type);
  204. if (!known_sid)
  205. return absl::nullopt;
  206. if (!::CreateWellKnownSid(*known_sid, nullptr, sid, &size_sid))
  207. return absl::nullopt;
  208. return Sid(sid, size_sid);
  209. }
  210. absl::optional<Sid> Sid::FromSddlString(const wchar_t* sddl_sid) {
  211. PSID psid = nullptr;
  212. if (!::ConvertStringSidToSid(sddl_sid, &psid))
  213. return absl::nullopt;
  214. return FromPSID(TakeLocalAlloc(psid).get());
  215. }
  216. absl::optional<Sid> Sid::FromPSID(PSID sid) {
  217. DCHECK(sid);
  218. if (!sid || !::IsValidSid(sid))
  219. return absl::nullopt;
  220. return Sid(sid, ::GetLengthSid(sid));
  221. }
  222. absl::optional<Sid> Sid::GenerateRandomSid() {
  223. SID_IDENTIFIER_AUTHORITY package_authority = {SECURITY_NULL_SID_AUTHORITY};
  224. DWORD sub_authorities[4] = {};
  225. RandBytes(&sub_authorities, sizeof(sub_authorities));
  226. return FromSubAuthorities(&package_authority, _countof(sub_authorities),
  227. sub_authorities);
  228. }
  229. absl::optional<Sid> Sid::FromIntegrityLevel(DWORD integrity_level) {
  230. SID_IDENTIFIER_AUTHORITY package_authority = {
  231. SECURITY_MANDATORY_LABEL_AUTHORITY};
  232. return FromSubAuthorities(&package_authority, 1, &integrity_level);
  233. }
  234. absl::optional<std::vector<Sid>> Sid::FromSddlStringVector(
  235. const std::vector<const wchar_t*>& sddl_sids) {
  236. return FromVector(sddl_sids, Sid::FromSddlString);
  237. }
  238. absl::optional<std::vector<Sid>> Sid::FromNamedCapabilityVector(
  239. const std::vector<const wchar_t*>& capability_names) {
  240. return FromVector(capability_names, Sid::FromNamedCapability);
  241. }
  242. absl::optional<std::vector<Sid>> Sid::FromKnownCapabilityVector(
  243. const std::vector<WellKnownCapability>& capabilities) {
  244. return FromVector(capabilities, Sid::FromKnownCapability);
  245. }
  246. absl::optional<std::vector<Sid>> Sid::FromKnownSidVector(
  247. const std::vector<WellKnownSid>& sids) {
  248. return FromVector(sids, Sid::FromKnownSid);
  249. }
  250. Sid::Sid(Sid&& sid) = default;
  251. Sid& Sid::operator=(Sid&&) = default;
  252. Sid::~Sid() = default;
  253. PSID Sid::GetPSID() const {
  254. DCHECK(!sid_.empty());
  255. return const_cast<char*>(sid_.data());
  256. }
  257. // Converts the SID to an SDDL format string.
  258. absl::optional<std::wstring> Sid::ToSddlString() const {
  259. LPWSTR sid = nullptr;
  260. if (!::ConvertSidToStringSid(GetPSID(), &sid))
  261. return absl::nullopt;
  262. return TakeLocalAlloc(sid).get();
  263. }
  264. Sid Sid::Clone() const {
  265. return Sid(sid_.data(), sid_.size());
  266. }
  267. bool Sid::Equal(PSID sid) const {
  268. return !!::EqualSid(GetPSID(), sid);
  269. }
  270. bool Sid::operator==(const Sid& sid) const {
  271. return Equal(sid.GetPSID());
  272. }
  273. bool Sid::operator!=(const Sid& sid) const {
  274. return !(operator==(sid));
  275. }
  276. } // namespace win
  277. } // namespace base